├── .editorconfig ├── .envrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 1-bug-report.yml │ ├── 2-feature-request.yml │ └── config.yml └── workflows │ └── nightly-release.yml ├── .gitignore ├── .prettierignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── DONATE.md ├── LICENSE ├── PRIVACY.md ├── README.md ├── SECURITY.md ├── build ├── addon.js ├── all.js ├── changelog.js ├── copy.js ├── html.js ├── release-nightly.js ├── release-notes.js ├── scripts.js ├── styles.js ├── utils.js └── webext.run.js ├── devenv.nix ├── docs ├── AMO │ ├── description.en.xml │ └── summary.en.txt ├── assets │ ├── readme-logo.svg │ ├── screenshot-002.png │ ├── screenshot-003.png │ ├── screenshot-005.png │ ├── screenshot-009.png │ └── screenshot-011.png └── wiki │ ├── Firefox-Styles-Snippets-(via-userChrome.css).md │ ├── Home.md │ ├── Sidebery-Styles-Snippets.md │ └── assets │ ├── GNOME-Theme.png │ ├── containers-icons.1.png │ ├── dynamic-native-tabs.gif │ ├── tabs-favs-right.png │ ├── tabs-multiline-titles.png │ └── vert-nav-labels.png ├── eslint.config.mjs ├── flake.lock ├── flake.nix ├── package-lock.json ├── package.json ├── src ├── _locales │ ├── dict.browser.json │ ├── dict.common.ts │ ├── dict.setup-page.ts │ └── dict.sidebar.ts ├── assets │ ├── add-tabs-panel.svg │ ├── archive.svg │ ├── arrow-down.svg │ ├── bell.svg │ ├── book.svg │ ├── bookmark-badge.svg │ ├── bookmarks-add.svg │ ├── bookmarks-badge.svg │ ├── bookmarks.svg │ ├── books.svg │ ├── briefcase.svg │ ├── calendar-2.svg │ ├── calendar-graph.svg │ ├── calendar-list.svg │ ├── calendar.svg │ ├── cart.svg │ ├── chill.svg │ ├── circle-o.svg │ ├── circle.svg │ ├── clipboard.svg │ ├── clock-arrow.svg │ ├── clock-list.svg │ ├── clock.svg │ ├── close-other-tabs.svg │ ├── close-tabs-above.svg │ ├── close-tabs-below.svg │ ├── close.svg │ ├── code.svg │ ├── coffee.svg │ ├── collapse-all.svg │ ├── cookie.svg │ ├── copy-badge.svg │ ├── create-bookmark.svg │ ├── create-folder.svg │ ├── create-separator.svg │ ├── ctr-exclude.svg │ ├── ctr-include.svg │ ├── dedup-tabs.svg │ ├── default-container.svg │ ├── developer.svg │ ├── discard.svg │ ├── dollar.svg │ ├── download-archive.svg │ ├── download-copy.svg │ ├── download-in-progress.svg │ ├── dropper.svg │ ├── duplicate.svg │ ├── edit.svg │ ├── edu.svg │ ├── ellipsis.svg │ ├── excl-12.svg │ ├── excl.svg │ ├── expand.svg │ ├── favicon-addons.svg │ ├── favicon-amo.svg │ ├── favicon-dashboard.svg │ ├── favicon-file.svg │ ├── favicon-group.svg │ ├── favicon-img.svg │ ├── favicon-jpg.svg │ ├── favicon-link.svg │ ├── favicon-music.svg │ ├── favicon-pdf.svg │ ├── favicon-perf.svg │ ├── favicon-png.svg │ ├── favicon-pref.svg │ ├── favicon-vid.svg │ ├── fence.svg │ ├── fingerprint.svg │ ├── firefox-min.svg │ ├── firefox.svg │ ├── flask.svg │ ├── flatten.svg │ ├── folder-open.svg │ ├── folder.svg │ ├── food.svg │ ├── fruit.svg │ ├── gamepad.svg │ ├── gift.svg │ ├── github.svg │ ├── group-page-favicon.svg │ ├── group-tabs.svg │ ├── hide.svg │ ├── home.svg │ ├── hourglass.svg │ ├── inf.svg │ ├── link.svg │ ├── load.svg │ ├── lock.svg │ ├── logo-native-dark.svg │ ├── logo-native-light.svg │ ├── logo-native.svg │ ├── logo.svg │ ├── loud-badge.svg │ ├── loud.svg │ ├── mail.svg │ ├── man.svg │ ├── move-badge.svg │ ├── move-out-badge.svg │ ├── move-to-new-normal-window.svg │ ├── move-to-new-private-window.svg │ ├── move-to-normal-window.svg │ ├── move-to-normal-windows.svg │ ├── move-to-private-window.svg │ ├── move-to-private-windows.svg │ ├── move.svg │ ├── mute-badge.svg │ ├── mute.svg │ ├── new-container.svg │ ├── new-folder.svg │ ├── new-inline.svg │ ├── new-private-window.svg │ ├── new-window.svg │ ├── none.svg │ ├── ok-12.svg │ ├── ok.svg │ ├── panel-config.svg │ ├── paste.svg │ ├── path-copy.svg │ ├── path.svg │ ├── pause-12.svg │ ├── pause.svg │ ├── pet.svg │ ├── pin.svg │ ├── play.svg │ ├── plus-b.svg │ ├── plus-badge.svg │ ├── plus-f.svg │ ├── plus-s.svg │ ├── plus-thin.svg │ ├── plus.svg │ ├── private-window.svg │ ├── proxy-native.svg │ ├── proxy-off.svg │ ├── proxy.svg │ ├── reload.svg │ ├── remove-branch.svg │ ├── remove-descendants.svg │ ├── remove.svg │ ├── reopen-in-new-normal-window.svg │ ├── reopen-in-new-private-window.svg │ ├── reopen-in-normal-window.svg │ ├── reopen-in-normal-windows.svg │ ├── reopen-in-private-window.svg │ ├── reopen-in-private-windows.svg │ ├── reopen.svg │ ├── restore-tabs.svg │ ├── save-as-pdf.svg │ ├── save-tabs.svg │ ├── search.svg │ ├── sel-all.svg │ ├── settings.svg │ ├── sidebery.svg │ ├── snapshot-native.svg │ ├── snapshot.svg │ ├── sort-name-asc.svg │ ├── sort-name-des.svg │ ├── sort-time-asc.svg │ ├── sort-time-des.svg │ ├── sort-url-asc.svg │ ├── sort-url-des.svg │ ├── star-add.svg │ ├── star.svg │ ├── stats.svg │ ├── stop-12.svg │ ├── stop.svg │ ├── sync.svg │ ├── tab.svg │ ├── tabs-badge.svg │ ├── tabs.svg │ ├── tags.svg │ ├── title.svg │ ├── trash.svg │ ├── tree-struct.svg │ ├── tree.svg │ ├── undo.svg │ ├── url-conf.svg │ ├── url.svg │ ├── vacation.svg │ ├── warn.svg │ ├── web-copy.svg │ ├── web.svg │ ├── window.svg │ ├── x.svg │ ├── zoom-in.svg │ └── zoom-out.svg ├── bg │ ├── background.html │ └── background.ts ├── components │ ├── bookmark-node.vue │ ├── count-field.vue │ ├── drop-down-button.vue │ ├── icon-select-field.vue │ ├── icon-select-input.vue │ ├── info-field.vue │ ├── loading-dots.vue │ ├── num-field.vue │ ├── popup.bookmarks.vue │ ├── popup.dialog.vue │ ├── popup.new-tab-shortcuts.vue │ ├── popup.site-config.vue │ ├── popup.tab-move-rules.vue │ ├── popup.tab-reopen-rules.vue │ ├── scroll-box.vue │ ├── select-field.vue │ ├── select-input.vue │ ├── style-field.vue │ ├── text-field.vue │ ├── text-input.vue │ ├── toggle-field.vue │ └── toggle-input.vue ├── defaults.ts ├── defaults │ ├── containers.ts │ ├── menu.ts │ ├── panels.ts │ └── settings.ts ├── dict.ts ├── injections │ ├── check-paused-media.ts │ ├── group.ipc.ts │ ├── group.styles.ts │ ├── group.ts │ ├── pause-media.ts │ ├── play-media.ts │ ├── tab-preview.ts │ └── url.ts ├── manifest.json ├── page.group │ └── group.html ├── page.setup │ ├── components │ │ ├── footer-section.vue │ │ ├── keybindings.keybinding.vue │ │ ├── keybindings.vue │ │ ├── menu-editor.option.vue │ │ ├── menu-editor.vue │ │ ├── popup.container-config.vue │ │ ├── popup.export-config.vue │ │ ├── popup.import-config.vue │ │ ├── popup.panel-config.vue │ │ ├── popup.permissions.vue │ │ ├── settings.appearance.vue │ │ ├── settings.bookmarks.vue │ │ ├── settings.containers.vue │ │ ├── settings.details.vue │ │ ├── settings.dnd.vue │ │ ├── settings.general.vue │ │ ├── settings.group.vue │ │ ├── settings.help.vue │ │ ├── settings.history.vue │ │ ├── settings.menu.vue │ │ ├── settings.mouse.vue │ │ ├── settings.navbar.vue │ │ ├── settings.search.vue │ │ ├── settings.snapshots.vue │ │ ├── settings.sync.vue │ │ ├── settings.tabs.vue │ │ ├── settings.vue │ │ ├── snapshots.tab.vue │ │ ├── snapshots.vue │ │ ├── storage.vue │ │ └── styles-editor.vue │ ├── setup.html │ ├── setup.ts │ └── setup.vue ├── page.url │ └── url.html ├── popup.editing │ ├── editing.html │ └── editing.ts ├── popup.panel-config │ ├── panel-config.html │ ├── panel-config.ts │ └── panel-config.vue ├── popup.proxy │ ├── proxy.html │ └── proxy.ts ├── popup.search │ ├── search.html │ └── search.ts ├── popup.sync │ ├── sync.html │ ├── sync.ts │ └── sync.vue ├── popup.tab-preview │ ├── tab-preview.html │ └── tab-preview.ts ├── services │ ├── _services.bg.ts │ ├── _services.fg.ts │ ├── _services.ts │ ├── bookmarks.actions.ts │ ├── bookmarks.handlers.ts │ ├── bookmarks.ts │ ├── containers.actions.ts │ ├── containers.handlers.ts │ ├── containers.ts │ ├── drag-and-drop.actions.ts │ ├── drag-and-drop.ts │ ├── favicons.bg.ts │ ├── favicons.fg.ts │ ├── favicons.ts │ ├── google.drive.ts │ ├── google.ts │ ├── history.actions.ts │ ├── history.ts │ ├── info.actions.ts │ ├── info.ts │ ├── ipc.ts │ ├── keybindings.actions.ts │ ├── keybindings.ts │ ├── logs.ts │ ├── menu.actions.ts │ ├── menu.options.bookmarks.ts │ ├── menu.options.history.ts │ ├── menu.options.tabs.ts │ ├── menu.options.ts │ ├── menu.ts │ ├── mouse.actions.ts │ ├── mouse.ts │ ├── notifications.ts │ ├── permissions.actions.ts │ ├── permissions.ts │ ├── popups.ts │ ├── search.actions.ts │ ├── search.bookmarks.ts │ ├── search.history.ts │ ├── search.tabs.ts │ ├── search.ts │ ├── selection.ts │ ├── settings.actions.ts │ ├── settings.ts │ ├── setup-page.actions.ts │ ├── setup-page.ts │ ├── sidebar-config.ts │ ├── sidebar.actions.ts │ ├── sidebar.ts │ ├── snapshots.actions.ts │ ├── snapshots.ts │ ├── storage.ts │ ├── styles.actions.ts │ ├── styles.ts │ ├── sync.firefox.ts │ ├── sync.google.ts │ ├── sync.ts │ ├── tabs.bg.actions.ts │ ├── tabs.bg.ts │ ├── tabs.fg.actions.ts │ ├── tabs.fg.colors.ts │ ├── tabs.fg.create.ts │ ├── tabs.fg.edit-title.ts │ ├── tabs.fg.groups.ts │ ├── tabs.fg.handlers.ts │ ├── tabs.fg.media.ts │ ├── tabs.fg.move.ts │ ├── tabs.fg.rm.ts │ ├── tabs.fg.scroll.ts │ ├── tabs.fg.shadow.ts │ ├── tabs.fg.sorting.ts │ ├── tabs.fg.sync.ts │ ├── tabs.fg.ts │ ├── tabs.preview.ts │ ├── web-req.actions.ts │ ├── web-req.fg.ts │ ├── web-req.ts │ ├── windows.actions.ts │ ├── windows.handlers.ts │ └── windows.ts ├── sidebar │ ├── components │ │ ├── animated-tab-list.vue │ │ ├── bar.navigation.vue │ │ ├── bar.new-tab.vue │ │ ├── bar.panel-view-switcher.vue │ │ ├── bar.pinned-tabs.vue │ │ ├── bar.search.vue │ │ ├── bookmark-card.vue │ │ ├── dnd-pointer.vue │ │ ├── dnd-tooltip.vue │ │ ├── history-item.vue │ │ ├── nav-item.vue │ │ ├── panel-placeholder.vue │ │ ├── panel.bookmarks.vue │ │ ├── panel.history.vue │ │ ├── panel.sync.entry.vue │ │ ├── panel.sync.vue │ │ ├── panel.tabs.vue │ │ ├── popup.confirm.vue │ │ ├── popup.container-config.vue │ │ ├── popup.context-menu.vue │ │ ├── popup.group-config.vue │ │ ├── popup.notification.vue │ │ ├── popup.notifications.vue │ │ ├── popup.panel-config.vue │ │ ├── popup.windows.vue │ │ ├── sub-list-title.vue │ │ ├── sub-panel.bookmarks.vue │ │ ├── sub-panel.closed-tabs.vue │ │ ├── sub-panel.vue │ │ └── tab.vue │ ├── sidebar.html │ ├── sidebar.ts │ └── sidebar.vue ├── styles │ ├── themes │ │ └── proton │ │ │ ├── animations.styl │ │ │ ├── btn.styl │ │ │ ├── inputs.styl │ │ │ ├── page.group │ │ │ └── group.styl │ │ │ ├── page.setup │ │ │ ├── menu-editor.styl │ │ │ ├── popup.config.styl │ │ │ ├── settings.details-box.styl │ │ │ ├── settings.keybindings.styl │ │ │ ├── settings.note-field.styl │ │ │ ├── settings.permissions.styl │ │ │ ├── settings.popup.styl │ │ │ ├── settings.storage.styl │ │ │ ├── settings.styl │ │ │ ├── settings.sync.styl │ │ │ ├── setup.styl │ │ │ ├── snapshots.styl │ │ │ └── styles-editor.styl │ │ │ ├── page.url │ │ │ └── url.styl │ │ │ ├── popup.panel-config │ │ │ └── panel-config.styl │ │ │ ├── popup.proxy │ │ │ └── proxy.styl │ │ │ ├── popup.sync │ │ │ └── sync.styl │ │ │ ├── sidebar │ │ │ ├── bar.navigation.styl │ │ │ ├── bar.panel-view-switcher.styl │ │ │ ├── bar.pinned-tabs.styl │ │ │ ├── bar.search.styl │ │ │ ├── bookmark-card.styl │ │ │ ├── bookmark-node.styl │ │ │ ├── loading-dots.styl │ │ │ ├── panel-placeholder.styl │ │ │ ├── panel.bookmarks.styl │ │ │ ├── panel.history.styl │ │ │ ├── panel.sync.entry.styl │ │ │ ├── panel.sync.styl │ │ │ ├── panel.tabs.styl │ │ │ ├── popup.bookmarks.styl │ │ │ ├── popup.confirm.styl │ │ │ ├── popup.container-config.styl │ │ │ ├── popup.context-menu.styl │ │ │ ├── popup.dialog.styl │ │ │ ├── popup.group-config.styl │ │ │ ├── popup.new-tab-shortcuts.styl │ │ │ ├── popup.notifications.styl │ │ │ ├── popup.panel-config.styl │ │ │ ├── popup.site-config.styl │ │ │ ├── popup.styl │ │ │ ├── popup.tab-move-rules.styl │ │ │ ├── popup.tab-reopen-rules.styl │ │ │ ├── popup.windows.styl │ │ │ ├── scroll-box.styl │ │ │ ├── sidebar.styl │ │ │ ├── sub-list-title.styl │ │ │ ├── sub-panel.bookmarks.styl │ │ │ ├── sub-panel.closed-tabs.styl │ │ │ ├── sub-panel.styl │ │ │ └── tab.styl │ │ │ └── vars.styl │ └── utils.styl ├── types.ts ├── types │ ├── bookmarks.ts │ ├── containers.ts │ ├── globals.d.ts │ ├── history.ts │ ├── ipc.ts │ ├── menu.ts │ ├── settings.ts │ ├── sidebar.ts │ ├── snapshots.ts │ ├── storage.ts │ ├── styles.ts │ ├── tabs.ts │ ├── vue-shims.d.ts │ ├── web-ext.d.ts │ └── windows.ts └── utils.ts ├── test ├── env-setup.js └── web-ext-setup.js ├── tsconfig.json └── updates.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" 3 | fi 4 | 5 | nix_direnv_watch_file devenv.nix 6 | #nix_direnv_watch_file devenv.lock 7 | #nix_direnv_watch_file devenv.yaml 8 | 9 | if ! use flake . --impure 10 | then 11 | echo "devenv could not be build. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2 12 | fi 13 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://github.com/mbnuqw/sidebery/blob/v5/DONATE.md"] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | labels: [] 4 | projects: [] 5 | body: 6 | - type: textarea 7 | id: repro 8 | attributes: 9 | label: Steps to reproduce 10 | description: | 11 | Include all steps needed to reproduce this bug, e.g.: Installing other addons, changing browser settings, changing `about:config` properties, changing Sidebery settings, etc... 12 | [How to open Firefox in a new profile](https://support.mozilla.org/en-US/kb/profile-manager-create-remove-switch-firefox-profiles) 13 | value: | 14 | - Open Firefox in a new profile 15 | - Install Sidebery 16 | - 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: actual 21 | attributes: 22 | label: Actual behavior 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: expected 27 | attributes: 28 | label: Expected behavior 29 | validations: 30 | required: true 31 | - type: input 32 | attributes: 33 | label: System 34 | description: "Name, version; e.g.: Windows 11, Manjaro Plasma 6.0 (Wayland) or macOS 14.4" 35 | validations: 36 | required: true 37 | - type: input 38 | attributes: 39 | label: Firefox version 40 | validations: 41 | required: true 42 | - type: input 43 | attributes: 44 | label: Sidebery version 45 | description: "To find it, open `about:addons`, click on Sidebery and check `version` field" 46 | validations: 47 | required: true 48 | - type: textarea 49 | id: logs 50 | attributes: 51 | label: Logs 52 | description: | 53 | - Open DevTools (open this url in new tab: `about:devtools-toolbox?id=%7B3c078156-979c-498b-8990-85f7987dd929%7D&type=extension`). 54 | - Navigate to `console` tab. 55 | - Click on the trash bin icon (at the top-left) to clear console. 56 | - Then try to reproduce the issue. 57 | - If messages appear, copy and paste them here inside this codeblock, replacing this text. 58 | render: code 59 | validations: 60 | required: false 61 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Request a feature 3 | labels: [] 4 | projects: [] 5 | body: 6 | - type: textarea 7 | id: desc 8 | attributes: 9 | label: Description 10 | description: | 11 | Note: Issue containing two or more unrelated feature requests will be closed. If you have a question, use [discussions](https://github.com/mbnuqw/sidebery/discussions). 12 | validations: 13 | required: true 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Question 4 | url: https://github.com/mbnuqw/sidebery/discussions 5 | about: Ask a question. 6 | -------------------------------------------------------------------------------- /.github/workflows/nightly-release.yml: -------------------------------------------------------------------------------- 1 | name: nightly-release 2 | 3 | on: 4 | workflow_dispatch 5 | 6 | jobs: 7 | build-and-sign: 8 | runs-on: ubuntu-latest 9 | env: 10 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 11 | WEB_EXT_API_KEY: ${{ secrets.WEB_EXT_API_KEY }} 12 | WEB_EXT_API_SECRET: ${{ secrets.WEB_EXT_API_SECRET }} 13 | steps: 14 | - name: Check out the repository to the runner 15 | uses: actions/checkout@v4 16 | with: 17 | ref: 'v5' 18 | fetch-depth: 0 19 | - name: Setup nodejs 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: lts/* 23 | - name: Configure git 24 | run: | 25 | git config --global user.name 'GitHub Action Bot' 26 | git config --global user.email 'mbnuqw@users.noreply.github.com' 27 | - name: Build and sign 28 | run: | 29 | npm install 30 | npm run release.nightly 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | .vscode 3 | dist 4 | node_modules 5 | coverage 6 | addon 7 | build/* 8 | !build/*.js 9 | !build/*.mjs 10 | /.devenv/ 11 | /.direnv/ 12 | .idea -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.test.js 2 | *.html -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for your interest in contributing to this project! Here you can find options to help maintain and develop Sidebery. 4 | 5 | 6 | ## Discussions 7 | 8 | You can ask/answer a question or start a general discussion related to Sidebery. 9 | 10 | 11 | ## Issues 12 | 13 | You can open an issue to report a bug or request a feature. Note that the more detailed you describe the steps to reproduce the bug (even if you think they are obvious), the faster I can reproduce it and fix it. 14 | 15 | 16 | ## Pull Requests 17 | 18 | You can open a PR to fix a bug, change/create translation or add a new feature. A PR that address multiple bugs/feature requests at once will be closed. It may take some time to review changes, so thank you in advance for your patience. 19 | 20 | ### Translations 21 | 22 | To edit/add translation: 23 | - Open a dictionary file in `https://github.com/mbnuqw/sidebery/blob/v5/src/_locales` 24 | - Click on a pencil icon to edit the file. 25 | - Make some changes, e.g.: 26 | ```ts 27 | // Edit string value 28 | 'some.label.id': { 29 | en: 'Value to edit', 30 | }, 31 | 32 | // Edit translation with the countable value in context 33 | 'some.label.id': { 34 | en: n => (n === 1 ? 'One' : 'Not one'), 35 | }, 36 | 'some.label.id': { 37 | en: n => { 38 | if (n === 0) return 'None' 39 | if (n < 5) return 'Less than five' 40 | if (n === 5) return 'Five' 41 | return 'More than five' 42 | }, 43 | } 44 | 45 | // Add new translations 46 | 'some.label.id': { 47 | en: 'Color', 48 | en_GB: 'Colour', 49 | fr: 'Couleur', 50 | }, 51 | ``` 52 | - Create pull request. 53 | 54 | All languages are optional and the fallback mechanism is (if user has the `pt_BR` UI language): 55 | `pt_BR` > `pt` > `en` > `label ID`. 56 | 57 | 58 | ## Donate 59 | 60 | You can also [donate to this project](./DONATE.md). 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 mbnuqw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE -------------------------------------------------------------------------------- /PRIVACY.md: -------------------------------------------------------------------------------- 1 | # Privacy Policy 2 | - Sidebery does not engage in ad targeting, data collection, or other activities that could compromise your privacy. 3 | - By default, all data is stored locally on your machine. 4 | - Sidebery sends data only when synchronization is enabled and only to chosen provider. 5 | - You can optionally enable one or more synchronization providers (third-party services) to sync your data across multiple devices. 6 | 7 | ## Synchronization providers 8 | - Firefox Sync privacy policy: https://www.mozilla.org/en-US/privacy/firefox/#sync 9 | - Google Drive privacy policy: https://policies.google.com/privacy 10 | 11 | ## Synchronized data 12 | You can choose what data will be synchronized (hence, sent to a third-party provider): 13 | - Sidebery settings 14 | - Sidebery context menu config 15 | - Sidebery keybindings 16 | - Custom styles for Sidebery 17 | - Selected tabs: 18 | - Data that will be sent: Title, URL, site icon, container configs, custom color/title + technical data. 19 | - You can check what data is used [here](https://github.com/mbnuqw/sidebery/blob/v5/src/services/tabs.fg.sync.ts). 20 | 21 | ## Email 22 | 23 | If you email the developer for support or other feedback, the emails with email addresses will be retained for quality assurance purposes. The email addresses will be used only to reply to the concerns or suggestions raised and will never be used for any marketing purpose. 24 | 25 | ## Feedback 26 | 27 | If you have any questions regarding this privacy policy, you can create a [Discussion](https://github.com/mbnuqw/sidebery/discussions/new/choose) or email me (maxbadryzlov@gmail.com). 28 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Latest version published on addons.mozilla.org. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | email: maxbadryzlov@gmail.com 10 | -------------------------------------------------------------------------------- /build/all.js: -------------------------------------------------------------------------------- 1 | import './copy.js' 2 | import './html.js' 3 | import './styles.js' 4 | import './scripts.js' 5 | -------------------------------------------------------------------------------- /build/webext.run.js: -------------------------------------------------------------------------------- 1 | import webExt from 'web-ext' 2 | import fs from 'node:fs' 3 | import path from 'node:path' 4 | import { ADDON_PATH } from './utils.js' 5 | 6 | let lastArg = process.argv[process.argv.length - 1] 7 | if (!lastArg || lastArg.startsWith('-')) lastArg = 'firefox' 8 | 9 | const IS_FF = lastArg.includes('irefox') || lastArg.includes('loorp') || lastArg.includes('zen') 10 | const cliOpts = { 11 | target: IS_FF ? 'firefox-desktop' : 'chromium', 12 | sourceDir: ADDON_PATH, 13 | keepProfileChanges: true, 14 | } 15 | 16 | async function main() { 17 | if (IS_FF) { 18 | cliOpts.firefox = lastArg 19 | cliOpts.firefoxProfile = './build/profile-' + path.basename(lastArg).split(".")[0] 20 | await fs.promises.mkdir(cliOpts.firefoxProfile, { recursive: true }) 21 | } else { 22 | cliOpts.chromiumBinary = lastArg 23 | cliOpts.chromiumProfile = './build/profile-' + path.basename(lastArg).split(".")[0] 24 | await fs.promises.mkdir(cliOpts.chromiumProfile, { recursive: true }) 25 | } 26 | 27 | webExt.cmd.run(cliOpts, { shouldExitProgram: true }) 28 | } 29 | main() 30 | -------------------------------------------------------------------------------- /devenv.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: { 2 | # https://devenv.sh/reference/options/ 3 | # ! not maintained by @mbnuqw - report issues here: https://github.com/onezoomin/sidebery/issues 4 | 5 | languages.javascript = { 6 | enable = true; # adds node LTS & npm 7 | # package = pkgs.nodejs-18_x; <- if you need to override npm version 8 | }; 9 | 10 | packages = with pkgs; [ 11 | # Add packages here - search: https://search.nixos.org/packages?channel=unstable&query= 12 | #gcc 13 | #nodePackages.pnpm 14 | ]; 15 | } 16 | -------------------------------------------------------------------------------- /docs/AMO/summary.en.txt: -------------------------------------------------------------------------------- 1 | Tabs tree, bookmarks and history in a highly configurable sidebar. -------------------------------------------------------------------------------- /docs/assets/screenshot-002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/assets/screenshot-002.png -------------------------------------------------------------------------------- /docs/assets/screenshot-003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/assets/screenshot-003.png -------------------------------------------------------------------------------- /docs/assets/screenshot-005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/assets/screenshot-005.png -------------------------------------------------------------------------------- /docs/assets/screenshot-009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/assets/screenshot-009.png -------------------------------------------------------------------------------- /docs/assets/screenshot-011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/assets/screenshot-011.png -------------------------------------------------------------------------------- /docs/wiki/Home.md: -------------------------------------------------------------------------------- 1 | ## Contents: 2 | - [Firefox Styles Snippets (via userChrome.css)](https://github.com/mbnuqw/sidebery/wiki/Firefox-Styles-Snippets-(via-userChrome.css)) 3 | - [Completely hide native tabs strip](https://github.com/mbnuqw/sidebery/wiki/Firefox-Styles-Snippets-(via-userChrome.css)#completely-hide-native-tabs-strip) 4 | - [Decrease size of the sidebar header](https://github.com/mbnuqw/sidebery/wiki/Firefox-Styles-Snippets-(via-userChrome.css)#decrease-size-of-the-sidebar-header) 5 | - [Dynamic native tabs](https://github.com/mbnuqw/sidebery/wiki/Firefox-Styles-Snippets-(via-userChrome.css)#dynamic-native-tabs) 6 | - [Native gnome look (by @Fletcher-Alderton)](https://github.com/mbnuqw/sidebery/wiki/Firefox-Styles-Snippets-(via-userChrome.css)#native-gnome-look-by-fletcher-alderton) 7 | - [Sidebery Styles Snippets](https://github.com/mbnuqw/sidebery/wiki/Sidebery-Styles-Snippets) 8 | - [Tab Favicons on the Right](https://github.com/mbnuqw/sidebery/wiki/Sidebery-Styles-Snippets#tab-favicons-on-the-right) 9 | - [Tabs multiline titles](https://github.com/mbnuqw/sidebery/wiki/Sidebery-Styles-Snippets#tabs-multiline-titles) 10 | - [Vertical panel labels](https://github.com/mbnuqw/sidebery/wiki/Sidebery-Styles-Snippets#vertical-panel-labels) 11 | -------------------------------------------------------------------------------- /docs/wiki/assets/GNOME-Theme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/wiki/assets/GNOME-Theme.png -------------------------------------------------------------------------------- /docs/wiki/assets/containers-icons.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/wiki/assets/containers-icons.1.png -------------------------------------------------------------------------------- /docs/wiki/assets/dynamic-native-tabs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/wiki/assets/dynamic-native-tabs.gif -------------------------------------------------------------------------------- /docs/wiki/assets/tabs-favs-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/wiki/assets/tabs-favs-right.png -------------------------------------------------------------------------------- /docs/wiki/assets/tabs-multiline-titles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/wiki/assets/tabs-multiline-titles.png -------------------------------------------------------------------------------- /docs/wiki/assets/vert-nav-labels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/docs/wiki/assets/vert-nav-labels.png -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | # Basically boilerplate - generated from: https://github.com/cachix/devenv/tree/main/templates 3 | # ! not maintained by @mbnuqw - report issues here: https://github.com/onezoomin/sidebery/issues 4 | 5 | inputs = { 6 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11"; 7 | systems.url = "github:nix-systems/default"; 8 | devenv.url = "github:cachix/devenv"; 9 | }; 10 | 11 | nixConfig = { 12 | extra-substituters = [ "https://devenv.cachix.org" ]; 13 | extra-trusted-public-keys = [ "devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw=" ]; 14 | }; 15 | 16 | outputs = { self, nixpkgs, devenv, systems, ... } @ inputs: 17 | let 18 | forEachSystem = nixpkgs.lib.genAttrs (import systems); 19 | in 20 | { 21 | devShells = forEachSystem (system: 22 | let 23 | pkgs = nixpkgs.legacyPackages.${system}; 24 | in 25 | { 26 | default = devenv.lib.mkShell { 27 | inherit inputs pkgs; 28 | modules = [ 29 | (import ./devenv.nix { inherit pkgs inputs; }) 30 | ]; 31 | }; 32 | }); 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /src/assets/add-tabs-panel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/archive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/arrow-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/bell.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/book.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/bookmark-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/bookmarks-add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/bookmarks-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/bookmarks.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/books.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/briefcase.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/calendar-2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/calendar-graph.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/calendar-list.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/cart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/chill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/circle-o.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/circle.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/clipboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/clock-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/clock-list.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/assets/clock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/close-other-tabs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/close-tabs-above.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/close-tabs-below.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/coffee.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/collapse-all.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/copy-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/create-bookmark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/create-folder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/create-separator.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/ctr-exclude.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/ctr-include.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/dedup-tabs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/default-container.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/developer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/discard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/dollar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/download-archive.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/download-copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/download-in-progress.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/dropper.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/duplicate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/edu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/ellipsis.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/excl-12.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/excl.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/expand.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-addons.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-amo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-dashboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-file.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-group.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-img.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-jpg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-music.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-perf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-png.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-pref.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/favicon-vid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/fence.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/fingerprint.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/firefox-min.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/firefox.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/flask.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/flatten.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/folder-open.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/folder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/food.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/fruit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/gamepad.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/gift.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/group-page-favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/group-tabs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/hide.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/hourglass.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/inf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/load.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/lock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/logo-native-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/logo-native-light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/logo-native.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/loud-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/loud.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/mail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/man.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-out-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-to-new-normal-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-to-new-private-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-to-normal-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-to-normal-windows.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-to-private-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move-to-private-windows.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/move.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/mute-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/mute.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/new-container.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/new-folder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/new-inline.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/new-private-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/new-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/none.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/ok-12.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/ok.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/panel-config.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/paste.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/path-copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/path.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/pause-12.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/pause.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/pet.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/pin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/plus-b.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/plus-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/plus-f.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/plus-s.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/plus-thin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/private-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/proxy-native.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/proxy-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/proxy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/remove-branch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/remove-descendants.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/remove.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen-in-new-normal-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen-in-new-private-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen-in-normal-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen-in-normal-windows.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen-in-private-window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen-in-private-windows.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/reopen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/restore-tabs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/save-as-pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/save-tabs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sel-all.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sidebery.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/snapshot-native.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/snapshot.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sort-name-asc.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sort-name-des.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sort-time-asc.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sort-time-des.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sort-url-asc.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sort-url-des.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/star-add.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/stats.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/stop-12.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/stop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/sync.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tabs-badge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tabs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tags.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/title.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/trash.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tree-struct.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tree.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/undo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/url-conf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/url.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/vacation.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/warn.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/web-copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/web.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/window.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/x.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/zoom-in.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/zoom-out.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/bg/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 |
15 |
16 | 17 | -------------------------------------------------------------------------------- /src/components/count-field.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 53 | -------------------------------------------------------------------------------- /src/components/icon-select-field.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /src/components/icon-select-input.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 19 | -------------------------------------------------------------------------------- /src/components/info-field.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | -------------------------------------------------------------------------------- /src/components/loading-dots.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /src/components/text-field.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 71 | -------------------------------------------------------------------------------- /src/components/toggle-input.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 26 | -------------------------------------------------------------------------------- /src/defaults/containers.ts: -------------------------------------------------------------------------------- 1 | import { Container } from '../types/containers' 2 | 3 | export const DEFAULT_CONTAINER: Container = { 4 | id: '', 5 | cookieStoreId: '', 6 | name: '', 7 | icon: 'fingerprint', 8 | color: 'blue', 9 | colorCode: '#37adff', 10 | proxified: false, 11 | proxy: null, 12 | reopenRulesActive: false, 13 | reopenRules: [], 14 | userAgentActive: false, 15 | userAgent: '', 16 | } 17 | 18 | export const DEFAULT_CONTAINER_ID = 'firefox-default' 19 | export const PRIVATE_CONTAINER_ID = 'firefox-private' 20 | export const CONTAINER_ID = browser.extension.inIncognitoContext 21 | ? PRIVATE_CONTAINER_ID 22 | : DEFAULT_CONTAINER_ID 23 | -------------------------------------------------------------------------------- /src/dict.ts: -------------------------------------------------------------------------------- 1 | const LANG_REG = browser.i18n.getUILanguage().replace('-', '_') 2 | export const LANG = LANG_REG.slice(0, 2) 3 | 4 | // Set dictionary 5 | const dict: Record = {} 6 | if (window.translations) { 7 | for (const key of Object.keys(window.translations)) { 8 | const prop = window.translations[key] 9 | dict[key] = prop[LANG_REG] ?? prop[LANG] ?? prop.en 10 | } 11 | } 12 | 13 | function isString(r: string | PlurFn): r is string { 14 | if (r.constructor === String) return true 15 | else return false 16 | } 17 | 18 | export function translate(id?: string, plurNum?: number | string): string { 19 | if (!id) return '' 20 | 21 | const record = dict[id] 22 | if (record === undefined) return id 23 | 24 | if (isString(record)) return record 25 | else return record(plurNum) 26 | } 27 | -------------------------------------------------------------------------------- /src/injections/check-paused-media.ts: -------------------------------------------------------------------------------- 1 | ;(function (): boolean { 2 | const audioEls = document.querySelectorAll('audio') 3 | const videoEls = document.querySelectorAll('video') 4 | 5 | let pausedElCount = 0 6 | 7 | if (audioEls && audioEls.length) { 8 | for (const el of audioEls) { 9 | if (el.currentTime === 0 || el.ended) continue 10 | if (el.paused && el.hasAttribute('data-sidebery-media-paused')) { 11 | pausedElCount++ 12 | } 13 | } 14 | } 15 | 16 | if (videoEls && videoEls.length) { 17 | for (const el of videoEls) { 18 | if (el.currentTime === 0 || el.ended) continue 19 | if (el.paused && el.hasAttribute('data-sidebery-media-paused')) { 20 | pausedElCount++ 21 | } 22 | } 23 | } 24 | 25 | return pausedElCount > 0 26 | })() 27 | -------------------------------------------------------------------------------- /src/injections/group.ipc.ts: -------------------------------------------------------------------------------- 1 | import { GroupedTabInfo, GroupPin } from 'src/types' 2 | 3 | export interface GroupMsg { 4 | index?: number 5 | len?: number 6 | windowId?: ID 7 | parentId?: ID 8 | title?: string 9 | tabs?: GroupedTabInfo[] 10 | pin?: GroupPin 11 | createdTab?: GroupedTabInfo 12 | updatedTab?: GroupedTabInfo 13 | removedTab?: ID 14 | } 15 | -------------------------------------------------------------------------------- /src/injections/group.styles.ts: -------------------------------------------------------------------------------- 1 | import { ParsedTheme, SrcVars } from 'src/services/styles' 2 | import { Stored } from 'src/types' 3 | import { toCSSVarName } from 'src/utils' 4 | 5 | export function applyThemeSrcVars(parsed: ParsedTheme, rootEl?: HTMLElement): void { 6 | if (!rootEl) rootEl = document.getElementById('root') ?? undefined 7 | if (!rootEl) return 8 | 9 | for (const prop of Object.keys(parsed.vars) as (keyof SrcVars)[]) { 10 | const value = parsed.vars[prop] 11 | 12 | if (value) { 13 | rootEl.style.setProperty(toCSSVarName('s_' + prop), value) 14 | } else { 15 | rootEl.style.removeProperty(toCSSVarName('s_' + prop)) 16 | } 17 | } 18 | } 19 | 20 | export async function loadCustomGroupCSS(): Promise { 21 | const stored = await browser.storage.local.get('groupCSS') 22 | applyCustomCSS(stored.groupCSS) 23 | } 24 | 25 | /** 26 | * Update custom css 27 | */ 28 | export function applyCustomCSS(css?: string | null): void { 29 | if (css === null || css === undefined) return 30 | 31 | // Find or create new style element 32 | let customStyleEl = document.getElementById('custom_css') as HTMLLinkElement 33 | if (!customStyleEl) { 34 | customStyleEl = document.createElement('style') as HTMLLinkElement 35 | customStyleEl.id = 'custom_css' 36 | customStyleEl.type = 'text/css' 37 | customStyleEl.rel = 'stylesheet' 38 | document.head.appendChild(customStyleEl) 39 | } else { 40 | // Remove old styles 41 | while (customStyleEl.lastChild) { 42 | customStyleEl.removeChild(customStyleEl.lastChild) 43 | } 44 | } 45 | 46 | // Apply css 47 | if (css) customStyleEl.appendChild(document.createTextNode(css)) 48 | } 49 | -------------------------------------------------------------------------------- /src/injections/pause-media.ts: -------------------------------------------------------------------------------- 1 | ;(function (): boolean { 2 | const audioEls = document.querySelectorAll('audio') 3 | const videoEls = document.querySelectorAll('video') 4 | 5 | const pausedEls: HTMLMediaElement[] = [] 6 | 7 | if (audioEls && audioEls.length) { 8 | for (const el of audioEls) { 9 | if (el.currentTime === 0 || el.ended) continue 10 | if (el.paused) { 11 | el.removeAttribute('data-sidebery-media-paused') 12 | continue 13 | } 14 | el.pause() 15 | pausedEls.push(el) 16 | } 17 | } 18 | 19 | if (videoEls && videoEls.length) { 20 | for (const el of videoEls) { 21 | if (el.currentTime === 0 || el.ended) continue 22 | if (el.paused) { 23 | el.removeAttribute('data-sidebery-media-paused') 24 | continue 25 | } 26 | el.pause() 27 | pausedEls.push(el) 28 | } 29 | } 30 | 31 | // Globaly store "ids" of paused elements and mark them 32 | for (const el of pausedEls) { 33 | el.setAttribute('data-sidebery-media-paused', 'true') 34 | } 35 | 36 | return pausedEls.length > 0 37 | })() 38 | -------------------------------------------------------------------------------- /src/injections/play-media.ts: -------------------------------------------------------------------------------- 1 | ;(function (): void { 2 | const audioEls = document.querySelectorAll('audio') 3 | const videoEls = document.querySelectorAll('video') 4 | 5 | if (audioEls && audioEls.length) { 6 | for (const el of audioEls) { 7 | if (!el.paused) continue 8 | const pausedBySidebery = el.getAttribute('data-sidebery-media-paused') 9 | if (pausedBySidebery) { 10 | el.removeAttribute('data-sidebery-media-paused') 11 | el.play() 12 | } 13 | } 14 | } 15 | 16 | if (videoEls && videoEls.length) { 17 | for (const el of videoEls) { 18 | if (!el.paused) continue 19 | const pausedBySidebery = el.getAttribute('data-sidebery-media-paused') 20 | if (pausedBySidebery) { 21 | el.removeAttribute('data-sidebery-media-paused') 22 | el.play() 23 | } 24 | } 25 | } 26 | })() 27 | -------------------------------------------------------------------------------- /src/page.setup/components/footer-section.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /src/page.setup/components/menu-editor.option.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 61 | -------------------------------------------------------------------------------- /src/page.setup/components/settings.group.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | -------------------------------------------------------------------------------- /src/page.setup/components/settings.history.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | -------------------------------------------------------------------------------- /src/page.setup/components/settings.search.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 45 | -------------------------------------------------------------------------------- /src/page.url/url.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | Unavailable URL 12 | 13 | 14 |
17 |
18 | 19 |

