├── .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 |
2 | .CountField(:data-active="props.value !== off" :data-inactive="props.inactive" @click="toggle")
3 | .body
4 | .label {{translate(props.label)}}
5 | .input-group(@click.stop)
6 | TextInput.text-input(
7 | :value="props.value"
8 | :line="true"
9 | :filter="valueFilter"
10 | @update:value="onInput"
11 | @change="onChange")
12 | ToggleInput.toggle-input(:value="props.value !== props.off" @update:value="toggle")
13 |
14 |
15 |
53 |
--------------------------------------------------------------------------------
/src/components/icon-select-field.vue:
--------------------------------------------------------------------------------
1 |
2 | .IconSelectField
3 | .label {{translate(props.label)}}
4 | SelectIconInput(
5 | :value="props.value"
6 | :opts="props.opts"
7 | :fill="props.optFill"
8 | @update:value="select")
9 |
10 |
11 |
27 |
--------------------------------------------------------------------------------
/src/components/icon-select-input.vue:
--------------------------------------------------------------------------------
1 |
2 | .IconSelectInput
3 | .icon(
4 | v-for="opt in opts"
5 | :data-active="opt === value"
6 | :data-color="fill"
7 | @click="select(opt)")
8 | svg: use(:xlink:href="'#' + opt")
9 |
10 |
11 |
19 |
--------------------------------------------------------------------------------
/src/components/info-field.vue:
--------------------------------------------------------------------------------
1 |
2 | .InfoField(:data-inactive="props.inactive" @click="onClick")
3 | .body
4 | .label {{translate(props.label)}}
5 | .info(v-if="props.value") {{props.value}}
6 |
7 |
8 |
18 |
--------------------------------------------------------------------------------
/src/components/loading-dots.vue:
--------------------------------------------------------------------------------
1 |
2 | .LoadingDots
3 | .loading-dots-a
4 | .loading-dots-b
5 | .loading-dots-c
6 |
7 |
--------------------------------------------------------------------------------
/src/components/text-field.vue:
--------------------------------------------------------------------------------
1 |
2 | .TextField(:data-inactive="props.inactive" @click="focus")
3 | .body
4 | .label {{translate(props.label)}}
5 | TextInput(
6 | ref="inputEl"
7 | :value="props.value"
8 | :padding="props.padding"
9 | :or="props.or"
10 | :filter="props.filter"
11 | :line="props.line"
12 | :tabindex="props.tabindex"
13 | :password="props.password"
14 | :valid="props.valid"
15 | :width="props.inputWidth"
16 | @update:value="emit('update:value', $event)"
17 | @keydown="emit('keydown', $event)")
18 | .note(v-if="props.note") {{props.note}}
19 |
20 |
21 |
71 |
--------------------------------------------------------------------------------
/src/components/toggle-input.vue:
--------------------------------------------------------------------------------
1 |
2 | .ToggleInput(:data-active="props.value" @click="toggle")
3 | .focus-el(ref="focusEl" tabindex="-1")
4 | .opt.-true: p {{translate('settings.opt_true')}}
5 | .opt.-false: p {{translate('settings.opt_false')}}
6 |
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 |
2 | footer
3 | a.github(tabindex="-1" href="https://github.com/mbnuqw/sidebery" target="_blank")
4 | svg: use(xlink:href="#icon_github")
5 | svg.logo: use(xlink:href="#icon_sidebery")
6 | a.amo(tabindex="-1" href="https://addons.mozilla.org/en-US/firefox/addon/sidebery/" target="_blank")
7 | svg: use(xlink:href="#icon_amo")
8 |
9 |
--------------------------------------------------------------------------------
/src/page.setup/components/menu-editor.option.vue:
--------------------------------------------------------------------------------
1 |
2 | .opt(:title="title"
3 | :data-separator="option.startsWith('separator')"
4 | :data-selected="selected"
5 | @click="emit('select', option)")
6 | .opt-btn.-in(
7 | v-if="isTopLvl"
8 | :title="translate('menu.editor.create_sub_tooltip')"
9 | @click.stop="emit('createSubMenu', type, option)")
10 | svg: use(xlink:href="#icon_expand")
11 |
12 | .opt-title {{shrinkedTitle}}
13 |
14 | .opt-btn(
15 | :title="translate('menu.editor.down_tooltip')"
16 | @click.stop="emit('downOpt', type, option)")
17 | svg: use(xlink:href="#icon_expand")
18 |
19 | .opt-btn.-up(
20 | :title="translate('menu.editor.up_tooltip')"
21 | @click.stop="emit('upOpt', type, option)")
22 | svg: use(xlink:href="#icon_expand")
23 |
24 | .opt-btn.-rm(
25 | :title="translate('menu.editor.disable_tooltip')"
26 | @click.stop="emit('disableOpt', type, option)")
27 | svg: use(xlink:href="#icon_remove")
28 |
29 |
30 |
61 |
--------------------------------------------------------------------------------
/src/page.setup/components/settings.group.vue:
--------------------------------------------------------------------------------
1 |
2 | section(ref="el")
3 | h2 {{translate('settings.group_title')}}
4 | span.header-shadow
5 | SelectField(
6 | label="settings.group_layout"
7 | optLabel="settings.group_layout_"
8 | v-model:value="Settings.state.groupLayout"
9 | :opts="Settings.getOpts('groupLayout')"
10 | @update:value="Settings.saveDebounced(150)")
11 |
12 |
13 |
24 |
--------------------------------------------------------------------------------
/src/page.setup/components/settings.history.vue:
--------------------------------------------------------------------------------
1 |
2 | section(ref="el")
3 | h2 {{translate('settings.history_title')}}
4 | span.header-shadow
5 | ToggleField(
6 | label="settings.load_history_on_demand"
7 | v-model:value="Settings.state.loadHistoryOnDemand"
8 | @update:value="Settings.saveDebounced(150)")
9 |
10 |
11 |
22 |
--------------------------------------------------------------------------------
/src/page.setup/components/settings.search.vue:
--------------------------------------------------------------------------------
1 |
2 | section(ref="el")
3 | h2 {{translate('settings.search_title')}}
4 | span.header-shadow
5 | SelectField(
6 | label="settings.search_bar_mode"
7 | optLabel="settings.search_bar_mode_"
8 | v-model:value="Settings.state.searchBarMode"
9 | :opts="Settings.getOpts('searchBarMode')"
10 | @update:value="Settings.saveDebounced(150)")
11 | SelectField(
12 | label="settings.search_panel_switch"
13 | optLabel="settings.search_panel_switch_"
14 | v-model:value="Settings.state.searchPanelSwitch"
15 | :opts="Settings.getOpts('searchPanelSwitch')"
16 | :folded="true"
17 | @update:value="Settings.saveDebounced(150)")
18 | InfoField(
19 | label="settings.search.shortcuts"
20 | :value="translate('settings.search.shortcuts.note')")
21 | .sub-fields
22 | TextField(
23 | label="settings.search.bookmarks_shortcut"
24 | v-model:value="Settings.state.searchBookmarksShortcut"
25 | @update:value="Settings.saveDebounced(150)")
26 | TextField(
27 | label="settings.search.history_shortcut"
28 | v-model:value="Settings.state.searchHistoryShortcut"
29 | @update:value="Settings.saveDebounced(150)")
30 |
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 |
28 |
29 |
30 |
34 |
38 |
39 |
Proxy DNS
40 |
---
41 |
42 |
43 |
47 |
48 |
Country
49 |
---
50 |
51 |
52 |
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 |
2 | #root.root.Sync(
3 | :data-native-scrollbar="Settings.state.nativeScrollbars"
4 | :data-native-scrollbars-thin="Settings.state.nativeScrollbarsThin"
5 | :data-native-scrollbars-left="Settings.state.nativeScrollbarsLeft"
6 | :data-theme="Settings.state.theme"
7 | :data-density="Settings.state.density"
8 | :data-frame-color-scheme="Styles.reactive.frameColorScheme"
9 | :data-toolbar-color-scheme="Styles.reactive.toolbarColorScheme"
10 | :data-act-el-color-scheme="Styles.reactive.actElColorScheme"
11 | :data-popup-color-scheme="Styles.reactive.popupColorScheme"
12 | :data-animations="animations"
13 | :data-syncing="Sync.reactive.syncing"
14 | :data-tabs-tree-lvl-marks="Settings.state.tabsLvlDots")
15 | .header
16 | .header-btn(@click="Sync.reload")
17 | svg.icon.-sync(): use(xlink:href="#icon_sync")
18 | .title {{translate('panel.sync.title')}}
19 | .space-filler
20 | SyncPanel
21 | NotificationsPopup
22 |
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 |
2 | .PanelViewSwitcherBar
3 | template(v-for="(btn, i) of props.conf" :key="btn.id")
4 | .btn-sep(v-if="i > 0")
5 | .view-btn(
6 | :data-active="props.panel.viewMode === btn.id"
7 | @click="switchViewMode(btn.id)")
8 | svg: use(:xlink:href="btn.icon")
9 |
10 |
11 |
34 |
--------------------------------------------------------------------------------
/src/sidebar/components/bar.pinned-tabs.vue:
--------------------------------------------------------------------------------
1 |
2 | .PinnedTabsBar(
3 | tabindex="-1"
4 | :data-empty="pinnedTabs.length === 0"
5 | :data-dnd-end="dropToEnd"
6 | data-dnd-type="pinned-bar"
7 | :data-dnd-id="panel?.id ?? NOID"
8 | @wheel="onWheel"
9 | @drop="onDrop")
10 | .tab-wrapper(v-for="id in pinnedTabs" :key="id" :data-targeted="DnD.reactive.dstPin && dropId === id")
11 | Tab(:tabId="id")
12 |
13 |
14 |
54 |
--------------------------------------------------------------------------------
/src/sidebar/components/dnd-pointer.vue:
--------------------------------------------------------------------------------
1 |
2 | .pointer(
3 | ref="pointerEl"
4 | v-show="subPanel === Sidebar.reactive.subPanelActive"
5 | :style="{ '--pointer-left': `${DnD.reactive.pointerLeft}px` }"
6 | :data-pointer="DndPointerModeNames[DnD.reactive.pointerMode]"
7 | :data-hover="DnD.reactive.pointerHover"
8 | :data-lvl="DnD.reactive.pointerLvl")
9 | .arrow(
10 | :data-expanding="DnD.reactive.pointerExpanding"
11 | @animationend="DnD.onPointerExpanded")
12 |
13 |
14 |
25 |
--------------------------------------------------------------------------------
/src/sidebar/components/dnd-tooltip.vue:
--------------------------------------------------------------------------------
1 |
2 | #drag_image.drag-image
3 | .drag-image-title(v-if="DnD.reactive.dragTooltipTitle") {{DnD.reactive.dragTooltipTitle}}
4 | .drag-image-info(v-if="DnD.reactive.dragTooltipInfo") {{DnD.reactive.dragTooltipInfo}}
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/src/sidebar/components/panel-placeholder.vue:
--------------------------------------------------------------------------------
1 |
2 | Transition(name="panel-placeholder")
3 | .PanelPlaceholder(v-if="props.isLoading || isMsg || isNotPerm" :data-loading="isLoading")
4 | .perm-warn(v-if="isNotPerm && perm")
5 | .perm-warn-msg {{permMsg}}
6 | .btn.perm-warn-btn(@click="requestPermission") Grant permissions
7 | LoadingDots(v-else-if="props.isLoading")
8 | .msg(v-else-if="props.isMsg") {{props.msg}}
9 |
10 |
11 |
36 |
--------------------------------------------------------------------------------
/src/sidebar/components/panel.sync.vue:
--------------------------------------------------------------------------------
1 |
2 | .SyncPanel.panel
3 | ScrollBox(ref="scrollBox")
4 | .content(v-if="!isHidden")
5 | SyncEntryComp(v-for="entry in Sync.reactive.entries" :key="entry.id" :entry="entry")
6 | LoadingDots(v-if="state.syncLoading")
7 |
8 | PanelPlaceholder(
9 | :isLoading="Sync.reactive.loading"
10 | :isMsg="!Sync.reactive.entries.length"
11 | :msg="translate('panel.nothing')")
12 |
13 |
14 |
53 |
--------------------------------------------------------------------------------
/src/sidebar/components/popup.confirm.vue:
--------------------------------------------------------------------------------
1 |
2 | .Confirm.popup-container(@click="Popups.finishConfirmation(false)")
3 | .popup(@click.stop)
4 | h2 {{translate('confirm.warn_title')}}
5 | .msg {{Popups.reactive.confirm?.msg}}
6 | .ctrls
7 | .btn(@click="Popups.finishConfirmation(true)") {{translate('btn.yes')}}
8 | .btn(@click="Popups.finishConfirmation(false)") {{translate('btn.no')}}
9 |
10 |
11 |
15 |
--------------------------------------------------------------------------------
/src/sidebar/components/popup.windows.vue:
--------------------------------------------------------------------------------
1 |
2 | .WindowsPopup.popup-container(:data-ready="isReady" @click="cancel")
3 | .popup(@click.stop="")
4 | h2(v-if="Windows.reactive.choosingTitle") {{Windows.reactive.choosingTitle}}
5 | .list
6 | ScrollBox
7 | .box(
8 | v-for="(win, i) in Windows.reactive.choosing"
9 | :key="win.id"
10 | :data-no-screenshot="!win.screen"
11 | :data-selected="win.sel")
12 | .win(@click.stop="win.choose")
13 | .window-title {{normalizeWinTitle(win.title)}}
14 | img(v-if="win.screen" :src="win.screen" @load="onScreenLoad(i)")
15 | LoadingDots(v-if="!Windows.reactive.choosing?.length")
16 | .ctrls
17 | .btn.-warn(@click="cancel") Cancel
18 |
19 |
20 |
57 |
--------------------------------------------------------------------------------
/src/sidebar/components/sub-list-title.vue:
--------------------------------------------------------------------------------
1 |
2 | .SubListTitle(
3 | :id="id"
4 | :data-folded="!expanded"
5 | :data-sel="Sidebar.reactive.selectedHeader === id"
6 | @click="emit('click', $event)")
7 | .body
8 | .title {{title}}
9 | .len {{len}}
10 | svg.expand: use(xlink:href="#icon_expand")
11 |
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 |
--------------------------------------------------------------------------------