Unavailable URL

20 |

Sidebery is unable to open this link due to security-related restrictions of Firefox.

21 | 22 |
23 |

Title

24 |

25 |

Original URL

26 |

27 |
Copy URL
28 |
29 | 30 | -------------------------------------------------------------------------------- /src/popup.editing/editing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 53 | 54 | 55 |
58 |
59 | svg://src/assets/edit.svg#icon_edit 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/popup.proxy/proxy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sidebery Proxy 7 | 8 | 17 | 18 | 19 | 20 |
23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 |
Type
32 |
---
33 |
34 |
35 |
Host
36 |
---
37 |
38 |
39 |
Proxy DNS
40 |
---
41 |
42 |
43 |
44 |
IP
45 |
---
46 |
47 |
48 |
Country
49 |
---
50 |
51 | 52 |
53 |
54 |
Update ip info
55 |
56 |
57 |
Configure
58 |
59 |
60 |
61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/popup.search/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 48 | 49 | 50 |
53 |
54 | svg://src/assets/search.svg#icon_search 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/popup.sync/sync.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 |
17 |
18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 |
26 | svg://src/assets/firefox.svg#icon_ff 27 | svg://src/assets/favicon-group.svg#icon_group 28 | svg://src/assets/favicon-img.svg#icon_img 29 | svg://src/assets/favicon-vid.svg#icon_vid 30 | svg://src/assets/favicon-music.svg#icon_music 31 | svg://src/assets/favicon-file.svg#icon_local_file 32 | svg://src/assets/favicon-pref.svg#icon_pref 33 | svg://src/assets/favicon-addons.svg#icon_addons 34 | svg://src/assets/favicon-perf.svg#icon_perf 35 | svg://src/assets/favicon-link.svg#icon_link_favicon 36 | svg://src/assets/close.svg#icon_close 37 | svg://src/assets/sync.svg#icon_sync 38 | svg://src/assets/settings.svg#icon_settings 39 | svg://src/assets/code.svg#icon_code 40 | svg://src/assets/favicon-dashboard.svg#icon_dashboard 41 | svg://src/assets/developer.svg#icon_dev 42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /src/popup.sync/sync.ts: -------------------------------------------------------------------------------- 1 | import { createApp, reactive } from 'vue' 2 | import Root from './sync.vue' 3 | import { InstanceType } from 'src/types' 4 | import { Info } from 'src/services/info' 5 | import { IPC, Logs, Sync } from 'src/services/_services' 6 | import { Settings } from 'src/services/settings' 7 | import { Styles } from 'src/services/styles' 8 | import { Windows } from 'src/services/windows' 9 | import { Notifications } from 'src/services/notifications' 10 | 11 | async function main(): Promise { 12 | Info.setInstanceType(InstanceType.sync) 13 | IPC.setInstanceType(InstanceType.sync) 14 | Logs.setInstanceType(InstanceType.sync) 15 | 16 | Logs.info('Init start') 17 | 18 | Settings.state = reactive(Settings.state) 19 | Sync.initSync(reactive) 20 | Styles.reactive = reactive(Styles.reactive) 21 | Notifications.reactive = reactive(Notifications.reactive) 22 | 23 | await Promise.all([ 24 | Settings.loadSettings().then(() => { 25 | Styles.initColorScheme() 26 | Styles.updateGlobalFontSize() 27 | Styles.udpateGlobalFontFamily() 28 | }), 29 | Windows.loadWindowInfo(), 30 | ]) 31 | 32 | IPC.setWinId(Windows.id) 33 | Logs.setWinId(Windows.id) 34 | 35 | IPC.setupGlobalMessageListener() 36 | IPC.setupConnectionListener() 37 | 38 | const app = createApp(Root) 39 | app.mount('#root_container') 40 | 41 | await Sync.load() 42 | } 43 | main() 44 | -------------------------------------------------------------------------------- /src/popup.sync/sync.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 35 | -------------------------------------------------------------------------------- /src/services/_services.bg.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/sidebery/639a951abbd88efb2202e4f7e55556a1634958aa/src/services/_services.bg.ts -------------------------------------------------------------------------------- /src/services/_services.fg.ts: -------------------------------------------------------------------------------- 1 | export * as TabsSync from './tabs.fg.sync' 2 | export * as Favicons from './favicons.fg' 3 | -------------------------------------------------------------------------------- /src/services/_services.ts: -------------------------------------------------------------------------------- 1 | export * as Utils from '../utils' 2 | export * as Logs from './logs' 3 | export * as IPC from './ipc' 4 | export * as Google from './google' 5 | export * as Sync from './sync' 6 | export * as SidebarConfig from './sidebar-config' 7 | export * as Popups from './popups' 8 | -------------------------------------------------------------------------------- /src/services/bookmarks.ts: -------------------------------------------------------------------------------- 1 | import { Bookmark } from 'src/types' 2 | import * as BookmarksActions from 'src/services/bookmarks.actions' 3 | import * as BookmarksHandlers from 'src/services/bookmarks.handlers' 4 | 5 | export interface BookmarksState { 6 | tree: Bookmark[] 7 | byId: Record 8 | popup: BookmarksPopupState | null 9 | expanded: Record> 10 | } 11 | 12 | export interface BookmarksPopupControlConfig { 13 | label: string 14 | inactive?: boolean 15 | } 16 | 17 | export interface BookmarksPopupConfig { 18 | title: string 19 | name?: string 20 | nameField?: boolean 21 | url?: string 22 | urlField?: boolean 23 | locationField?: boolean 24 | locationTree?: boolean 25 | location?: ID 26 | recentLocations?: boolean 27 | recentLocationAsDefault?: boolean 28 | newFolderPosition?: [parentId: ID, index: number] 29 | target?: Bookmark 30 | controls?: BookmarksPopupControlConfig[] 31 | validate?: (popupState: BookmarksPopupState) => void 32 | } 33 | 34 | export interface BookmarksPopupState extends BookmarksPopupConfig { 35 | name: string 36 | nameValid: boolean 37 | url: string 38 | urlValid: boolean 39 | close: (result?: BookmarksPopupResult) => void 40 | } 41 | 42 | export interface BookmarksPopupResult { 43 | name?: string 44 | url?: string 45 | location?: ID 46 | controlIndex: number 47 | } 48 | 49 | export const Bookmarks = { 50 | reactive: { 51 | tree: [], 52 | byId: {}, 53 | popup: null, 54 | expanded: {}, 55 | } as BookmarksState, 56 | 57 | byUrl: {} as Record, 58 | markedFolders: {} as Record, 59 | overallCount: 0, 60 | 61 | ...BookmarksHandlers, 62 | ...BookmarksActions, 63 | } 64 | -------------------------------------------------------------------------------- /src/services/containers.ts: -------------------------------------------------------------------------------- 1 | import { Container } from 'src/types' 2 | import * as ContainersActions from 'src/services/containers.actions' 3 | import * as ContainersHandlers from 'src/services/containers.handlers' 4 | 5 | export interface ContainersState { 6 | byId: Record 7 | } 8 | 9 | export interface ContainerProxy { 10 | type: browser.proxy.ProxyType 11 | host: string 12 | port: string 13 | } 14 | 15 | export const Containers = { 16 | reactive: { byId: {} } as ContainersState, 17 | 18 | ...ContainersHandlers, 19 | ...ContainersActions, 20 | } 21 | -------------------------------------------------------------------------------- /src/services/drag-and-drop.ts: -------------------------------------------------------------------------------- 1 | import { NOID } from 'src/defaults' 2 | import { DragItem, DragType, DropType } from 'src/types' 3 | import * as DndActions from 'src/services/drag-and-drop.actions' 4 | 5 | export const enum DndPointerMode { 6 | None = 0, 7 | Between = 1, 8 | Inside = 2, 9 | } 10 | 11 | export const DndPointerModeNames = { 12 | [DndPointerMode.None]: 'none', 13 | [DndPointerMode.Between]: 'between', 14 | [DndPointerMode.Inside]: 'inside', 15 | } 16 | 17 | export interface DragAndDropState { 18 | isStarted: boolean 19 | 20 | pointerExpanding: boolean 21 | pointerMode: DndPointerMode 22 | pointerLvl: number 23 | pointerHover: boolean 24 | pointerLeft: number 25 | 26 | dstType: DropType 27 | dstIndex: number 28 | dstParentId: ID 29 | dstPin: boolean 30 | dstPanelId: ID 31 | 32 | dragTooltipTitle: string 33 | dragTooltipInfo: string 34 | } 35 | 36 | export const DnD = { 37 | reactive: { 38 | isStarted: false, 39 | pointerExpanding: false, 40 | pointerMode: DndPointerMode.None, 41 | pointerLvl: 0, 42 | pointerHover: false, 43 | pointerLeft: 0, 44 | dstType: DropType.Nowhere, 45 | dstIndex: -1, 46 | dstParentId: NOID, 47 | dstPanelId: NOID, 48 | dstPin: false, 49 | dragTooltipTitle: '', 50 | dragTooltipInfo: '', 51 | } as DragAndDropState, 52 | 53 | dropEventConsumed: false, 54 | dropMode: 'auto' as 'auto' | 'copy', 55 | items: [] as DragItem[], 56 | isExternal: false, 57 | goOutside: false, 58 | startX: 0, 59 | startY: 0, 60 | 61 | srcType: DragType.Nothing, 62 | srcIncognito: false, 63 | srcPin: false, 64 | srcWinId: NOID, 65 | srcPanelId: NOID, 66 | srcIndex: -1, 67 | 68 | dragEndedRecently: false, 69 | 70 | ...DndActions, 71 | } 72 | -------------------------------------------------------------------------------- /src/services/history.ts: -------------------------------------------------------------------------------- 1 | import { HistoryDay, Visit } from 'src/types' 2 | import * as HistoryActions from 'src/services/history.actions' 3 | 4 | export interface HistoryState { 5 | loading: boolean 6 | days: HistoryDay[] 7 | } 8 | 9 | export const History = { 10 | reactive: { days: [], loading: false } as HistoryState, 11 | 12 | visits: [] as Visit[], 13 | filtered: undefined as Visit[] | undefined, 14 | byId: {} as Record, 15 | 16 | ready: false, 17 | allLoaded: false, 18 | loadingMore: false, 19 | 20 | panelScrollEl: null as HTMLElement | null, 21 | subPanelScrollEl: null as HTMLElement | null, 22 | 23 | ...HistoryActions, 24 | } 25 | -------------------------------------------------------------------------------- /src/services/info.ts: -------------------------------------------------------------------------------- 1 | import { InstanceType } from 'src/types' 2 | import * as InfoActions from 'src/services/info.actions' 3 | import { NOID } from 'src/defaults' 4 | 5 | interface InfoState { 6 | os: string 7 | addonVer: string 8 | } 9 | 10 | export const Info = { 11 | reactive: { 12 | os: 'unknown', 13 | addonVer: browser.runtime.getManifest().version, 14 | } as InfoState, 15 | 16 | instanceType: InstanceType.unknown, 17 | isSidebar: false, 18 | isSetup: false, 19 | isGroup: false, 20 | isProxy: false, 21 | isUrl: false, 22 | isBg: false, 23 | isSearch: false, 24 | isEditing: false, 25 | isPreview: false, 26 | isSync: false, 27 | isPanelConfig: false, 28 | 29 | majorVersion: undefined as number | undefined, 30 | prevMajorVersion: undefined as number | undefined, 31 | prevVersion: undefined as string | undefined, 32 | 33 | currentTabId: NOID, 34 | 35 | ...InfoActions, 36 | } 37 | -------------------------------------------------------------------------------- /src/services/keybindings.ts: -------------------------------------------------------------------------------- 1 | import { Command } from 'src/types' 2 | import * as KeybindingsActions from 'src/services/keybindings.actions' 3 | 4 | export interface KBState { 5 | list: Command[] 6 | byName: Record 7 | } 8 | 9 | export const Keybindings = { 10 | reactive: { list: [], byName: {} } as KBState, 11 | 12 | ...KeybindingsActions, 13 | } 14 | -------------------------------------------------------------------------------- /src/services/logs.ts: -------------------------------------------------------------------------------- 1 | /* eslint no-console: off */ 2 | import { NOID } from 'src/defaults' 3 | import { InstanceType } from 'src/types' 4 | import { getInstanceName } from './info.actions' 5 | 6 | let _type = 'unknown' 7 | let _winId = '' 8 | let _tabId = '' 9 | 10 | export function setInstanceType(type: InstanceType): void { 11 | _type = getInstanceName(type) 12 | } 13 | 14 | export function setWinId(id: ID): void { 15 | if (id !== NOID) _winId = `:${id}` 16 | } 17 | 18 | export function setTabId(id: ID): void { 19 | if (id !== NOID) _tabId = `:${id}` 20 | } 21 | 22 | export function info>(msg: string, ...args: T): void { 23 | console.log(`[${_type}${_winId}${_tabId}] ${msg}`, ...args) 24 | } 25 | 26 | export function warn>(msg: string, ...args: T): void { 27 | console.warn(`[${_type}${_winId}${_tabId}] ${msg}`, ...args) 28 | } 29 | 30 | export function err(msg: string, err?: unknown, ...args: Array): void { 31 | msg = `[${_type}${_winId}${_tabId}] ${msg}\n` 32 | 33 | if (args.length) args.unshift('\n') 34 | 35 | if (err !== undefined) console.error(msg, err, ...args) 36 | else console.error(msg, ...args) 37 | } 38 | -------------------------------------------------------------------------------- /src/services/menu.options.history.ts: -------------------------------------------------------------------------------- 1 | import { MenuOption } from 'src/types' 2 | import { translate } from 'src/dict' 3 | import { History } from './history' 4 | import * as Selection from './selection' 5 | import { Search } from './search' 6 | import { Sidebar } from './sidebar' 7 | 8 | export const historyMenuOptions: Record MenuOption | MenuOption[] | undefined> = { 9 | open: () => { 10 | return { 11 | label: translate('menu.history.open'), 12 | icon: 'icon_reopen', 13 | onClick: () => { 14 | const firstId = Selection.getFirst() 15 | const list = History.filtered ?? History.visits 16 | const target = list.find(v => v.id === firstId) 17 | if (!target) return 18 | History.open(target, { panelId: Sidebar.getRecentTabsPanelId() }, false, true) 19 | }, 20 | } 21 | }, 22 | 23 | copyHistoryUrls: () => { 24 | const selected = Selection.ids() 25 | return { 26 | label: translate('menu.copy_urls', selected.length), 27 | icon: 'icon_link', 28 | badge: 'icon_copy_badge', 29 | onClick: () => History.copyUrls(selected), 30 | } 31 | }, 32 | 33 | copyHistoryTitles: () => { 34 | const selected = Selection.ids() 35 | return { 36 | label: translate('menu.copy_titles', selected.length), 37 | icon: 'icon_title', 38 | badge: 'icon_copy_badge', 39 | onClick: () => History.copyTitles(selected), 40 | } 41 | }, 42 | 43 | deleteVisits: () => { 44 | const selected = Selection.ids() 45 | 46 | return { 47 | label: translate('menu.history.delete_visits', selected.length), 48 | icon: 'icon_clock', 49 | badge: 'icon_close', 50 | keepSearching: true, 51 | onClick: () => History.deleteVisits(selected), 52 | } 53 | }, 54 | 55 | deleteSites: () => { 56 | const selected = Selection.ids() 57 | 58 | return { 59 | label: translate('menu.history.delete_sites', selected.length), 60 | icon: 'icon_web', 61 | badge: 'icon_close', 62 | keepSearching: true, 63 | onClick: async () => { 64 | await History.deleteSites(selected) 65 | if (Search.rawValue) Search.search() 66 | }, 67 | } 68 | }, 69 | } 70 | -------------------------------------------------------------------------------- /src/services/menu.ts: -------------------------------------------------------------------------------- 1 | import { MenuConf } from 'src/types' 2 | import * as MenuActions from 'src/services/menu.actions' 3 | 4 | export const Menu = { 5 | isOpen: false, 6 | tabsConf: [] as MenuConf, 7 | bookmarksConf: [] as MenuConf, 8 | tabsPanelConf: [] as MenuConf, 9 | bookmarksPanelConf: [] as MenuConf, 10 | ctxMenuIgnoreContainersRules: {} as Record, 11 | 12 | ...MenuActions, 13 | } 14 | -------------------------------------------------------------------------------- /src/services/mouse.ts: -------------------------------------------------------------------------------- 1 | import * as MouseActions from 'src/services/mouse.actions' 2 | 3 | export type ResizingMode = 'x' | 'y' | null 4 | 5 | export const Mouse = { 6 | multiSelectionMode: false, 7 | resizing: null as ResizingMode, 8 | longClickApplied: false, 9 | mouseIn: false, 10 | 11 | x: 0, 12 | y: 0, 13 | 14 | ...MouseActions, 15 | } 16 | -------------------------------------------------------------------------------- /src/services/permissions.ts: -------------------------------------------------------------------------------- 1 | import * as PermissionsActions from 'src/services/permissions.actions' 2 | 3 | export interface PermissionsState { 4 | webData: boolean 5 | bookmarks: boolean 6 | tabHide: boolean 7 | clipboardWrite: boolean 8 | clipboardRead: boolean 9 | history: boolean 10 | downloads: boolean 11 | } 12 | 13 | export const Permissions = { 14 | reactive: { 15 | webData: false, 16 | bookmarks: false, 17 | tabHide: false, 18 | clipboardWrite: false, 19 | clipboardRead: false, 20 | history: false, 21 | downloads: false, 22 | } as PermissionsState, 23 | 24 | allUrls: false, 25 | webRequest: false, 26 | webRequestBlocking: false, 27 | proxy: false, 28 | 29 | bookmarks: false, 30 | tabHide: false, 31 | clipboardWrite: false, 32 | clipboardRead: false, 33 | history: false, 34 | downloads: false, 35 | 36 | ...PermissionsActions, 37 | } 38 | -------------------------------------------------------------------------------- /src/services/search.ts: -------------------------------------------------------------------------------- 1 | import * as SearchActions from 'src/services/search.actions' 2 | 3 | export interface SearchState { 4 | barIsShowed: boolean 5 | barIsActive: boolean 6 | barIsFocused: boolean 7 | value: string 8 | rawValue: string 9 | } 10 | 11 | export interface SearchShortcut { 12 | ctrl: boolean 13 | alt: boolean 14 | meta: boolean 15 | key: string 16 | } 17 | 18 | interface SearchShortcuts { 19 | bookmarks?: SearchShortcut 20 | history?: SearchShortcut 21 | } 22 | 23 | export const Search = { 24 | reactive: { 25 | barIsShowed: false, 26 | barIsActive: false, 27 | barIsFocused: false, 28 | value: '', 29 | rawValue: '', 30 | } as SearchState, 31 | rawValue: '', 32 | prevValue: '', 33 | prevExpandedBookmarks: undefined as Record> | undefined, 34 | 35 | shortcuts: {} as SearchShortcuts, 36 | 37 | ...SearchActions, 38 | } 39 | -------------------------------------------------------------------------------- /src/services/settings.ts: -------------------------------------------------------------------------------- 1 | import * as Utils from 'src/utils' 2 | import { CopyTemplate } from 'src/types' 3 | import { DEFAULT_SETTINGS } from 'src/defaults' 4 | import * as SettingsActions from 'src/services/settings.actions' 5 | 6 | export const Settings = { 7 | state: Utils.cloneObject(DEFAULT_SETTINGS), 8 | 9 | updateWinPrefaceOnPanelSwitch: false, 10 | copyTemplates: [] as CopyTemplate[], 11 | 12 | rmChildTabsFolded: false, 13 | rmChildTabsAll: false, 14 | rmChildTabsNone: false, 15 | 16 | activateAfterClosingNone: false, 17 | activateAfterClosingNext: false, 18 | activateAfterClosingPrev: false, 19 | activateAfterClosingPrevAct: false, 20 | 21 | tabsUpdateMarkAll: false, 22 | tabsUpdateMarkPin: false, 23 | tabsUpdateMarkNorm: false, 24 | tabsUpdateMarkNone: false, 25 | 26 | ...SettingsActions, 27 | } 28 | -------------------------------------------------------------------------------- /src/services/snapshots.ts: -------------------------------------------------------------------------------- 1 | import { Snapshot } from 'src/types' 2 | import * as SnapshotsActions from 'src/services/snapshots.actions' 3 | 4 | export interface SnapshotsState { 5 | list: Snapshot[] 6 | } 7 | 8 | export const Snapshots = { 9 | state: { list: [] } as SnapshotsState, 10 | 11 | ...SnapshotsActions, 12 | } 13 | -------------------------------------------------------------------------------- /src/services/styles.ts: -------------------------------------------------------------------------------- 1 | import * as StylesActions from 'src/services/styles.actions' 2 | import { RGBA } from 'src/types' 3 | 4 | export interface StylesState { 5 | frameColorScheme: 'dark' | 'light' 6 | toolbarColorScheme: 'dark' | 'light' 7 | actElColorScheme: 'dark' | 'light' 8 | popupColorScheme: 'dark' | 'light' 9 | } 10 | 11 | export interface ParsedTheme { 12 | error: boolean 13 | vars: SrcVars 14 | 15 | frameBg?: RGBA 16 | frameFg?: RGBA 17 | 18 | toolbarBg?: RGBA 19 | toolbarFg?: RGBA 20 | toolbarBorder?: RGBA 21 | 22 | actElBg?: RGBA 23 | actElFg?: RGBA 24 | actElBorder?: RGBA 25 | 26 | popupBg?: RGBA 27 | popupFg?: RGBA 28 | popupBorder?: RGBA 29 | 30 | accent?: RGBA 31 | 32 | frameVariant?: ColorSchemeVariant 33 | toolbarVariant?: ColorSchemeVariant 34 | actElVariant?: ColorSchemeVariant 35 | popupVariant?: ColorSchemeVariant 36 | } 37 | 38 | export interface SrcVars { 39 | frame_bg?: string | null 40 | frame_fg?: string | null 41 | 42 | toolbar_bg?: string | null 43 | toolbar_fg?: string | null 44 | toolbar_border?: string | null 45 | 46 | act_el_bg?: string | null 47 | act_el_fg?: string | null 48 | act_el_border?: string | null 49 | 50 | popup_bg?: string | null 51 | popup_fg?: string | null 52 | popup_border?: string | null 53 | popup_separator?: string | null 54 | 55 | accent?: string | null 56 | top_padding?: string | null 57 | darker_border_width?: string | null 58 | } 59 | 60 | export const enum ColorSchemeVariant { 61 | Dark = 1, 62 | Light = 2, 63 | } 64 | 65 | const defaultColorScheme = StylesActions.getSystemColorScheme() 66 | 67 | export const Styles = { 68 | reactive: { 69 | colorScheme: defaultColorScheme, 70 | frameColorScheme: defaultColorScheme, 71 | toolbarColorScheme: defaultColorScheme, 72 | actElColorScheme: defaultColorScheme, 73 | popupColorScheme: defaultColorScheme, 74 | } as StylesState, 75 | sidebarCSS: '', 76 | groupCSS: '', 77 | theme: undefined as browser.theme.Theme | undefined, 78 | parsedTheme: undefined as ParsedTheme | undefined, 79 | 80 | ...StylesActions, 81 | } 82 | -------------------------------------------------------------------------------- /src/services/tabs.bg.ts: -------------------------------------------------------------------------------- 1 | import { Tab, TabCache } from 'src/types' 2 | import * as TabsActions from 'src/services/tabs.bg.actions' 3 | 4 | export const Tabs = { 5 | ready: false, 6 | byId: {} as Record, 7 | cacheByWin: {} as Record, 8 | deferredEventHandling: [] as (() => void)[], 9 | 10 | ...TabsActions, 11 | } 12 | -------------------------------------------------------------------------------- /src/services/web-req.ts: -------------------------------------------------------------------------------- 1 | import * as WebReqActions from 'src/services/web-req.actions' 2 | 3 | export const WebReq = { 4 | containersProxies: {} as Record, 5 | 6 | ...WebReqActions, 7 | } 8 | -------------------------------------------------------------------------------- /src/services/windows.ts: -------------------------------------------------------------------------------- 1 | import { NOID } from 'src/defaults' 2 | import { Window, WindowChooseOption } from 'src/types' 3 | import * as WindowsActions from 'src/services/windows.actions' 4 | import * as WindowsHandlers from 'src/services/windows.handlers' 5 | 6 | export interface WindowsState { 7 | choosing: WindowChooseOption[] | null 8 | choosingTitle: string 9 | } 10 | 11 | export const Windows = { 12 | byId: {} as Record, 13 | 14 | reactive: { choosing: null, choosingTitle: '' } as WindowsState, 15 | id: NOID, 16 | uniqWinId: NOID, 17 | incognito: false, 18 | lastFocusedId: NOID, 19 | focused: false, 20 | lastFocused: false, 21 | otherWindows: [] as Window[], 22 | 23 | lastFocusedWinId: NOID as ID | undefined, 24 | 25 | ...WindowsActions, 26 | ...WindowsHandlers, 27 | } 28 | -------------------------------------------------------------------------------- /src/sidebar/components/bar.panel-view-switcher.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 34 | -------------------------------------------------------------------------------- /src/sidebar/components/bar.pinned-tabs.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 54 | -------------------------------------------------------------------------------- /src/sidebar/components/dnd-pointer.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 25 | -------------------------------------------------------------------------------- /src/sidebar/components/dnd-tooltip.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /src/sidebar/components/panel-placeholder.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 36 | -------------------------------------------------------------------------------- /src/sidebar/components/panel.sync.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 53 | -------------------------------------------------------------------------------- /src/sidebar/components/popup.confirm.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /src/sidebar/components/popup.windows.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 57 | -------------------------------------------------------------------------------- /src/sidebar/components/sub-list-title.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /src/styles/themes/proton/animations.styl: -------------------------------------------------------------------------------- 1 | // --- 2 | // -- Animations 3 | // - 4 | @keyframes rotating-animation 5 | 0% 6 | transform: rotateZ(0deg) 7 | 100% 8 | transform: rotateZ(360deg) 9 | 10 | @keyframes shake-animation 11 | 0% 12 | transform: translateX(0) 13 | 20% 14 | transform: translateX(-12px) 15 | 40% 16 | transform: translateX(12px) 17 | 55% 18 | transform: translateX(-8px) 19 | 70% 20 | transform: translateX(6px) 21 | 80% 22 | transform: translateX(-4px) 23 | 90% 24 | transform: translateX(2px) 25 | 100% 26 | transform: translateX(0) 27 | 28 | @keyframes err-blink-animation 29 | 0% 30 | box-shadow: inset 0 0 0 1px var(--status-err) 31 | 20% 32 | box-shadow: inset 0 0 0 1px var(--status-err) 33 | 100% 34 | box-shadow: inset 0 0 0 1px #00000016 35 | 36 | @keyframes middle-click-animation 37 | 0% 38 | opacity: 1 39 | 5% 40 | opacity: .3 41 | 100% 42 | opacity: 1 43 | 44 | // --- 45 | // -- Vue transitions 46 | // - 47 | #root .popup-enter-active 48 | #root .popup-leave-active 49 | transition: opacity var(--d-fast), z-index var(--d-fast) 50 | .popup 51 | transition: transform var(--d-fast) 52 | #root .popup-enter-from 53 | opacity: 0 54 | z-index: 0 55 | .popup 56 | transform: translateY(16px) 57 | #root .popup-enter-to 58 | opacity: 1 59 | z-index: 10000 60 | .popup 61 | transform: translateY(0) 62 | #root .popup-leave-from 63 | opacity: 1 64 | z-index: 10000 65 | .popup 66 | transform: translateY(0) 67 | #root .popup-leave-to 68 | opacity: 0 69 | z-index: 0 70 | .popup 71 | transform: translateY(16px) 72 | -------------------------------------------------------------------------------- /src/styles/themes/proton/btn.styl: -------------------------------------------------------------------------------- 1 | @import '../../utils' 2 | 3 | #root 4 | --btn-border-radius: var(--general-border-radius) 5 | 6 | .btn 7 | position: relative 8 | max-width: 100% 9 | font-size: rem(15) 10 | padding: 4px 12px 11 | white-space: nowrap 12 | text-overflow: ellipsis 13 | font-weight: 600 14 | overflow: hidden 15 | cursor: default 16 | text-align: center 17 | -moz-user-select: none 18 | color: var(--btn-fg) 19 | border-radius: var(--btn-border-radius) 20 | border: none 21 | outline: none 22 | background-color: transparent 23 | &.-focused 24 | box-shadow: 0 0 0 2px var(--toolbar-fg-active) 25 | &.-wide 26 | width: 100% 27 | min-width: auto 28 | &.-wrap 29 | white-space: normal 30 | text-overflow: clip 31 | &.-warn:after 32 | &:before 33 | content: '' 34 | position: absolute 35 | top: 0 36 | left: 0 37 | width: 100% 38 | height: 100% 39 | background-color: var(--btn-fg) 40 | border-radius: var(--btn-border-radius) 41 | opacity: .1 42 | &.-warn:after 43 | background-color: #ff2200 44 | &:hover:before 45 | opacity: .2 46 | &:active:before 47 | opacity: .08 48 | &.-inactive 49 | opacity: .3 50 | cursor: default 51 | &:before 52 | opacity: .2 53 | 54 | > input 55 | position: absolute 56 | top: 0 57 | left: 0 58 | width: 100% 59 | height: 100% 60 | opacity: 0 61 | -------------------------------------------------------------------------------- /src/styles/themes/proton/page.setup/settings.details-box.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .DetailsBox 4 | position: fixed 5 | display: flex 6 | top: 0 7 | left: 0 8 | width: 100vw 9 | height: 100vh 10 | flex-flow: column 11 | align-items: center 12 | background-color: var(--frame-bg) 13 | z-index: 20 14 | overflow: auto 15 | scrollbar-color: var(--scrollbar-color) #0000 16 | 17 | .DetailsBox > .box 18 | position: fixed 19 | display: flex 20 | grid-gap: 16px 8px 21 | flex-wrap: wrap 22 | margin: 0 16px 23 | top: 24px 24 | right: 16px 25 | padding: 8px 16px 26 | justify-content: center 27 | align-items: center 28 | z-index: 1 29 | &:before 30 | content: '' 31 | position: absolute 32 | top: 0 33 | left: 0 34 | width: 100% 35 | height: 100% 36 | border-radius: 4px 37 | background-color: var(--frame-bg) 38 | opacity: .9 39 | 40 | .DetailsBox .btn 41 | .DetailsBox .btn 42 | font-size: rem(12) 43 | font-weight: 700 44 | padding: 6px 12px 45 | 46 | .DetailsBox .title 47 | position: relative 48 | color: var(--toolbar-fg) 49 | font-size: rem(18) 50 | font-weight: 700 51 | margin-right: 6px 52 | 53 | .DetailsBox .json 54 | position: relative 55 | max-width: 100% 56 | font-family: monospace 57 | font-size: rem(11) 58 | padding: 70px 40px 32px 59 | white-space: pre 60 | margin: 0 auto 61 | color: var(--toolbar-fg) 62 | 63 | .DetailsBox .editor 64 | position: relative 65 | box-sizing: border-box 66 | width: calc(100% - 16px) 67 | height: 100% 68 | font-family: monospace 69 | font-size: rem(12) 70 | color: var(--status-ok) 71 | -webkit-appearance: none 72 | border: none 73 | outline: none 74 | margin: 0 75 | padding: 70px 8px 32px 76 | background-color: transparent 77 | resize: none 78 | -------------------------------------------------------------------------------- /src/styles/themes/proton/page.setup/settings.note-field.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .Settings .note-field 4 | position: relative 5 | display: flex 6 | min-height: 42px 7 | justify-content: space-between 8 | align-items: center 9 | flex-wrap: wrap 10 | padding: 0 16px 11 | flex-shrink: 0 12 | 13 | &:not(:first-of-type):after 14 | content: '' 15 | position: absolute 16 | top: 1px 17 | left: 6px 18 | width: calc(100% - 12px) 19 | height: 1px 20 | background-color: var(--toolbar-fg) 21 | opacity: .1 22 | 23 | .label 24 | position: relative 25 | font-size: rem(16) 26 | line-height: 26px 27 | padding: 8px 8px 4px 0 28 | align-self: flex-start 29 | color: var(--toolbar-fg) 30 | transition: color var(--d-fast) 31 | 32 | .note 33 | position: relative 34 | font-size: rem(14) 35 | max-width: 100% 36 | padding: 0 0 8px 16px 37 | white-space: pre-wrap 38 | color: var(--toolbar-fg) 39 | opacity: .7 40 | &.-wide 41 | width: 100% 42 | code.note 43 | font-size: rem(12) 44 | word-break: break-all 45 | opacity: .9 46 | 47 | .link 48 | position: relative 49 | align-self: flex-start 50 | font-size: rem(16) 51 | line-height: 26px 52 | padding: 8px 0 4px 53 | white-space: pre-wrap 54 | color: var(--status-notice) 55 | text-decoration: underline 56 | 57 | .inline-box 58 | width: 100% 59 | display: flex 60 | justify-content: space-between 61 | -------------------------------------------------------------------------------- /src/styles/themes/proton/page.setup/settings.permissions.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .Settings .permission 4 | position: relative 5 | 6 | &:not(:first-of-type):after 7 | content: '' 8 | position: absolute 9 | top: 0 10 | left: 1px 11 | width: calc(100% - 2px) 12 | height: 1px 13 | background-color: var(--toolbar-fg) 14 | opacity: .1 15 | 16 | .Settings .permission[data-highlight="true"] 17 | position: relative 18 | 19 | .Settings .permission[data-highlight="true"]:before 20 | content: '' 21 | position: absolute 22 | top: -8px 23 | left: -8px 24 | width: calc(100% + 16px) 25 | height: calc(100% + 16px) 26 | outline: 2px dashed var(--status-err) 27 | outline-offset: -2px 28 | -------------------------------------------------------------------------------- /src/styles/themes/proton/page.setup/settings.popup.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .Settings .popup-layer 4 | position: fixed 5 | display: flex 6 | top: 0 7 | left: 0 8 | width: 100vw 9 | height: 100vh 10 | flex-direction: column 11 | justify-content: flex-start 12 | align-items: center 13 | z-index: 20 14 | &:before 15 | content: '' 16 | position: absolute 17 | top: 0 18 | left: 0 19 | width: 100% 20 | height: 100% 21 | background-color: #2228 22 | opacity: .5 23 | &:after 24 | content: '' 25 | position: relative 26 | width: 100% 27 | height: 64px 28 | flex-shrink: 10 29 | 30 | .Settings .popup-box 31 | position: relative 32 | width: calc(100vw - 8px) 33 | max-width: 640px 34 | min-height: 32px 35 | margin: 16px 0 36 | overflow: hidden 37 | background-color: var(--popup-bg) 38 | border-radius: 3px 39 | box-shadow: var(--popup-shadow) 40 | 41 | .popup-enter-active 42 | .popup-leave-active 43 | transition: opacity var(--d-fast) 44 | .popup-box 45 | transition: transform var(--d-fast) 46 | .popup-enter-from 47 | opacity: 0 48 | .popup-box 49 | transform: translateY(32px) 50 | .popup-enter-to 51 | opacity: 1 52 | .popup-box 53 | transform: translateY(0) 54 | .popup-leave-from 55 | opacity: 1 56 | .popup-box 57 | transform: translateY(0) 58 | .popup-leave-to 59 | opacity: 0 60 | .popup-box 61 | transform: translateY(32px) 62 | -------------------------------------------------------------------------------- /src/styles/themes/proton/page.url/url.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | @import '../vars' 3 | @import '../btn' 4 | 5 | html 6 | position: relative 7 | height: 100% 8 | 9 | body 10 | --btn-fg: var(--toolbar-fg) 11 | 12 | position: relative 13 | display: flex 14 | width: calc(100% - 16px) 15 | min-height: 100% 16 | font-family: system-ui 17 | -webkit-font-smoothing: antialiased 18 | -moz-osx-font-smoothing: grayscale 19 | margin: 0 20 | flex-direction: column 21 | justify-content: center 22 | align-items: center 23 | padding: 0 8px 24 | background-color: var(--toolbar-bg) 25 | 26 | h2 27 | position: relative 28 | color: var(--toolbar-fg) 29 | font-size: rem(32) 30 | padding: 32px 0 8px 31 | 32 | #title_note 33 | position: relative 34 | color: var(--toolbar-fg) 35 | font-size: rem(21) 36 | padding: 0 8px 16px 37 | margin: 0 38 | opacity: .64 39 | 40 | main 41 | position: relative 42 | display: flex 43 | justify-content: center 44 | align-items: center 45 | flex-direction: column 46 | width: 100% 47 | height: 100% 48 | flex-grow: 1 49 | padding: 0 0 100px 0 50 | 51 | .label 52 | position: relative 53 | width: calc(100% - 32px) 54 | max-width: 720px 55 | font-size: rem(14) 56 | font-weight: 600 57 | color: var(--toolbar-fg) 58 | margin: 0 59 | padding: 0 16px 60 | opacity: .5 61 | 62 | .value 63 | position: relative 64 | font-size: rem(16) 65 | width: calc(100% - 32px) 66 | max-width: 720px 67 | color: var(--toolbar-fg) 68 | padding: 8px 16px 24px 69 | margin: 0 70 | word-wrap: anywhere 71 | 72 | .btn 73 | font-size: rem(16) 74 | padding: 8px 18px 75 | margin-top: 12px 76 | overflow: visible 77 | .btn:after 78 | content: '' 79 | position: absolute 80 | width: 100% 81 | height: 100% 82 | top: 0 83 | left: 0 84 | border-radius: 4px 85 | .btn:focus:after 86 | box-shadow: 0 0 0 2px var(--toolbar-fg) 87 | 88 | .note 89 | position: relative 90 | max-width: 720px 91 | font-size: rem(12) 92 | color: var(--toolbar-fg) 93 | margin: 8px 16px 94 | overflow: hidden 95 | opacity: .5 96 | a 97 | color: var(--toolbar-fg) -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/bar.panel-view-switcher.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .PanelViewSwitcherBar 4 | position: relative 5 | display: flex 6 | flex-shrink: 0 7 | width: 100% 8 | height: 100% 9 | overflow: hidden 10 | .view-btn 11 | position: relative 12 | display: flex 13 | justify-content: center 14 | align-items: center 15 | width: 100% 16 | min-width: 28px 17 | height: 100% 18 | overflow: hidden 19 | &:before 20 | content: '' 21 | position: absolute 22 | top: 2px 23 | left: 2px 24 | width: calc(100% - 4px) 25 | height: calc(100% - 4px) 26 | border-radius: 4px 27 | background-color: var(--toolbar-fg) 28 | opacity: 0 29 | > svg 30 | position: absolute 31 | width: 16px 32 | height: 16px 33 | fill: var(--toolbar-fg) 34 | opacity: .7 35 | &:hover:before 36 | opacity: .12 37 | &[data-active="true"] 38 | &:before 39 | opacity: .2 40 | > svg 41 | opacity: 1 42 | &:active:before 43 | opacity: .16 44 | 45 | .btn-sep 46 | display: none 47 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/loading-dots.styl: -------------------------------------------------------------------------------- 1 | .LoadingDots 2 | position: absolute 3 | display: flex 4 | width: 100% 5 | height: 100% 6 | justify-content: center 7 | align-items: center 8 | .loading-dots-a, .loading-dots-b, .loading-dots-c 9 | position: relative 10 | width: 4px 11 | height: 4px 12 | flex-shrink: 0 13 | background-color: var(--frame-fg) 14 | border-radius: 2px 15 | margin: 2px 16 | .loading-dots-a 17 | animation: loading-dots .7s infinite 18 | .loading-dots-b 19 | animation: loading-dots .7s .1s infinite 20 | .loading-dots-c 21 | animation: loading-dots .7s .2s infinite 22 | 23 | #root[data-animations="none"] .LoadingDots 24 | .loading-dots-a, .loading-dots-b, .loading-dots-c 25 | animation: none 26 | 27 | @keyframes loading-dots 28 | 0% 29 | opacity: 0 30 | 50% 31 | opacity: 1 32 | 100% 33 | opacity: 0 34 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/panel-placeholder.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .PanelPlaceholder 4 | --btn-fg: var(--frame-fg) 5 | 6 | position: absolute 7 | display: flex 8 | justify-content: center 9 | align-items: center 10 | width: 100% 11 | height: 100% 12 | top: 0 13 | left: 0 14 | z-index: 1000 15 | background-color: var(--frame-bg) 16 | &[data-loading="true"] 17 | cursor: progress 18 | 19 | .PanelPlaceholder .msg 20 | text-align: center 21 | font-size: rem(17) 22 | font-weight: 700 23 | padding: 0 8px 24 | color: var(--frame-fg) 25 | 26 | .PanelPlaceholder .perm-warn 27 | position: absolute 28 | width: 100% 29 | height: 100% 30 | display: flex 31 | justify-content: center 32 | align-items: center 33 | flex-grow: 1 34 | flex-direction: column 35 | cursor: default 36 | box-shadow: inset 0 -1px 0 0 var(--border) 37 | outline: 3px dashed var(--status-err); outline-offset: -2px; 38 | 39 | .PanelPlaceholder .perm-warn-msg 40 | position: relative 41 | text-align: center 42 | padding: 0 16px 43 | color: var(--frame-fg) 44 | font-size: rem(13) 45 | 46 | .PanelPlaceholder .perm-warn-btn 47 | padding: 5px 10px 48 | margin: 16px 8px 0 49 | font-size: rem(12) 50 | 51 | .panel-placeholder-enter-active 52 | transition: opacity var(--d-fast) 53 | .panel-placeholder-leave-active 54 | transition: opacity var(--d-fast) var(--d-fast) 55 | .panel-placeholder-enter-from 56 | .panel-placeholder-leave-to 57 | opacity: 0 58 | .panel-placeholder-enter-to 59 | .panel-placeholder-leave-from 60 | opacity: 1 61 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/panel.bookmarks.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .BookmarksPanel 4 | position: absolute 5 | display: flex 6 | width: 100% 7 | height: 100% 8 | flex-direction: column 9 | z-index: 100 10 | transition: transform var(--d-fast), opacity var(--d-fast), z-index var(--d-fast) 11 | overflow: hidden 12 | 13 | #root[data-sticky-bookmarks="true"]:not([data-drag="true"]) .BookmarksPanel[data-view-mode="tree"] .ScrollBox .top-shadow 14 | display: none 15 | 16 | .BookmarksPanel .bookmarks-tree 17 | .BookmarksPanel .bookmarks-history 18 | position: relative 19 | padding-bottom: 64px 20 | 21 | .BookmarksPanel .SubListTitle[data-folded="false"] 22 | position: sticky 23 | top: 0px 24 | 25 | .BookmarksPanel .group 26 | position: relative 27 | 28 | .BookmarksPanel .group-list 29 | position: relative 30 | padding: 0 0 12px 31 | 32 | // --- 33 | // -- Root nodes 34 | // - 35 | .BookmarksPanel .root-node 36 | position: relative 37 | opacity: 1 38 | transition: opacity var(--d-fast) 39 | 40 | // --- 41 | // -- Search 42 | // - 43 | .BookmarksPanel .filtered 44 | position: relative 45 | padding-bottom: 64px 46 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/panel.sync.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .SyncPanel 4 | --sync-item-margin: var(--general-margin) 5 | 6 | position: absolute 7 | display: flex 8 | width: 100% 9 | height: 100% 10 | flex-direction: column 11 | z-index: 100 12 | transition: transform var(--d-fast), opacity var(--d-fast), z-index var(--d-fast) 13 | min-height: 150px 14 | .sub-panel .SyncPanel 15 | position: relative 16 | overflow: hidden 17 | padding-top: var(--sync-item-margin) 18 | 19 | .SyncPanel .content 20 | position: relative 21 | min-height: 150px 22 | 23 | .SyncPanel .tmp-space 24 | position: relative 25 | height: 150px 26 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.confirm.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .Confirm .msg 4 | position: relative 5 | font-size: rem(15) 6 | padding: 0 8px 7 | color: var(--popup-fg) 8 | text-align: center 9 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.container-config.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .ContainerConfigPopup .field 4 | position: relative 5 | padding: 2px 4px 6 | &:first-of-type 7 | margin-top: 0 8 | 9 | .ContainerConfigPopup .field-label 10 | position: relative 11 | width: 100% 12 | font-size: rem(12) 13 | font-weight: 700 14 | color: var(--popup-fg) 15 | opacity: .7 16 | 17 | .ContainerConfigPopup .field > .input 18 | font-size: rem(15) 19 | transition: color 1s 20 | margin: 2px 0 11px 21 | > input 22 | > textarea 23 | > .placeholder 24 | color: var(--popup-fg) 25 | &[data-empty="true"] .placeholder 26 | opacity: .5 27 | &.err 28 | transition: none 29 | color: var(--status-err) 30 | &[data-active="true"]:before 31 | box-shadow: inset 0 0 0 1px var(--popup-fg) 32 | 33 | .ContainerConfigPopup .SelectInput 34 | padding: 0 35 | justify-content: flex-start 36 | max-width: unset 37 | .opt 38 | display: flex 39 | justify-content: center 40 | align-items: center 41 | height: 26px 42 | width: 26px 43 | &:before 44 | background-color: var(--color, var(--popup-fg)) 45 | svg 46 | padding: 0 47 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.dialog.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .Dialog .focus-stealer 4 | position: absolute 5 | opacity: 0 6 | 7 | .Dialog h2 8 | padding: 12px 8px 10px 9 | white-space: normal 10 | text-overflow: clip 11 | 12 | .Dialog .msg 13 | position: relative 14 | font-size: rem(15) 15 | padding: 0 8px 16 | color: var(--popup-fg) 17 | text-align: center 18 | 19 | .Dialog .note 20 | position: relative 21 | font-size: rem(13) 22 | padding: 0 4px 8px 23 | color: var(--popup-fg) 24 | opacity: .7 25 | 26 | .Dialog .ctrls[data-inline="true"] 27 | flex-wrap: nowrap 28 | 29 | .Dialog .ctrls .btn 30 | text-align: left 31 | min-width: auto 32 | .Dialog .ctrls[data-centered="true"] .btn 33 | text-align: center 34 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.group-config.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .GroupConfigPopup .field 4 | position: relative 5 | padding: 2px 4px 6 | &:first-of-type 7 | margin-top: 0 8 | 9 | .GroupConfigPopup .field-label 10 | position: relative 11 | width: 100% 12 | font-size: rem(12) 13 | font-weight: 700 14 | color: var(--popup-fg) 15 | opacity: .7 16 | 17 | .GroupConfigPopup .field > .input 18 | font-size: rem(15) 19 | transition: color 1s 20 | margin: 2px 0 11px 21 | > input 22 | > textarea 23 | > .placeholder 24 | color: var(--popup-fg) 25 | &[data-empty="true"] .placeholder 26 | opacity: .5 27 | &.err 28 | transition: none 29 | color: var(--status-err) 30 | &[data-active="true"]:before 31 | box-shadow: inset 0 0 0 1px var(--popup-fg) 32 | 33 | .GroupConfigPopup .SelectInput 34 | padding: 0 35 | justify-content: flex-start 36 | max-width: unset 37 | .opt 38 | display: flex 39 | justify-content: center 40 | align-items: center 41 | height: 26px 42 | width: 26px 43 | &:before 44 | background-color: var(--color, var(--popup-fg)) 45 | svg 46 | padding: 0 47 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.panel-config.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .PanelConfigPopup .field 4 | position: relative 5 | padding: 2px 4px 6 | &:first-of-type 7 | margin-top: 0 8 | 9 | .PanelConfigPopup .field-label 10 | position: relative 11 | width: 100% 12 | font-size: rem(12) 13 | font-weight: 700 14 | color: var(--popup-fg) 15 | opacity: .7 16 | 17 | .PanelConfigPopup .field > .input 18 | font-size: rem(15) 19 | transition: color 1s 20 | margin: 2px 0 11px 21 | > input 22 | > textarea 23 | > .placeholder 24 | color: var(--popup-fg) 25 | &[data-empty="true"] .placeholder 26 | opacity: .5 27 | &.err 28 | transition: none 29 | color: var(--status-err) 30 | &[data-active="true"]:before 31 | box-shadow: inset 0 0 0 1px var(--popup-fg) 32 | 33 | .PanelConfigPopup .SelectInput 34 | padding: 0 35 | justify-content: flex-start 36 | max-width: unset 37 | .opt 38 | display: flex 39 | justify-content: center 40 | align-items: center 41 | height: 18px 42 | width: 26px 43 | &:before 44 | background-color: var(--color, var(--popup-fg)) 45 | svg 46 | padding: 0 47 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.site-config.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | // Set toolbar colors for fields 4 | #root .SiteConfigPopup 5 | --toolbar-bg: var(--popup-bg) 6 | --toolbar-fg: var(--popup-fg) 7 | [data-color="toolbar"] 8 | --color: var(--popup-fg) 9 | 10 | .SiteConfigPopup .space 11 | height: 8px 12 | &:first-child 13 | display: none 14 | 15 | // Temp margins fix 16 | .Setup .SiteConfigPopup .SelectField 17 | .Setup .SiteConfigPopup .TextField 18 | padding: 0 8px 19 | margin-left: 4px 20 | margin-right: 4px 21 | 22 | .SiteConfigPopup .match-options 23 | position: relative 24 | display: flex 25 | flex-wrap: wrap 26 | grid-gap: 2px 27 | padding: 2px 4px 28 | 29 | .SiteConfigPopup .match-option 30 | position: relative 31 | padding: 5px 8px 32 | max-width: 100% 33 | border-radius: 4px 34 | &:before 35 | &:after 36 | content: '' 37 | position: absolute 38 | top: 0 39 | left: 0 40 | width: 100% 41 | height: 100% 42 | border-radius: 4px 43 | &:before 44 | background-color: var(--popup-fg) 45 | opacity: .1 46 | &[data-active="true"]:before 47 | opacity: .2 48 | &[data-active="true"]:after 49 | box-shadow: inset 0 0 0 2px var(--accent) 50 | &:hover:before 51 | opacity: .2 52 | &:not([data-active="true"]):active 53 | opacity: .7 54 | 55 | .label 56 | position: relative 57 | color: var(--popup-fg) 58 | font-size: rem(14) 59 | z-index: 1 60 | opacity: .7 61 | white-space: nowrap 62 | overflow: hidden 63 | text-overflow: ellipsis 64 | &[data-active="true"] .label 65 | opacity: 1 66 | 67 | .SiteConfigPopup .note 68 | position: relative 69 | margin: 3px 4px 3px 4px 70 | font-size: rem(14) 71 | font-weight: 700 72 | opacity: .7 73 | color: var(--popup-fg) 74 | 75 | .SiteConfigPopup .TextInput 76 | margin: 4px 77 | width: 100% 78 | 79 | .SiteConfigPopup .matchString .label 80 | font-weight: 400 81 | 82 | .SiteConfigPopup .sub-field 83 | .ToggleField 84 | padding-left: 8px 85 | 86 | .ToggleField .label 87 | font-size: rem(13) 88 | margin-right: 4px 89 | 90 | .ToggleField .ToggleInput 91 | align-self: center 92 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/popup.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | .popup-container 4 | --btn-fg: var(--popup-fg) 5 | 6 | position: absolute 7 | display: flex 8 | justify-content: center 9 | align-items: flex-start 10 | width: 100% 11 | height: 100% 12 | z-index: 10000 13 | transform: translateZ(0) 14 | background-color: #2228 15 | .popup-container.-centered 16 | align-items: center 17 | 18 | .popup 19 | position: relative 20 | display: flex 21 | flex-direction: column 22 | width: 100% 23 | max-width: 320px 24 | max-height: calc(100vh - 64px) 25 | margin: 32px 2px 0 26 | overflow: hidden 27 | border-radius: var(--general-border-radius) 28 | background-color: var(--popup-bg) 29 | box-shadow: var(--popup-shadow) 30 | .popup-container.-centered .popup 31 | margin: 0 2px 32 | 33 | .Setup .popup 34 | max-width: 350px 35 | 36 | .popup h2 37 | position: relative 38 | flex-shrink: 0 39 | font-size: rem(18) 40 | font-weight: 700 41 | color: var(--popup-fg) 42 | margin: 0 43 | padding: 12px 4px 10px 44 | text-align: center 45 | 46 | .popup .ctrls 47 | position: relative 48 | display: flex 49 | align-items: center 50 | justify-content: center 51 | padding: 0 2px 52 | margin: 4px 0 2px 53 | flex-wrap: wrap 54 | 55 | .popup .ctrls > .btn 56 | min-width: max-content 57 | font-size: rem(14) 58 | padding: 5px 12px 59 | margin: 2px 60 | flex-grow: 1 61 | .popup .ctrls > .btn.-wide 62 | min-width: auto 63 | -------------------------------------------------------------------------------- /src/styles/themes/proton/sidebar/scroll-box.styl: -------------------------------------------------------------------------------- 1 | @import '../../../utils' 2 | 3 | #root[data-frame-color-scheme="dark"] 4 | --scroll-progress-height: 1px 5 | --scroll-progress-bg: #37adef 6 | --scroll-color: #ffffff36 7 | #root[data-frame-color-scheme="light"] 8 | --scroll-progress-height: 2px 9 | --scroll-progress-bg: #178dff 10 | --scroll-color: #00000036 11 | 12 | .ScrollBox 13 | position: relative 14 | width: 100% 15 | height: 100% 16 | overflow: hidden 17 | 18 | // --- 19 | // -- Container of scrollable element 20 | // - 21 | .ScrollBox > .scroll-container 22 | position: relative 23 | width: 100% 24 | height: 100% 25 | overflow-x: hidden 26 | overflow-y: auto 27 | scrollbar-width: none 28 | scrollbar-color: var(--scroll-color) var(--frame-bg) 29 | #root[data-native-scrollbar="true"] .ScrollBox > .scroll-container 30 | scrollbar-width: auto 31 | #root[data-native-scrollbar="true"][data-native-scrollbars-thin="true"] .ScrollBox > .scroll-container 32 | scrollbar-width: thin 33 | #root[data-native-scrollbar="true"][data-native-scrollbars-left="true"] .ScrollBox > .scroll-container 34 | direction: rtl 35 | > .scrollable 36 | direction: ltr 37 | 38 | // --- 39 | // -- Scroll shadows 40 | // - 41 | .ScrollBox > .top-shadow 42 | .ScrollBox > .bottom-shadow 43 | position: absolute 44 | width: 100% 45 | height: 12px 46 | z-index: 999 47 | opacity: 0 48 | transition: opacity var(--d-norm) 49 | &[data-show="true"] 50 | opacity: 1 51 | 52 | .ScrollBox > .top-shadow 53 | top: -12px 54 | left: 0 55 | box-shadow: 0 1px 0 0 #00000012, 0 1px 12px 0 #00000068 56 | 57 | .ScrollBox > .bottom-shadow 58 | left: 0 59 | bottom: -12px 60 | box-shadow: 0 -1px 0 0 #00000012, 0 -1px 12px 0 #00000068 61 | 62 | // --- 63 | // -- Scrollable element 64 | // - 65 | .ScrollBox > .scroll-container > .scrollable 66 | position: relative 67 | width: 100% 68 | min-height: 100% 69 | // background-color: var(--frame-bg) 70 | -------------------------------------------------------------------------------- /src/styles/utils.styl: -------------------------------------------------------------------------------- 1 | // --- func 2 | // Convert px value to rem. 3 | // > px: length in px 4 | // > base: 1rem length in px (default 5 | // font size) 6 | // < rem value 7 | // ------------------------------------ 8 | rem(px, base = 16) 9 | return (1 / base * px)rem 10 | 11 | 12 | // --- mixin 13 | // Render blocks for sys and manual styles 14 | // > style: light|dark 15 | theme_style(style) 16 | if style == dark 17 | @media (prefers-color-scheme: dark), (prefers-color-scheme: no-preference) 18 | &[data-color-scheme="sys"] 19 | {block} 20 | &[data-color-scheme="dark"] 21 | {block} 22 | if style == light 23 | @media (prefers-color-scheme: light) 24 | &[data-color-scheme="sys"] 25 | {block} 26 | &[data-color-scheme="light"] 27 | {block} 28 | -------------------------------------------------------------------------------- /src/types/bookmarks.ts: -------------------------------------------------------------------------------- 1 | export interface Bookmark extends browser.bookmarks.TreeNode { 2 | parentId: ID // Required since I'm not using Root node 3 | index: number 4 | children?: Bookmark[] 5 | sel?: boolean 6 | selLock?: boolean 7 | isOpen?: boolean 8 | isParent?: boolean 9 | len?: number 10 | } 11 | 12 | export type BookmarksSortType = 'name' | 'link' | 'time' 13 | -------------------------------------------------------------------------------- /src/types/containers.ts: -------------------------------------------------------------------------------- 1 | import { TabReopenRuleConfig } from './sidebar' 2 | 3 | export interface Container extends browser.contextualIdentities.Container { 4 | id: string 5 | proxified: boolean 6 | proxy: browser.proxy.ProxyInfo | null 7 | reopenRulesActive: boolean 8 | reopenRules: TabReopenRuleConfig[] 9 | userAgentActive: boolean 10 | userAgent: string 11 | } 12 | -------------------------------------------------------------------------------- /src/types/globals.d.ts: -------------------------------------------------------------------------------- 1 | type ID = string | number 2 | 3 | type FirstParameter any> = T extends (arg: infer P) => any ? P : never 4 | 5 | type DOMEvent = E & { 6 | target: T 7 | currentTarget: T 8 | } 9 | 10 | type PlurFn = (n?: number | string) => string 11 | type Translations = Record> 12 | 13 | interface MozFocusEvent extends FocusEvent { 14 | explicitOriginalTarget: Node | Element 15 | } 16 | 17 | interface Window { 18 | sideberyInitData?: Record 19 | onSideberyInitDataReady?: () => void 20 | 21 | translations: Record> | undefined 22 | 23 | getSideberyState?: () => any 24 | } 25 | 26 | type DeepReadonly = { 27 | readonly [P in keyof T]: DeepReadonly 28 | } 29 | -------------------------------------------------------------------------------- /src/types/history.ts: -------------------------------------------------------------------------------- 1 | export type NativeHistoryItem = browser.history.HistoryItem 2 | export type NativeVisit = browser.history.VisitItem 3 | 4 | export interface Visit { 5 | id: string 6 | dayId: string 7 | url: string 8 | decodedUrl: string 9 | domain: string 10 | title: string 11 | noTitle: boolean 12 | time: number 13 | timeStr: string 14 | tooltip: string 15 | hiddenUnderParentId?: string 16 | 17 | reactive: { 18 | title: string 19 | tooltip: string 20 | sel: boolean 21 | moreVisits?: ID[] 22 | moreActive?: boolean 23 | } 24 | } 25 | 26 | export interface HistoryDay { 27 | id: string 28 | title: string 29 | visits: ID[] 30 | } 31 | -------------------------------------------------------------------------------- /src/types/menu.ts: -------------------------------------------------------------------------------- 1 | // Config types 2 | export type MenuConfOptionId = string 3 | export type MenuConfSubOptions = { name?: string; opts: MenuConfOptionId[] } 4 | export type MenuConf = (MenuConfOptionId | MenuConfSubOptions)[] 5 | export interface MenuConfs { 6 | tabs?: MenuConf 7 | bookmarks?: MenuConf 8 | tabsPanel?: MenuConf 9 | bookmarksPanel?: MenuConf 10 | } 11 | 12 | // Internal types 13 | export const enum MenuType { 14 | Tabs = 1, 15 | Bookmarks = 2, 16 | History = 3, 17 | NewTab = 6, 18 | TabsPanel = 7, 19 | BookmarksPanel = 8, 20 | Panel = 9, 21 | } 22 | export type MenuOptionType = 'option' | 'separator' 23 | export interface MenuOptionFlag { 24 | active?: boolean 25 | icon?: string 26 | onClick?: (opt: MenuOption) => void 27 | } 28 | export interface MenuOption { 29 | type?: MenuOptionType 30 | label?: string 31 | tooltip?: string 32 | icon?: string 33 | img?: string 34 | badge?: string 35 | color?: browser.ColorName 36 | inactive?: boolean 37 | sub?: MenuOption[] 38 | flag?: MenuOptionFlag 39 | keepSearching?: boolean 40 | onClick?: () => void 41 | onAltClick?: () => void 42 | } 43 | export type MenuBlockType = 'list' | 'inline' | 'sub' 44 | export interface MenuBlock { 45 | type: MenuBlockType 46 | opts: MenuOption[] 47 | name?: string 48 | } 49 | export interface MenuInvokeDetails { 50 | x: number 51 | y: number 52 | blocks: MenuBlock[] 53 | off?: () => void 54 | } 55 | -------------------------------------------------------------------------------- /src/types/storage.ts: -------------------------------------------------------------------------------- 1 | import { SettingsState, Container, Snapshot } from 'src/types' 2 | import { TabCache, FavDomain } from 'src/types' 3 | import { SidebarConfig, MenuConfs } from 'src/types' 4 | 5 | export type StoredProps = (keyof Stored)[] 6 | 7 | export interface Stored { 8 | ver?: string 9 | settings?: SettingsState 10 | containers?: Record 11 | profileID?: string 12 | 13 | tabsDataCache?: TabCache[][] 14 | 15 | favicons_01?: string[] 16 | favicons_02?: string[] 17 | favicons_03?: string[] 18 | favicons_04?: string[] 19 | favicons_05?: string[] 20 | favHashes?: number[] 21 | favDomains?: Record 22 | 23 | sidebar?: SidebarConfig 24 | 25 | snapshots?: Snapshot[] 26 | lastSnapTime?: number 27 | 28 | contextMenu?: MenuConfs 29 | 30 | sidebarCSS?: string 31 | groupCSS?: string 32 | 33 | expandedBookmarkFolders?: Record> 34 | bookmarksRecentFolders?: ID[] 35 | 36 | googleDriveFileIds?: Record 37 | } 38 | 39 | export type StorageChanges = { 40 | [key in keyof Stored]: browser.storage.StorageChange 41 | } 42 | -------------------------------------------------------------------------------- /src/types/styles.ts: -------------------------------------------------------------------------------- 1 | export type CustomCssTarget = 'sidebar' | 'group' 2 | export type CustomCssFieldName = 'sidebarCSS' | 'groupCSS' 3 | export type CustomStyles = { sidebarCSS?: string; groupCSS?: string } 4 | -------------------------------------------------------------------------------- /src/types/vue-shims.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue' 3 | const component: DefineComponent<{}, {}, any> 4 | export default component 5 | } 6 | -------------------------------------------------------------------------------- /src/types/windows.ts: -------------------------------------------------------------------------------- 1 | import { Tab } from './tabs' 2 | 3 | export interface Window extends browser.windows.Window { 4 | tabs?: Tab[] 5 | } 6 | 7 | export interface WindowChooseOption { 8 | id: ID 9 | title: string 10 | screen: string 11 | choose: () => void 12 | loaded?: boolean 13 | sel?: boolean 14 | } 15 | 16 | export interface WindowChoosingDetails { 17 | title?: string 18 | filter?: (window: Window) => boolean 19 | otherWindows?: boolean 20 | } 21 | -------------------------------------------------------------------------------- /test/env-setup.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = 'production' 2 | -------------------------------------------------------------------------------- /test/web-ext-setup.js: -------------------------------------------------------------------------------- 1 | const MsgHandlers = [] 2 | 3 | const browser = { 4 | bookmarks: {}, 5 | commands: { 6 | cmds: [], 7 | getAll: () => Promise.resolve(browser.commands.cmds), 8 | }, 9 | cookies: {}, 10 | contextualIdentities: {}, 11 | extension: { 12 | inIncognitoContext: false, 13 | }, 14 | i18n: { 15 | getUILanguage: () => 'en', 16 | }, 17 | proxy: { 18 | onRequest: {}, 19 | }, 20 | permissions: {}, 21 | runtime: { 22 | getURL: path => 'moz-extension://blablabla/' + path, 23 | sendMessage: msg => MsgHandlers.map(h => h(msg)), 24 | onMessage: { addListener: handler => MsgHandlers.push(handler) }, 25 | }, 26 | storage: { 27 | local: { 28 | data: {}, 29 | set: obj => { 30 | browser.storage.local.data = { ...browser.storage.local.data, ...obj } 31 | return Promise.resolve() 32 | }, 33 | get: key => Promise.resolve({ [key]: browser.storage.local.data[key] }), 34 | }, 35 | sync: {}, 36 | }, 37 | tabs: { 38 | captureTab: () => 'tab image', 39 | }, 40 | windows: {}, 41 | } 42 | 43 | global.browser = browser 44 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | // "noUncheckedIndexedAccess": true, 4 | "strict": true, 5 | "allowJs": false, 6 | "moduleResolution": "node", 7 | "target": "ESNext", 8 | "module": "ESNext", 9 | "removeComments": true, 10 | "preserveConstEnums": false, 11 | "types": [], 12 | "outDir": "./addon", 13 | "baseUrl": ".", 14 | "jsx": "preserve", 15 | "paths": { 16 | "src/*": ["src/*"] 17 | }, 18 | "skipDefaultLibCheck": true 19 | }, 20 | "include": ["src/**/*.ts", "src/**/*.vue"], 21 | "exclude": ["**/__test__/*"], 22 | "vueCompilerOptions": { 23 | "plugins": [ 24 | "@vue/language-plugin-pug" 25 | ] 26 | } 27 | } 28 | --------------------------------------------------------------------------------