mirror of
https://github.com/zen-browser/desktop.git
synced 2026-05-27 23:35:09 +00:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60318bb64c | ||
|
|
23ceaf7721 | ||
|
|
eb176edf8b | ||
|
|
9c1164b9bc | ||
|
|
036cfb187c | ||
|
|
c4948ee0cd | ||
|
|
4d56da4319 | ||
|
|
f718d4414e | ||
|
|
25c5740331 | ||
|
|
64fc35658d | ||
|
|
dac4575a91 | ||
|
|
58ffcd13c8 | ||
|
|
0ee960e3a3 | ||
|
|
7c8ccdedd4 | ||
|
|
ea35896484 | ||
|
|
dbf6daebdc | ||
|
|
3f0f07ac37 | ||
|
|
d25a99cd21 | ||
|
|
efae7418c4 | ||
|
|
34c2618ca0 | ||
|
|
84b7cf8ddd | ||
|
|
0d816b3cc2 | ||
|
|
ad4eeee55a | ||
|
|
ad74b55dbf | ||
|
|
5ffb2d8d69 | ||
|
|
5a91c0c70b | ||
|
|
3831af027e | ||
|
|
ee5c1894eb | ||
|
|
e31d91282b | ||
|
|
32b355595c | ||
|
|
b5b31c02d0 | ||
|
|
bcdb905ad6 | ||
|
|
3044b409fa | ||
|
|
747dd3d4bc | ||
|
|
49225cf685 | ||
|
|
0f4abf2237 | ||
|
|
657d03821f | ||
|
|
8fc2ecbb66 | ||
|
|
d78dcdddaf |
32
.github/workflows/code-linter.yml
vendored
32
.github/workflows/code-linter.yml
vendored
@@ -28,20 +28,32 @@ jobs:
|
||||
with:
|
||||
node-version-file: ".nvmrc"
|
||||
|
||||
- name: Setup and run autopep8
|
||||
if: ${{ contains(join(github.event.commits.*.modified, ' '), '.py') || contains(join(github.event.commits.*.added, ' '), '.py') || contains(join(github.event.commits.*.removed, ' '), '.py') }}
|
||||
run: |
|
||||
sudo apt install python3-autopep8
|
||||
autopep8 --diff scripts/ src/
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Download Firefox
|
||||
env:
|
||||
ZEN_DOWNLOAD_DONT_INIT_GIT: "1"
|
||||
- name: Restore Surfer engine cache
|
||||
id: surfer-engine-cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .surfer/engine/
|
||||
key: surfer-engine-${{ hashFiles('surfer.json') }}
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
npm run download
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Download Firefox
|
||||
run: npm run download
|
||||
|
||||
- name: Import patches
|
||||
run: npm run import
|
||||
|
||||
- name: Add .hgignore file to the engine dir
|
||||
run: touch engine/.hgignore
|
||||
|
||||
- name: Run Bootstrap
|
||||
run: npm run bootstrap
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
24
.github/workflows/pr-test.yml
vendored
24
.github/workflows/pr-test.yml
vendored
@@ -28,13 +28,29 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Restore Surfer engine cache
|
||||
id: surfer-engine-cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .surfer/engine/
|
||||
key: surfer-engine-${{ hashFiles('surfer.json') }}
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Download Firefox and dependencies
|
||||
env:
|
||||
ZEN_DOWNLOAD_DONT_INIT_GIT: "1"
|
||||
run: npm run download
|
||||
|
||||
- name: Run linting
|
||||
run: npm run lint
|
||||
- name: Run Bootstrap
|
||||
run: npm run bootstrap
|
||||
|
||||
- name: Add .hgignore file to the engine dir
|
||||
run: touch engine/.hgignore
|
||||
|
||||
- name: Import patches
|
||||
run: npm run import
|
||||
|
||||
- name: Run linting
|
||||
run: npm run lint
|
||||
|
||||
2
.github/workflows/src/release-build.sh
vendored
2
.github/workflows/src/release-build.sh
vendored
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -xe
|
||||
|
||||
|
||||
20
.github/workflows/sync-upstream.yml
vendored
20
.github/workflows/sync-upstream.yml
vendored
@@ -60,6 +60,13 @@ jobs:
|
||||
npm run surfer -- ci --brand release
|
||||
fi
|
||||
|
||||
- name: Restore Surfer engine cache
|
||||
id: surfer-engine-cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .surfer/engine/
|
||||
key: surfer-engine-${{ hashFiles('surfer.json') }}
|
||||
|
||||
- name: Download Firefox and dependencies
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: npm run download
|
||||
@@ -73,8 +80,13 @@ jobs:
|
||||
npm run sync
|
||||
fi
|
||||
|
||||
- name: Install autopep8
|
||||
run: sudo apt install python3-autopep8
|
||||
- name: Run Import
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: npm run import
|
||||
|
||||
- name: Run Bootstrap
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: npm run bootstrap
|
||||
|
||||
- name: Install requirements
|
||||
run: pip3 install -r requirements.txt
|
||||
@@ -82,7 +94,7 @@ jobs:
|
||||
- name: Check if any files changed
|
||||
id: git-check
|
||||
run: |
|
||||
npm run pretty
|
||||
npm run lint:fix
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
echo "files_changed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
@@ -119,7 +131,7 @@ jobs:
|
||||
- name: Run formatter
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: |
|
||||
npm run pretty
|
||||
npm run lint:fix
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -24,3 +24,4 @@ target/
|
||||
locales/firefox-l10n/
|
||||
|
||||
!src/toolkit/themes/shared/design-system/dist/
|
||||
.DS_Store
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
engine/
|
||||
|
||||
**/*.html
|
||||
**/*.xhtml
|
||||
**/*.inc.xhtml
|
||||
**/*.bundle.min.js
|
||||
**/*.min.js
|
||||
**/*.min.mjs
|
||||
|
||||
**/*.svg
|
||||
|
||||
**/*.inc.css
|
||||
|
||||
surfer.json
|
||||
|
||||
src/zen/tests/mochitests/*
|
||||
|
||||
src/browser/app/profile/*.js
|
||||
pnpm-lock.yaml
|
||||
|
||||
**/engine/
|
||||
|
||||
docs/issue-metrics/*.md
|
||||
|
||||
.husky/
|
||||
|
||||
# Some CSS files are preprocessed and prettier doesn't handle them well
|
||||
# We also dont want to format the CSS files that are generated by the build
|
||||
src/zen/tabs/zen-tabs.css
|
||||
src/zen/common/styles/zen-theme.css
|
||||
src/zen/compact-mode/zen-compact-mode.css
|
||||
src/zen/common/ZenEmojis.mjs
|
||||
|
||||
src/zen/split-view/zen-decks.css
|
||||
src/zen/workspaces/zen-workspaces.css
|
||||
src/zen/common/styles/zen-toolbar.css
|
||||
|
||||
*.inc
|
||||
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"bracketSameLine": true,
|
||||
"endOfLine": "lf",
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"jsxSingleQuote": false,
|
||||
"semi": true,
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-sh"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.css",
|
||||
"options": {
|
||||
"parser": "css",
|
||||
"printWidth": 160
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -34,8 +34,8 @@ Zen is a firefox-based browser with the aim of pushing your productivity to a ne
|
||||
|
||||
### Firefox Versions
|
||||
|
||||
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `148.0`! 🚀
|
||||
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 148.0`!
|
||||
- [`Release`](https://zen-browser.app/download) - Is currently built using Firefox version `148.0.2`! 🚀
|
||||
- [`Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 148.0.2`!
|
||||
|
||||
### Contributing
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
40d4c2395112d4188721e69d338ee75bded8858a
|
||||
7b8f3620beb1de157d972de32f9f34320f0ae189
|
||||
@@ -23,6 +23,9 @@ mkdir windsign-temp -ErrorAction SilentlyContinue
|
||||
# echo "Downloaded git objects repo to"
|
||||
#} -Verbose -ArgumentList $PWD -Debug
|
||||
|
||||
$env:SURFER_MOZCONFIG_ONLY="1"
|
||||
$env:SURFER_SIGNING_MODE=""
|
||||
|
||||
Start-Job -Name "DownloadGitl10n" -ScriptBlock {
|
||||
param($PWD)
|
||||
cd $PWD
|
||||
@@ -31,14 +34,11 @@ Start-Job -Name "DownloadGitl10n" -ScriptBlock {
|
||||
echo "Fetched l10n and Firefox's one"
|
||||
} -Verbose -ArgumentList $PWD -Debug
|
||||
|
||||
Start-Job -Name "SurferInit" -ScriptBlock {
|
||||
param($PWD)
|
||||
cd $PWD
|
||||
npm run import -- --verbose
|
||||
$surferJson = Get-Content surfer.json | ConvertFrom-Json
|
||||
$version = $surferJson.brands.release.release.displayVersion
|
||||
npm run ci -- $version
|
||||
} -Verbose -ArgumentList $PWD -Debug
|
||||
$surferJson = Get-Content surfer.json | ConvertFrom-Json
|
||||
$version = $surferJson.brands.release.release.displayVersion
|
||||
npm run ci -- $version
|
||||
npm run import -- --verbose
|
||||
npm run build
|
||||
|
||||
echo "Downloading artifacts info"
|
||||
$artifactsInfo=gh api repos/zen-browser/desktop/actions/runs/$GithubRunId/artifacts
|
||||
@@ -120,7 +120,6 @@ signtool.exe sign /n "$SignIdentity" /t http://time.certum.pl/ /fd sha256 /v $fi
|
||||
$env:ZEN_RELEASE="true"
|
||||
$env:SURFER_SIGNING_MODE="true"
|
||||
$env:SCCACHE_GHA_ENABLED="false"
|
||||
Wait-Job -Name "SurferInit"
|
||||
Wait-Job -Name "DownloadGitl10n"
|
||||
|
||||
function SignAndPackage($name) {
|
||||
|
||||
217
docs/issue-metrics/2026_2026-02-01..2026-02-28.md
Normal file
217
docs/issue-metrics/2026_2026-02-01..2026-02-28.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# Issue Metrics
|
||||
|
||||
| Metric | Average | Median | 90th percentile |
|
||||
| --- | --- | --- | ---: |
|
||||
| Time to first response | 1 day, 1:26:40 | 2:07:50 | 2 days, 5:33:54 |
|
||||
| Time to close | 1 day, 12:18:56 | 3:30:42 | 4 days, 7:35:38 |
|
||||
|
||||
| Metric | Count |
|
||||
| --- | ---: |
|
||||
| Number of items that remain open | 97 |
|
||||
| Number of items closed | 102 |
|
||||
| Total number of items created | 199 |
|
||||
|
||||
| Title | URL | Time to first response | Time to close |
|
||||
| --- | --- | --- | --- |
|
||||
| Zen browser highlight elements by itself | https://github.com/zen-browser/desktop/issues/12551 | 5:54:36 | None |
|
||||
| pasted url revert to old one automaticaly ? | https://github.com/zen-browser/desktop/issues/12548 | 6:47:54 | None |
|
||||
| chat.mistral.ai - site is not usable | https://github.com/zen-browser/desktop/issues/12547 | 10:45:42 | None |
|
||||
| Horizontal Scrolling with mouse wheel is not working | https://github.com/zen-browser/desktop/issues/12545 | None | 1:30:19 |
|
||||
| The Text color of search bar when press the "Ctrl + f" | https://github.com/zen-browser/desktop/issues/12537 | None | None |
|
||||
| Buggy Native Popover for Tab Previews on Twilight | https://github.com/zen-browser/desktop/issues/12529 | 0:06:41 | 0:06:41 |
|
||||
| Can't drag files directly from Downloads panel | https://github.com/zen-browser/desktop/issues/12520 | 11:56:10 | 11:56:24 |
|
||||
| Repeated SIGSEGV in libxul.so on Linux (1.18.10b, Fedora 43, AMD) | https://github.com/zen-browser/desktop/issues/12516 | None | None |
|
||||
| Previously closed windows recovery option missing | https://github.com/zen-browser/desktop/issues/12515 | 1:40:19 | 1:40:20 |
|
||||
| Empty Spaces after waking laptop | https://github.com/zen-browser/desktop/issues/12512 | 4:14:32 | 1 day, 1:42:28 |
|
||||
| New tab shortcut shows search input instead of tab input | https://github.com/zen-browser/desktop/issues/12510 | 8:46:21 | 8:46:21 |
|
||||
| Folder tree breaks with live folders fetch | https://github.com/zen-browser/desktop/issues/12509 | 0:08:50 | 8:11:04 |
|
||||
| Tabs bar shakes in compact mode | https://github.com/zen-browser/desktop/issues/12505 | 0:02:08 | None |
|
||||
| Youtube Playlist issue | https://github.com/zen-browser/desktop/issues/12502 | None | 18:54:24 |
|
||||
| Maps with very much data are very laggy | https://github.com/zen-browser/desktop/issues/12501 | 3:09:58 | 16:56:17 |
|
||||
| Allow changing interface font for generic Linux tarball | https://github.com/zen-browser/desktop/issues/12500 | 1:05:58 | None |
|
||||
| The transparent gradient background suddenly covers the current tab | https://github.com/zen-browser/desktop/issues/12497 | 8:59:58 | 8:59:58 |
|
||||
| Obscene memory leak on Mac | https://github.com/zen-browser/desktop/issues/12496 | 0:35:11 | None |
|
||||
| top tool bar and close/minimize buttons on title bar overlap on windows | https://github.com/zen-browser/desktop/issues/12495 | 1 day, 16:34:34 | None |
|
||||
| Tabs in essentials disappear after closing Zen | https://github.com/zen-browser/desktop/issues/12493 | 14:53:54 | None |
|
||||
| When you open a new window using the taskbar icon, it mirrors the tabs of another window. | https://github.com/zen-browser/desktop/issues/12492 | 0:11:21 | 0:11:21 |
|
||||
| using my GoBack mouse button switches workspaces | https://github.com/zen-browser/desktop/issues/12491 | 0:03:40 | None |
|
||||
| closing Folder tabs doesn't close them | https://github.com/zen-browser/desktop/issues/12490 | 0:08:26 | 0:08:26 |
|
||||
| Zen compact hover mode time increase not respected | https://github.com/zen-browser/desktop/issues/12489 | 0:06:19 | 0:06:19 |
|
||||
| White dots spreading everywhere on any website visited in Zen Browser, reset when interacting with UI layer; duplicate contour lines appearing at the same time as the dots on the Zen Browser UI - Windows 11 | https://github.com/zen-browser/desktop/issues/12488 | None | 2 days, 13:52:50 |
|
||||
| What just happened to my tab??? (Also when I close Zen browser while I watching YouTube, the audio still exist, wth?) | https://github.com/zen-browser/desktop/issues/12486 | 0:27:29 | None |
|
||||
| Reddit multi word enter search won't work | https://github.com/zen-browser/desktop/issues/12485 | None | None |
|
||||
| Use a different default search engine in private windows defaults to true | https://github.com/zen-browser/desktop/issues/12484 | None | 1:52:44 |
|
||||
| ALSA support disabled, no sound on ALSA only systems | https://github.com/zen-browser/desktop/issues/12483 | 10:13:00 | None |
|
||||
| Addressbar closing when inputing german Umlauts with us_intl keymap | https://github.com/zen-browser/desktop/issues/12482 | 2:18:36 | 2:18:36 |
|
||||
| Zen Browser Tabs: Backgroung Image is not working | https://github.com/zen-browser/desktop/issues/12479 | 7:28:03 | 17:51:35 |
|
||||
| bookmarks keep vanishing | https://github.com/zen-browser/desktop/issues/12478 | 8:34:20 | None |
|
||||
| The menu for my browser history button is moving down in KDE Plasma. | https://github.com/zen-browser/desktop/issues/12475 | None | 1:43:31 |
|
||||
| Zen Browser is being blocked by BattlEye anti-cheat during game launch on Windows 11. | https://github.com/zen-browser/desktop/issues/12473 | 0:06:23 | None |
|
||||
| CRUNCHYROLL NOT WORKING | https://github.com/zen-browser/desktop/issues/12467 | 0:05:42 | 0:05:42 |
|
||||
| Holding rightclick will caues wrong mouse position | https://github.com/zen-browser/desktop/issues/12466 | None | None |
|
||||
| Battery Drain MacOS - High CPU usage | https://github.com/zen-browser/desktop/issues/12464 | 3 days, 19:23:37 | None |
|
||||
| Logged out of all Google accounts and can't log back in. | https://github.com/zen-browser/desktop/issues/12462 | 20:50:59 | None |
|
||||
| Blank Window and Session Loss After Update | https://github.com/zen-browser/desktop/issues/12460 | 0:05:20 | None |
|
||||
| Sometimes web lagging for a few second | https://github.com/zen-browser/desktop/issues/12458 | 0:00:47 | None |
|
||||
| Mods don't work anymore | https://github.com/zen-browser/desktop/issues/12455 | 0:36:29 | 2:08:08 |
|
||||
| Auto Update Failing To Update (Message Update Failed) | https://github.com/zen-browser/desktop/issues/12454 | 2:55:11 | 2:55:11 |
|
||||
| Setting up keyboard shortcuts does not recognize azerty keyboard | https://github.com/zen-browser/desktop/issues/12451 | 0:12:44 | None |
|
||||
| External links open new window with duplicated tabs when browser is minimized on Windows | https://github.com/zen-browser/desktop/issues/12450 | 6:32:08 | None |
|
||||
| Browser doesn't know where mouse is until clicking out of the browser | https://github.com/zen-browser/desktop/issues/12447 | None | None |
|
||||
| Beginning w/ v1.18.8b (?) my navigation started floating/popping/hiding; never asked for that. Then v1.18.9b (?) removed all my tabs incl auto/pinned | https://github.com/zen-browser/desktop/issues/12443 | 1:13:56 | 1:18:00 |
|
||||
| Bookmarks not shown on site pages | https://github.com/zen-browser/desktop/issues/12442 | 0:01:11 | 0:01:11 |
|
||||
| Side bar flickering | https://github.com/zen-browser/desktop/issues/12441 | None | None |
|
||||
| Sidebar should not hide when mouse pointer is still at the edge of the screen | https://github.com/zen-browser/desktop/issues/12439 | 0:08:24 | None |
|
||||
| Zen not respecting output audio device switching in Windows | https://github.com/zen-browser/desktop/issues/12438 | None | None |
|
||||
| New tab does not make a new tab - it only activates the URL bar | https://github.com/zen-browser/desktop/issues/12432 | 0:26:23 | 0:26:23 |
|
||||
| ZEN Ignoring DNS over HTTPS OFF | https://github.com/zen-browser/desktop/issues/12429 | 0:29:20 | None |
|
||||
| The search window does not appear until you start typing | https://github.com/zen-browser/desktop/issues/12428 | 1:42:23 | 5 days, 22:42:30 |
|
||||
| Toolbar icons overflow after uninstalling extension (requires restart to fix) | https://github.com/zen-browser/desktop/issues/12427 | 6:05:59 | 6:05:58 |
|
||||
| Side Tab Flickering when minimized from full view - faced in mac desktop browser | https://github.com/zen-browser/desktop/issues/12425 | 4:54:13 | None |
|
||||
| buggy Tabs drag and drop | https://github.com/zen-browser/desktop/issues/12423 | 0:28:12 | None |
|
||||
| Spaces dissapear suddently | https://github.com/zen-browser/desktop/issues/12422 | 0:07:36 | 4 days, 0:53:47 |
|
||||
| Tabs become New Tab when using Window Sync | https://github.com/zen-browser/desktop/issues/12421 | 2 days, 13:53:49 | 3 days, 15:49:00 |
|
||||
| Closed the browser after a glitch, now the app remains full white | https://github.com/zen-browser/desktop/issues/12420 | 0:04:32 | 1 day, 2:01:15 |
|
||||
| Search bar overflow over main screen from pining to overflow menu but also breaks ui in recreating | https://github.com/zen-browser/desktop/issues/12419 | None | None |
|
||||
| Closing Sidebar Causes Unexpected Border Increase on the Other Side. | https://github.com/zen-browser/desktop/issues/12418 | 0:25:14 | None |
|
||||
| Persistent Favicon Inconsistency/Tint on GitHub Bookmarks | https://github.com/zen-browser/desktop/issues/12415 | 1 day, 22:54:53 | None |
|
||||
| Sometimes, the right-click menu for links will keep shifting to the right | https://github.com/zen-browser/desktop/issues/12413 | 6:45:26 | 10:55:38 |
|
||||
| AppImage lacks version metadata, preventing AppImage update detection | https://github.com/zen-browser/desktop/issues/12412 | 13:17:50 | 8:27:29 |
|
||||
| [Windows] Launching a new window (Ctrl + N) replicates the same tabs on the new window | https://github.com/zen-browser/desktop/issues/12411 | 11:10:43 | 11:10:43 |
|
||||
| Tab preview text illegible in front of light background | https://github.com/zen-browser/desktop/issues/12410 | 11:14:21 | None |
|
||||
| Temporary Containers broke with update | https://github.com/zen-browser/desktop/issues/12409 | 1:57:05 | 14:06:01 |
|
||||
| Zen doesn't work with Simple Tab Groups | https://github.com/zen-browser/desktop/issues/12408 | 4:58:31 | None |
|
||||
| Unable to set "Copy Current URL" to ctrl+shift+INSERT | https://github.com/zen-browser/desktop/issues/12406 | None | None |
|
||||
| Browser Toolbox Error Loading | https://github.com/zen-browser/desktop/issues/12405 | 5:30:27 | 5:30:27 |
|
||||
| Restoring Split Tabs Ignored | https://github.com/zen-browser/desktop/issues/12403 | 0:14:37 | None |
|
||||
| Windows: Scroll bar in tab list causes layout shift when always show scroll bars is enabled | https://github.com/zen-browser/desktop/issues/12402 | 2 days, 3:59:15 | None |
|
||||
| Trash icon appears in ‘Change Icon’ menu for folders with no icon | https://github.com/zen-browser/desktop/issues/12401 | None | 8 days, 11:45:52 |
|
||||
| Window sync has been forced back on | https://github.com/zen-browser/desktop/issues/12400 | 0:47:07 | 0:47:07 |
|
||||
| Toolbar not opening when approaching with mouse to fast | https://github.com/zen-browser/desktop/issues/12398 | None | None |
|
||||
| Can't use Proton Pass because of second password | https://github.com/zen-browser/desktop/issues/12393 | None | None |
|
||||
| Can't Customize toolbar on "only sidebar" configuration | https://github.com/zen-browser/desktop/issues/12391 | None | None |
|
||||
| Sync deletes tab (kind of) | https://github.com/zen-browser/desktop/issues/12390 | 9 days, 7:25:30 | None |
|
||||
| Please allow us to increase the font size on the left tabs. | https://github.com/zen-browser/desktop/issues/12388 | 0:52:26 | 0:52:26 |
|
||||
| Vertical Sidebar starts 'oscillating' when it is reduced in size. | https://github.com/zen-browser/desktop/issues/12387 | 0:05:02 | 0:05:41 |
|
||||
| [Regression] Severe stuttering and long loading on Bilibili (4K) in v1.18.7b | https://github.com/zen-browser/desktop/issues/12386 | 8 days, 5:05:17 | None |
|
||||
| [macOS] Now Playing widget completely non-functional (works in Firefox) | https://github.com/zen-browser/desktop/issues/12385 | 1:16:07 | 1 day, 23:03:30 |
|
||||
| responsive design mode can't be enlarged by zooming | https://github.com/zen-browser/desktop/issues/12381 | 11 days, 16:50:20 | None |
|
||||
| Pinned tab under a folder, opens and redirect to a new regular tab | https://github.com/zen-browser/desktop/issues/12379 | 2:37:39 | None |
|
||||
| xdg-open fails to open files in existing Zen instance (Arch Linux and Hyprland) | https://github.com/zen-browser/desktop/issues/12378 | 23:23:25 | None |
|
||||
| Sidebar coloring issues in private windows | https://github.com/zen-browser/desktop/issues/12377 | None | None |
|
||||
| [Bug] Youtube shorts notplaying properly, and when using the shortcut "I' it gives an error. | https://github.com/zen-browser/desktop/issues/12376 | 13:44:07 | None |
|
||||
| Sometimes, when opening a new tab, M4 and M5 buttons change spaces | https://github.com/zen-browser/desktop/issues/12375 | 0:41:41 | 0:41:41 |
|
||||
| Private Windows don't function with Window Sync | https://github.com/zen-browser/desktop/issues/12374 | 0:33:47 | 0:33:47 |
|
||||
| Passkey from qr code not showing on widows 10 os | https://github.com/zen-browser/desktop/issues/12372 | None | None |
|
||||
| Relatively Low Audio Volume | https://github.com/zen-browser/desktop/issues/12370 | None | None |
|
||||
| Workspace icon highlight missing after latest update | https://github.com/zen-browser/desktop/issues/12368 | 1:49:10 | 1:49:15 |
|
||||
| Prime Video | https://github.com/zen-browser/desktop/issues/12365 | 0:18:36 | 0:18:36 |
|
||||
| Taskbar Tabs create semi-transparent, empty, non-closeable windows | https://github.com/zen-browser/desktop/issues/12364 | 1:17:21 | None |
|
||||
| [Bug] Enterprise Policies via macOS Managed Preferences (.plist) are not recognized | https://github.com/zen-browser/desktop/issues/12363 | None | None |
|
||||
| Misaligned video fullscreen mode for 2 monitors | https://github.com/zen-browser/desktop/issues/12362 | 2 days, 5:21:33 | None |
|
||||
| Choppy audio on YouTube when using a external DAC | https://github.com/zen-browser/desktop/issues/12361 | 2 days, 5:21:25 | 2 days, 5:47:20 |
|
||||
| Performance difference between appimage and Flatpak | https://github.com/zen-browser/desktop/issues/12357 | 0:01:34 | None |
|
||||
| "Close Pinned Tab Shortcut Behavior" ignored for "Places" tab | https://github.com/zen-browser/desktop/issues/12353 | 15 days, 10:51:28 | None |
|
||||
| Menu flickers when pressed | https://github.com/zen-browser/desktop/issues/12352 | 9 days, 0:49:56 | None |
|
||||
| Closing, Minimizing, and Maximizing Buttons squished | https://github.com/zen-browser/desktop/issues/12351 | 0:09:14 | 0:09:14 |
|
||||
| New Tab bug on mac | https://github.com/zen-browser/desktop/issues/12350 | 0:02:33 | 0:02:32 |
|
||||
| Redirect notification toast overlaps right sidebar | https://github.com/zen-browser/desktop/issues/12348 | None | 13:39:22 |
|
||||
| macOS: close/minimize/maximize buttons are not displayed correctly | https://github.com/zen-browser/desktop/issues/12347 | 0:15:49 | 0:15:49 |
|
||||
| After updating to 1.18.6b, minimize, maximize and close buttons are squished in Windows | https://github.com/zen-browser/desktop/issues/12346 | 0:09:07 | 0:09:56 |
|
||||
| Layout bug for minimize/maximize/close window buttons on Windows 11 | https://github.com/zen-browser/desktop/issues/12345 | 0:11:27 | 0:11:28 |
|
||||
| Disabling windows sync still results in same tabs being displayed throught multiple window sessions when restarting/restoring | https://github.com/zen-browser/desktop/issues/12344 | None | 0:20:21 |
|
||||
| Picture-in-picture not working as intended | https://github.com/zen-browser/desktop/issues/12342 | 3:39:41 | 1 day, 2:32:57 |
|
||||
| Icons aren't displaying correctly | https://github.com/zen-browser/desktop/issues/12340 | None | 5:45:13 |
|
||||
| Workspaces aren't syncing to a new device | https://github.com/zen-browser/desktop/issues/12339 | 1:07:18 | 6:26:52 |
|
||||
| All tabs and folders are missing after update to 1.18.5b | https://github.com/zen-browser/desktop/issues/12337 | 8:49:51 | 8:49:51 |
|
||||
| macOS profile lost pinned tabs and Essentials after Windows sync – folders remain but are empty | https://github.com/zen-browser/desktop/issues/12336 | 9:29:24 | None |
|
||||
| Zen misses some color support | https://github.com/zen-browser/desktop/issues/12335 | 0:45:02 | 0:45:02 |
|
||||
| Disabled "sync tabs" loose tabs | https://github.com/zen-browser/desktop/issues/12333 | 4:05:24 | None |
|
||||
| MacOs: Intel-based Mac Pro - Zen fails to launch (GPU subprocess / IPC timeouts) | https://github.com/zen-browser/desktop/issues/12331 | None | None |
|
||||
| Zen launch error | https://github.com/zen-browser/desktop/issues/12330 | None | 0:39:18 |
|
||||
| When I attempted to rename the workspace, the compact mode failed and I was unable to enter the compact mode again. | https://github.com/zen-browser/desktop/issues/12329 | 3:21:05 | 3:21:05 |
|
||||
| Cannot properly position or resize Zen with certain window managers | https://github.com/zen-browser/desktop/issues/12327 | None | None |
|
||||
| Space resets when closing window (but not quitting) after clearing browser history | https://github.com/zen-browser/desktop/issues/12326 | 0:46:52 | 14:27:39 |
|
||||
| New tabs don't change tab title | https://github.com/zen-browser/desktop/issues/12318 | 10:51:08 | None |
|
||||
| Weird reopen closed tab behaviour for folders | https://github.com/zen-browser/desktop/issues/12316 | None | None |
|
||||
| Per Workspace Essentials No Longer Work. | https://github.com/zen-browser/desktop/issues/12313 | 0:54:50 | 2:25:53 |
|
||||
| Are Spaces supposed to sync between different devices? | https://github.com/zen-browser/desktop/issues/12311 | 1:26:09 | 1:26:09 |
|
||||
| Open previous windows and tabs settings / continue where you left off being ignored. | https://github.com/zen-browser/desktop/issues/12307 | 12:51:38 | 13:53:11 |
|
||||
| local access disappeared after 18.5 | https://github.com/zen-browser/desktop/issues/12305 | 16:24:35 | None |
|
||||
| Transparency is weird on macOS | https://github.com/zen-browser/desktop/issues/12303 | 1:16:12 | None |
|
||||
| Vertical Sidebar flickering/jittering during interaction | https://github.com/zen-browser/desktop/issues/12299 | 3:23:55 | None |
|
||||
| "Sync only pinned tabs in workspaces" breaks "Open previous windows and tabs" | https://github.com/zen-browser/desktop/issues/12297 | 0:05:40 | 10:53:40 |
|
||||
| Github Actions Artifacts downloads do not work on Zen | https://github.com/zen-browser/desktop/issues/12296 | None | None |
|
||||
| Zen menu bar items take excessive horizontal space compared to other apps | https://github.com/zen-browser/desktop/issues/12294 | None | None |
|
||||
| Workspaces lost after upgrade to 1.18.5b (Firefox 147.0.3) (64-bit) on Windows 11 Pro Intel | https://github.com/zen-browser/desktop/issues/12293 | 3:33:29 | 3:33:29 |
|
||||
| Kernel panic on macOS Sequoia 15.7.3 when running Zen | https://github.com/zen-browser/desktop/issues/12290 | None | None |
|
||||
| Opening a GitHub CodeSpace in the Browser throws a "Oh No, it looks like youre offline!" error tho i have a stable Internet connection, and it worked on older Versions of Zen before. Chrome on the same device/internet works. | https://github.com/zen-browser/desktop/issues/12288 | None | None |
|
||||
| Zen does not read privacy.fingerprintingProtection from user.js | https://github.com/zen-browser/desktop/issues/12286 | 1:44:38 | 7:13:24 |
|
||||
| Closing a window lead sometimes to window sync to stop working | https://github.com/zen-browser/desktop/issues/12284 | None | None |
|
||||
| Pinned tabs reset to incorrect URL (pinned URL changes) | https://github.com/zen-browser/desktop/issues/12281 | 0:00:55 | None |
|
||||
| Compact mode non hide stuck | https://github.com/zen-browser/desktop/issues/12279 | 15:23:06 | None |
|
||||
| Recently closed windows/undo close window missing | https://github.com/zen-browser/desktop/issues/12278 | 4 days, 8:20:17 | 4 days, 8:20:17 |
|
||||
| Opening about: pages causes 'new tab' bug with window sync | https://github.com/zen-browser/desktop/issues/12277 | 9 days, 16:39:47 | None |
|
||||
| arm64 Flatpak compositor crash on ChromeOS Crostini (virgl / Mesa 25.x regression) | https://github.com/zen-browser/desktop/issues/12276 | 8 days, 18:31:53 | None |
|
||||
| YouTube freezes when switching audio output in fxSound | https://github.com/zen-browser/desktop/issues/12275 | None | None |
|
||||
| Button missing: Hamburger Menu > History > Restore Previous Session | https://github.com/zen-browser/desktop/issues/12272 | 0:10:35 | None |
|
||||
| Next/Prev Tab Shortcut Conflict | https://github.com/zen-browser/desktop/issues/12267 | 0:03:09 | 0:03:09 |
|
||||
| 1.18.5b Release Download Not Found | https://github.com/zen-browser/desktop/issues/12266 | 0:13:04 | 0:13:04 |
|
||||
| Viedo streaming websites become unresponsive when multiple instances are open | https://github.com/zen-browser/desktop/issues/12265 | None | None |
|
||||
| All workspaces deleted upon v1.18.5b installation | https://github.com/zen-browser/desktop/issues/12261 | 1:07:39 | 3:40:07 |
|
||||
| Zen fails to start with sync only pinned tabs | https://github.com/zen-browser/desktop/issues/12260 | 0:04:34 | 0:41:21 |
|
||||
| Thunderbird cannot open a new Zen window when clicking a link | https://github.com/zen-browser/desktop/issues/12259 | 14:35:21 | None |
|
||||
| zen.urlbar.replace-newtab = False issues with new windows and tab syncing | https://github.com/zen-browser/desktop/issues/12258 | 2 days, 7:24:59 | None |
|
||||
| Shortcuts Icon's not working | https://github.com/zen-browser/desktop/issues/12257 | 1 day, 7:22:00 | 15 days, 8:21:20 |
|
||||
| ADD A METHOD TO DISABLE UPDATES , IM LITERALLY USING A TASK SCHEDULER TO DELETE YOUR STUPID UPDATES FOLDER AND YOU STILL FIND A WAY | https://github.com/zen-browser/desktop/issues/12256 | 2:34:58 | 0:05:06 |
|
||||
| Broken essential tab URL after switching with keyboard shortcuts | https://github.com/zen-browser/desktop/issues/12255 | 0:19:28 | None |
|
||||
| Closing glance bug with multiple windows | https://github.com/zen-browser/desktop/issues/12254 | None | None |
|
||||
| Dragging tabs into folders shows selected folder highlight at incorrect position in some view modes. | https://github.com/zen-browser/desktop/issues/12252 | 1:31:56 | 3:52:46 |
|
||||
| "New split view" in command bar (on a page accessed from an Essential tab) opens a new tab instead | https://github.com/zen-browser/desktop/issues/12251 | 0:10:54 | None |
|
||||
| Zen starts as blank widows on macOS Tahoe Version 26.3 (25D122) beta | https://github.com/zen-browser/desktop/issues/12250 | 0:38:21 | 3 days, 23:19:20 |
|
||||
| Pined extensions icons no longer visible in compact sidebar since last release | https://github.com/zen-browser/desktop/issues/12249 | 2 days, 20:44:58 | None |
|
||||
| Facing Glitches On Start Opens 2 Windows for Same tabs. | https://github.com/zen-browser/desktop/issues/12248 | 1:25:01 | None |
|
||||
| Separate windows mirroring | https://github.com/zen-browser/desktop/issues/12247 | 0:12:51 | 0:12:51 |
|
||||
| H.264, HEVC, and AAC Not Supported in Kubuntu App Center Version (1.17.14b) | https://github.com/zen-browser/desktop/issues/12245 | 1 day, 12:07:19 | None |
|
||||
| Private and blank windows ignore CloseWindowWithLastTab setting | https://github.com/zen-browser/desktop/issues/12242 | 9:22:25 | 2 days, 8:59:22 |
|
||||
| Bookmark temporarily removes | https://github.com/zen-browser/desktop/issues/12241 | None | None |
|
||||
| Multiple Windows Launch on Startup after Multiple Windows Have Been Closed | https://github.com/zen-browser/desktop/issues/12238 | 16:04:12 | None |
|
||||
| Duplicated Toggle Full Screen and View Full Screen for keyboard shortcut | https://github.com/zen-browser/desktop/issues/12237 | 10 days, 20:34:41 | 11 days, 11:58:31 |
|
||||
| Container no longer displayed when moving tabs between windows on different spaces | https://github.com/zen-browser/desktop/issues/12235 | 10 days, 13:27:01 | 10 days, 18:33:05 |
|
||||
| Multi account container settings reset | https://github.com/zen-browser/desktop/issues/12234 | None | None |
|
||||
| Clicking the “Copy” button opens an “Open With” dialog on KDE Plasma Wayland. | https://github.com/zen-browser/desktop/issues/12232 | 13 days, 7:34:57 | 14 days, 19:58:57 |
|
||||
| Can't open a new window with clear context | https://github.com/zen-browser/desktop/issues/12229 | None | 0:01:26 |
|
||||
| Can't play DRM content in Linux | https://github.com/zen-browser/desktop/issues/12228 | 4:21:30 | 6:06:50 |
|
||||
| Missing icons in address bar: padlock (https) and star (to bookmark current page) | https://github.com/zen-browser/desktop/issues/12226 | None | 0:08:28 |
|
||||
| Broken extension/browser tools sidebar keybind | https://github.com/zen-browser/desktop/issues/12225 | 5:45:59 | 9 days, 20:16:58 |
|
||||
| Sidebar empty after copying profile from Firefox | https://github.com/zen-browser/desktop/issues/12224 | 0:25:56 | 0:25:56 |
|
||||
| Lost all my folders with the latest update | https://github.com/zen-browser/desktop/issues/12223 | 0:55:54 | 0:55:54 |
|
||||
| History window doesnt follow default system or browser theme | https://github.com/zen-browser/desktop/issues/12222 | None | None |
|
||||
| when i have multiple windows and restart zen , all the windows will be the same , have the same tabs | https://github.com/zen-browser/desktop/issues/12221 | 0:35:11 | 0:22:16 |
|
||||
| Deleting All Data | https://github.com/zen-browser/desktop/issues/12220 | 0:59:01 | None |
|
||||
| Move to Space in Tab Context Menu not available | https://github.com/zen-browser/desktop/issues/12219 | 0:12:00 | None |
|
||||
| When opening Zen after closing multiple windows, only one window has workspaces | https://github.com/zen-browser/desktop/issues/12218 | 0:59:47 | None |
|
||||
| Forms don't allow to be processed | https://github.com/zen-browser/desktop/issues/12217 | 6:15:33 | 6:15:33 |
|
||||
| Cannot drag and drop to create a split view | https://github.com/zen-browser/desktop/issues/12216 | 0:37:06 | 0:37:06 |
|
||||
| Glance does not work via keybind+click in Reader VIew | https://github.com/zen-browser/desktop/issues/12214 | None | None |
|
||||
| "New Blank Window" is not capitalized in Mac OS menu bar | https://github.com/zen-browser/desktop/issues/12213 | None | 7 days, 4:10:17 |
|
||||
| Zen changes tab IDs without sending tabs.onReplaced events | https://github.com/zen-browser/desktop/issues/12212 | 1:12:47 | 1:12:47 |
|
||||
| Private window is adopting Blank windows styling | https://github.com/zen-browser/desktop/issues/12211 | None | 0:19:10 |
|
||||
| The loading indicator on tabs does not appear when a tab is loading. | https://github.com/zen-browser/desktop/issues/12210 | 1:23:55 | 1:23:55 |
|
||||
| Page content cannot scroll fully to top; top area is hidden behind browser UI | https://github.com/zen-browser/desktop/issues/12209 | 13:06:36 | None |
|
||||
| TURN OFF WINDOW SYNC | https://github.com/zen-browser/desktop/issues/12206 | 0:47:53 | 1:23:13 |
|
||||
| Essentials not working correctly | https://github.com/zen-browser/desktop/issues/12205 | 3:18:34 | 3:27:55 |
|
||||
| Tab titles not updating | https://github.com/zen-browser/desktop/issues/12204 | 3:40:45 | 5:54:14 |
|
||||
| Folders disappeared after updating to the Zen version 1.18.3b (Firefox 147.0.2) (aarch64) | https://github.com/zen-browser/desktop/issues/12203 | 9:12:45 | 9:12:45 |
|
||||
| Some websites don't load | https://github.com/zen-browser/desktop/issues/12202 | 1 day, 10:47:54 | None |
|
||||
| Website favicons have the wrong icons | https://github.com/zen-browser/desktop/issues/12201 | 2:36:06 | 0:04:20 |
|
||||
| tab indexes are off by 2 | https://github.com/zen-browser/desktop/issues/12199 | None | 3:02:10 |
|
||||
| Zen doesn't identify itself in the extensions API | https://github.com/zen-browser/desktop/issues/12198 | 1 day, 21:45:16 | 6 days, 22:02:36 |
|
||||
| Part of the screenshot overlay is rendered below glance windows | https://github.com/zen-browser/desktop/issues/12196 | None | 21 days, 5:30:56 |
|
||||
| Glance opens without keyboard shortcut in Essential tabs | https://github.com/zen-browser/desktop/issues/12194 | 8:27:58 | 8:27:58 |
|
||||
| Context menu extensions multiply | https://github.com/zen-browser/desktop/issues/12192 | None | None |
|
||||
| Tab folder not closing properly when a tab is opened | https://github.com/zen-browser/desktop/issues/12190 | None | 10:15:16 |
|
||||
| Can't set a theme | https://github.com/zen-browser/desktop/issues/12189 | 1:38:06 | None |
|
||||
|
||||
_This report was generated with the [Issue Metrics Action](https://github.com/github/issue-metrics)_
|
||||
Search query used to find these items: `repo:zen-browser/desktop is:issue created:2026-02-01..2026-02-28`
|
||||
@@ -47,6 +47,7 @@ pictureinpicture-minimize-btn =
|
||||
zen-panel-ui-gradient-generator-custom-color = Custom Color
|
||||
|
||||
zen-copy-current-url-confirmation = Copied current URL!
|
||||
zen-copy-current-url-as-markdown-confirmation = Copied current URL as Markdown!
|
||||
|
||||
zen-general-cancel-label =
|
||||
.label = Cancel
|
||||
|
||||
1
locales/update-supported-languages.sh
Normal file → Executable file
1
locales/update-supported-languages.sh
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
LANGS_FILE="./supported-languages"
|
||||
|
||||
# Clean up the file
|
||||
|
||||
4407
package-lock.json
generated
4407
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
35
package.json
35
package.json
@@ -21,9 +21,8 @@
|
||||
"sync:raw": "surfer update",
|
||||
"sync:rc": "python3 scripts/update_ff.py --rc",
|
||||
"sync:l10n": "python3 scripts/update_ff.py --just-l10n",
|
||||
"pretty": "prettier . --write --cache && autopep8 -r --in-place scripts/ src/ --exclude src/zen/tests/",
|
||||
"lint": "npx eslint src/ && prettier . --check --cache",
|
||||
"lint:fix": "npm run pretty && npx eslint src/ --fix",
|
||||
"lint": "cd engine && ./mach lint zen",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"prepare": "husky",
|
||||
"reset-ff": "surfer reset",
|
||||
"surfer": "surfer",
|
||||
@@ -51,32 +50,14 @@
|
||||
"homepage": "https://github.com/zen-browser/desktop#readme",
|
||||
"devDependencies": {
|
||||
"@babel/preset-typescript": "^7.27.0",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@eslint/json": "^0.14.0",
|
||||
"@microsoft/eslint-plugin-sdl": "^1.1.0",
|
||||
"@zen-browser/surfer": "^1.13.1",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-eslint-plugin": "^7.3.0",
|
||||
"eslint-plugin-html": "^8.1.3",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-jest": "^29.12.1",
|
||||
"eslint-plugin-json": "^4.0.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-lit": "^2.1.1",
|
||||
"eslint-plugin-mozilla": "^4.3.3",
|
||||
"eslint-plugin-no-unsanitized": "4.1.4",
|
||||
"eslint-plugin-promise": "7.2.1",
|
||||
"eslint-plugin-react": "7.37.5",
|
||||
"eslint-plugin-react-hooks": "^5.2.0",
|
||||
"eslint-plugin-spidermonkey-js": "file:tools/eslint-plugin-spidermonkey-js",
|
||||
"@zen-browser/prettier": "^3.9.3",
|
||||
"@zen-browser/surfer": "^1.13.4",
|
||||
"formal-git": "^1.2.9",
|
||||
"globals": "^16.3.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.3.0",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-sh": "^0.14.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.52.0"
|
||||
}
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"notes(private)": "We don't want to publish to npm, so this is marked as private",
|
||||
"private": true
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
- name: zen.view.compact.toolbar-hide-after-hover.duration
|
||||
value: 1000
|
||||
|
||||
- name: zen.view.compact.sidebar-keep-hover.duration
|
||||
value: 150
|
||||
|
||||
- name: zen.view.compact.animate-sidebar
|
||||
value: true
|
||||
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
value: 1000
|
||||
|
||||
- name: zen.splitView.drag-over-split-threshold
|
||||
value: 25
|
||||
value: 40
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
[tool.autopep8]
|
||||
max_line_length = 120
|
||||
recursive = true
|
||||
aggressive = 3
|
||||
indent_size = 2
|
||||
@@ -2,7 +2,6 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
autopep8==2.3.1
|
||||
click==8.1.8
|
||||
mypy-extensions==1.0.0
|
||||
packaging==24.2
|
||||
|
||||
1
scripts/download-language-packs.sh
Normal file → Executable file
1
scripts/download-language-packs.sh
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
2
scripts/fetch-formal-git-components.sh
Normal file → Executable file
2
scripts/fetch-formal-git-components.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
5
scripts/recalculate-patches.sh
Normal file → Executable file
5
scripts/recalculate-patches.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
@@ -12,6 +12,9 @@ IGNORE_FILES=(
|
||||
"shared.nsh"
|
||||
"ignorePrefs.json"
|
||||
"moz.configure"
|
||||
"AsyncShutdown.sys.mjs"
|
||||
"Info.plist.in"
|
||||
"firefox.js"
|
||||
)
|
||||
|
||||
# Recursively find all .patch files in the current directory and its subdirectories
|
||||
|
||||
2
scripts/remove-failed-jobs.sh
Normal file → Executable file
2
scripts/remove-failed-jobs.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
2
scripts/update-surfer.sh
Normal file → Executable file
2
scripts/update-surfer.sh
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
17
src/-prettierignore.patch
Normal file
17
src/-prettierignore.patch
Normal file
@@ -0,0 +1,17 @@
|
||||
diff --git a/.prettierignore b/.prettierignore
|
||||
index cbca8bb4b36cecc44e6b498e9ef15bc4bdc21871..8f3a14e14a2d58875bdd6f04bd31f57e23073148 100644
|
||||
--- a/.prettierignore
|
||||
+++ b/.prettierignore
|
||||
@@ -1795,3 +1795,12 @@ tools/ts/test/baselines/
|
||||
try_task_config.json
|
||||
xpcom/idl-parser/xpidl/fixtures/xpctest.d.json
|
||||
**/package-lock.json
|
||||
+
|
||||
+
|
||||
+*.bundle.min.js
|
||||
+*.min.js
|
||||
+*.min.mjs
|
||||
+*.inc
|
||||
+*/mochitests/*
|
||||
+*.svg
|
||||
+
|
||||
24
src/-stylelintignore.patch
Normal file
24
src/-stylelintignore.patch
Normal file
@@ -0,0 +1,24 @@
|
||||
diff --git a/.stylelintignore b/.stylelintignore
|
||||
index 185490999507b8a5032977237af50f5e61c71df1..e887fafa90b881e852a287ed8898638c995861ab 100644
|
||||
--- a/.stylelintignore
|
||||
+++ b/.stylelintignore
|
||||
@@ -106,3 +106,19 @@ build/pgo/blueprint/**/*.css
|
||||
# under our control or we don't want to modify at this point:
|
||||
testing/web-platform/mozilla/
|
||||
testing/web-platform/tests/
|
||||
+
|
||||
+*.inc.css
|
||||
+
|
||||
+zen/tests/mochitests/*
|
||||
+
|
||||
+# Some CSS files are preprocessed and prettier doesn't handle them well
|
||||
+# We also dont want to format the CSS files that are generated by the build
|
||||
+zen/tabs/zen-tabs.css
|
||||
+zen/common/styles/zen-theme.css
|
||||
+zen/compact-mode/zen-compact-mode.css
|
||||
+
|
||||
+zen/split-view/zen-decks.css
|
||||
+zen/workspaces/zen-workspaces.css
|
||||
+zen/common/styles/zen-toolbar.css
|
||||
+
|
||||
+*.inc
|
||||
25
src/-stylelintrc-js.patch
Normal file
25
src/-stylelintrc-js.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
diff --git a/.stylelintrc.js b/.stylelintrc.js
|
||||
index 36719c9e152c34da2aa76fc74d74e58cb9e6b1cc..4226db2e0af4b36923a93dcd0b76e59f8508ba36 100644
|
||||
--- a/.stylelintrc.js
|
||||
+++ b/.stylelintrc.js
|
||||
@@ -67,7 +67,7 @@ module.exports = {
|
||||
],
|
||||
|
||||
"max-nesting-depth": [
|
||||
- 3,
|
||||
+ 6,
|
||||
{
|
||||
ignore: ["blockless-at-rules"],
|
||||
},
|
||||
@@ -274,9 +274,9 @@ module.exports = {
|
||||
// Remove this line setting `csscontrols/use-logical` to null after implementing fixes
|
||||
"csstools/use-logical": null,
|
||||
"stylelint-plugin-mozilla/no-base-design-tokens": true,
|
||||
- "stylelint-plugin-mozilla/use-design-tokens": true,
|
||||
+ "stylelint-plugin-mozilla/use-design-tokens": false,
|
||||
"stylelint-plugin-mozilla/no-non-semantic-token-usage": true,
|
||||
- "stylelint-plugin-mozilla/use-size-tokens": true,
|
||||
+ "stylelint-plugin-mozilla/use-size-tokens": false,
|
||||
},
|
||||
|
||||
overrides: [
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/browser/app/macbuild/Contents/Info.plist.in b/browser/app/macbuild/Contents/Info.plist.in
|
||||
index 0c4fb837a24490c66b284abf2bd9299c2e021de0..ea28831b90662b12bdcb137c35b6bb83626c77e7 100644
|
||||
--- a/browser/app/macbuild/Contents/Info.plist.in
|
||||
+++ b/browser/app/macbuild/Contents/Info.plist.in
|
||||
@@ -190,8 +190,6 @@
|
||||
<string>@MAC_APP_NAME@ @APP_VERSION@</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>firefox.icns</string>
|
||||
- <key>CFBundleIconName</key>
|
||||
- <string>AppIcon</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@MOZ_MACBUNDLE_ID@</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
@@ -1,8 +1,18 @@
|
||||
diff --git a/browser/base/content/browser-box.inc.xhtml b/browser/base/content/browser-box.inc.xhtml
|
||||
index 2faed30e09511c381051bc40910a883d1d7bc10d..6ba2d0d91235ed33e4b4bad281c974b5960beaa2 100644
|
||||
index 2faed30e09511c381051bc40910a883d1d7bc10d..3b8c89902502aa384473dd6f43be7ec49bad06ac 100644
|
||||
--- a/browser/base/content/browser-box.inc.xhtml
|
||||
+++ b/browser/base/content/browser-box.inc.xhtml
|
||||
@@ -25,7 +25,13 @@
|
||||
@@ -3,6 +3,9 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
<hbox flex="1" id="browser">
|
||||
+ <html:div id="zen-browser-background" class="zen-browser-generic-background">
|
||||
+ <html:div class="zen-browser-grain" />
|
||||
+ </html:div>
|
||||
<box context="sidebar-context-menu" id="sidebar-main" hidden="true">
|
||||
<html:sidebar-main flex="1">
|
||||
<box id="vertical-tabs" slot="tabstrip" customizable="true" contextmenu="toolbar-context-menu"></box>
|
||||
@@ -25,7 +28,13 @@
|
||||
</stack>
|
||||
</vbox>
|
||||
<splitter id="sidebar-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
|
||||
@@ -16,7 +26,7 @@ index 2faed30e09511c381051bc40910a883d1d7bc10d..6ba2d0d91235ed33e4b4bad281c974b5
|
||||
<tabpanels id="tabbrowser-tabpanels" flex="1" selectedIndex="0"/>
|
||||
</tabbox>
|
||||
<splitter id="ai-window-splitter" class="chromeclass-extrachrome sidebar-splitter" resizebefore="none" resizeafter="sibling" hidden="true"/>
|
||||
@@ -34,3 +40,5 @@
|
||||
@@ -34,3 +43,5 @@
|
||||
</stack>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385a3bfe223 100644
|
||||
index 4d4223c508560136aba220adb18528aac913a188..10d4d9cecbb0e7cec9191d78fb81a57376b37ff1 100644
|
||||
--- a/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
|
||||
@@ -2,7 +2,7 @@
|
||||
@@ -11,7 +11,7 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
|
||||
<script src="chrome://browser/content/navigator-toolbox.js" />
|
||||
|
||||
<!-- Menu -->
|
||||
@@ -18,9 +18,9 @@
|
||||
@@ -18,9 +18,12 @@
|
||||
#include browser-menubar.inc
|
||||
</toolbaritem>
|
||||
<spacer flex="1" skipintoolbarset="true" style="order: 1000;"/>
|
||||
@@ -19,10 +19,13 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
|
||||
</toolbar>
|
||||
|
||||
+<hbox id="titlebar">
|
||||
+ <html:div id="zen-toolbar-background" class="zen-toolbar-background zen-browser-generic-background">
|
||||
+ <html:div class="zen-browser-grain" />
|
||||
+ </html:div>
|
||||
<toolbar id="TabsToolbar"
|
||||
class="browser-toolbar browser-titlebar"
|
||||
fullscreentoolbar="true"
|
||||
@@ -62,6 +62,9 @@
|
||||
@@ -62,6 +65,9 @@
|
||||
<html:sidebar-pins-promo id="drag-to-pin-promo-card"></html:sidebar-pins-promo>
|
||||
<arrowscrollbox id="pinned-tabs-container" orient="horizontal" clicktoscroll=""></arrowscrollbox>
|
||||
<splitter orient="vertical" id="vertical-pinned-tabs-splitter" resizebefore="sibling" resizeafter="none" hidden="true"/>
|
||||
@@ -32,7 +35,7 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
|
||||
<hbox class="tab-drop-indicator" hidden="true"/>
|
||||
<arrowscrollbox id="tabbrowser-arrowscrollbox" orient="horizontal" flex="1" clicktoscroll="" scrolledtostart="" scrolledtoend="">
|
||||
<tab is="tabbrowser-tab" class="tabbrowser-tab" selected="true" visuallyselected="" fadein=""/>
|
||||
@@ -81,6 +84,7 @@
|
||||
@@ -81,6 +87,7 @@
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
data-l10n-id="tabs-toolbar-new-tab"/>
|
||||
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
|
||||
@@ -40,7 +43,7 @@ index 4d4223c508560136aba220adb18528aac913a188..7e7432f7adb761a598d3e3e5ca4c6385
|
||||
</tabs>
|
||||
|
||||
<toolbarbutton id="new-tab-button"
|
||||
@@ -114,9 +118,10 @@
|
||||
@@ -114,9 +121,10 @@
|
||||
|
||||
<toolbarbutton class="content-analysis-indicator toolbarbutton-1 content-analysis-indicator-icon"/>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/base/content/navigator-toolbox.js b/browser/base/content/navigator-toolbox.js
|
||||
index 15469e9d9b91c1eaef2578c9e43b6999edac3392..553402b41bc15f7cd99bf87c54416dc66d7c03e7 100644
|
||||
index 15469e9d9b91c1eaef2578c9e43b6999edac3392..95ae5036b57baeb5237603c0921f1e9252af6919 100644
|
||||
--- a/browser/base/content/navigator-toolbox.js
|
||||
+++ b/browser/base/content/navigator-toolbox.js
|
||||
@@ -6,7 +6,7 @@
|
||||
@@ -19,15 +19,25 @@ index 15469e9d9b91c1eaef2578c9e43b6999edac3392..553402b41bc15f7cd99bf87c54416dc6
|
||||
#picture-in-picture-button,
|
||||
#urlbar-zoom-button,
|
||||
#star-button-box,
|
||||
@@ -206,6 +207,7 @@ document.addEventListener(
|
||||
case "vertical-tabs-newtab-button":
|
||||
case "tabs-newtab-button":
|
||||
case "new-tab-button":
|
||||
+ case "zen-tabs-wrapper":
|
||||
@@ -209,6 +210,17 @@ document.addEventListener(
|
||||
gBrowser.handleNewTabMiddleClick(element, event);
|
||||
break;
|
||||
|
||||
@@ -318,6 +320,7 @@ document.addEventListener(
|
||||
+ case "zen-tabs-wrapper":
|
||||
+ if (event.button == 1) {
|
||||
+ BrowserCommands.openTab();
|
||||
+ // Stop the propagation of the click event, to prevent the event from being
|
||||
+ // handled more than once.
|
||||
+ // E.g. see https://bugzilla.mozilla.org/show_bug.cgi?id=1657992#c4
|
||||
+ event.stopPropagation();
|
||||
+ event.preventDefault();
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
case "back-button":
|
||||
case "forward-button":
|
||||
case "reload-button":
|
||||
@@ -318,6 +330,7 @@ document.addEventListener(
|
||||
#downloads-button,
|
||||
#fxa-toolbar-menu-button,
|
||||
#unified-extensions-button,
|
||||
@@ -35,7 +45,7 @@ index 15469e9d9b91c1eaef2578c9e43b6999edac3392..553402b41bc15f7cd99bf87c54416dc6
|
||||
#library-button,
|
||||
#split-view-button
|
||||
`);
|
||||
@@ -401,6 +404,16 @@ document.addEventListener(
|
||||
@@ -401,6 +414,16 @@ document.addEventListener(
|
||||
gUnifiedExtensions.togglePanel(event);
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js
|
||||
index 836bee14d2b63604688ebe477a5d915a5e99b305..a675aed711560b4a44604fc17478cffa7fb68439 100644
|
||||
index 836bee14d2b63604688ebe477a5d915a5e99b305..7e105a1ae07657b0a0e664a8e3d9d2eb894fa1d4 100644
|
||||
--- a/browser/components/tabbrowser/content/tab.js
|
||||
+++ b/browser/components/tabbrowser/content/tab.js
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -65,11 +65,11 @@ index 836bee14d2b63604688ebe477a5d915a5e99b305..a675aed711560b4a44604fc17478cffa
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Selected tabs are always visible
|
||||
+ if (this.selected || this.multiselected || this.hasAttribute("folder-active")) return true;
|
||||
+ if (this.selected || this.multiselected) return true;
|
||||
+ // Recursively check all parent groups
|
||||
+ let currentParent = this.group;
|
||||
+ while (currentParent) {
|
||||
+ if (currentParent.collapsed) {
|
||||
+ if (currentParent.collapsed && !currentParent.activeTabs?.includes(this)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ currentParent = currentParent.group;
|
||||
|
||||
@@ -499,7 +499,7 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:is([open], [starred]) image {
|
||||
&:where([starred]) image {
|
||||
list-style-image: url("permissions-fill.svg");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
22
src/eslint-file-globals-config-mjs.patch
Normal file
22
src/eslint-file-globals-config-mjs.patch
Normal file
@@ -0,0 +1,22 @@
|
||||
diff --git a/eslint-file-globals.config.mjs b/eslint-file-globals.config.mjs
|
||||
index 00e49fce00efecab254aa1b8f0f0fe9ed2c24057..e9f390e15537d3d03a87f1c87099cb34698aee49 100644
|
||||
--- a/eslint-file-globals.config.mjs
|
||||
+++ b/eslint-file-globals.config.mjs
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
import globals from "globals";
|
||||
import mozilla from "eslint-plugin-mozilla";
|
||||
+import zenGlobals from "./zen/zen.globals.mjs";
|
||||
|
||||
export default [
|
||||
{
|
||||
@@ -550,4 +551,9 @@ export default [
|
||||
],
|
||||
languageOptions: { globals: globals.worker },
|
||||
},
|
||||
+ {
|
||||
+ name: "zen-globals",
|
||||
+ files: ["zen/**/!(*.sys).mjs", "zen/**/*.js"],
|
||||
+ languageOptions: { globals: zenGlobals.reduce((acc, name) => ({ ...acc, [name]: "readonly" }), {}) },
|
||||
+ }
|
||||
];
|
||||
13
src/eslint-ignores-config-mjs.patch
Normal file
13
src/eslint-ignores-config-mjs.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/eslint-ignores.config.mjs b/eslint-ignores.config.mjs
|
||||
index 0cfd7e02ad58c331f48f1ba8e1588777e1ce2595..888674b5ed2b68dbe77eb177ba0947f94ed57c80 100644
|
||||
--- a/eslint-ignores.config.mjs
|
||||
+++ b/eslint-ignores.config.mjs
|
||||
@@ -312,4 +312,8 @@ export default [
|
||||
// Test files for circular import in modules.
|
||||
"dom/base/test/jsmodules/import_circular.mjs",
|
||||
"dom/base/test/jsmodules/import_circular_1.mjs",
|
||||
+
|
||||
+ "zen/common/emojis/ZenEmojisData.min.mjs",
|
||||
+ "zen/tests/**",
|
||||
+ "zen/vendor/**",
|
||||
];
|
||||
12
src/eslint-test-paths-config-mjs.patch
Normal file
12
src/eslint-test-paths-config-mjs.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/eslint-test-paths.config.mjs b/eslint-test-paths.config.mjs
|
||||
index 53d97521a676d04212abb0263cb166da06c889e0..fa8c261de7a8663a369fb41671476d314722c025 100644
|
||||
--- a/eslint-test-paths.config.mjs
|
||||
+++ b/eslint-test-paths.config.mjs
|
||||
@@ -218,6 +218,7 @@ const extraBrowserTestPaths = [
|
||||
"toolkit/components/windowwatcher/test/",
|
||||
"toolkit/mozapps/extensions/test/xpinstall/",
|
||||
"uriloader/exthandler/tests/mochitest/",
|
||||
+ "zen/tests/",
|
||||
];
|
||||
|
||||
// DO NOT add more items to this list. Please see the note at the top
|
||||
@@ -1,7 +1,31 @@
|
||||
diff --git a/browser/base/content/main-popupset.inc.xhtml b/browser/base/content/main-popupset.inc.xhtml
|
||||
--- a/browser/base/content/main-popupset.inc.xhtml
|
||||
+++ b/browser/base/content/main-popupset.inc.xhtml
|
||||
@@ -556,10 +556,11 @@
|
||||
@@ -193,10 +193,11 @@
|
||||
<!-- Starting point for selection actions -->
|
||||
<panel class="panel-no-padding"
|
||||
id="selection-shortcut-action-panel"
|
||||
noautofocus="true"
|
||||
consumeoutsideclicks="never"
|
||||
+ nonnativepopover="true"
|
||||
type="arrow">
|
||||
<hbox class="panel-subview-body">
|
||||
<html:moz-button id="ai-action-button"/>
|
||||
</hbox>
|
||||
</panel>
|
||||
@@ -204,10 +205,11 @@
|
||||
|
||||
<!-- Shortcut options for Gen AI action -->
|
||||
<panel class="panel-no-padding"
|
||||
id="chat-shortcuts-options-panel"
|
||||
noautofocus="true"
|
||||
+ nonnativepopover="true"
|
||||
type="arrow">
|
||||
<vbox class="panel-subview-body"/>
|
||||
</panel>
|
||||
|
||||
<html:template id="screenshotsPagePanelTemplate">
|
||||
@@ -556,10 +558,11 @@
|
||||
type="arrow"
|
||||
orient="vertical"
|
||||
noautofocus="true"
|
||||
@@ -43,6 +67,40 @@ diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/brows
|
||||
viewCacheId="appMenu-viewCache">
|
||||
</panelmultiview>
|
||||
</panel>
|
||||
diff --git a/dom/xul/XULPopupElement.cpp b/dom/xul/XULPopupElement.cpp
|
||||
--- a/dom/xul/XULPopupElement.cpp
|
||||
+++ b/dom/xul/XULPopupElement.cpp
|
||||
@@ -84,10 +84,15 @@
|
||||
|
||||
void XULPopupElement::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos,
|
||||
bool aIsContextMenu,
|
||||
Event* aTriggerEvent) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
+ // TODO(cheff): We do the same at nsCocoaWindow::Show but it doesn't seem
|
||||
+ // to trigger a restyle so `appearance: auto` doesn't apply the native
|
||||
+ // popover style. We should remove this and use the other implementation
|
||||
+ // because this is a bit of a hack, not sure how reliable it is.
|
||||
+ SetXULBoolAttr(nsGkAtoms::nonnativepopover, true, IgnoreErrors());
|
||||
if (pm) {
|
||||
pm->ShowPopupAtScreen(this, aXPos, aYPos, aIsContextMenu, aTriggerEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,10 +101,14 @@
|
||||
int32_t aWidth, int32_t aHeight,
|
||||
bool aIsContextMenu,
|
||||
bool aAttributesOverride,
|
||||
Event* aTriggerEvent) {
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
+ // TODO: See OpenPopupAtScreen. We should remove this and use the other
|
||||
+ // implementation because this is a bit of a hacky way to determine whether to
|
||||
+ // use a native popover or not.
|
||||
+ SetXULBoolAttr(nsGkAtoms::nonnativepopover, true, IgnoreErrors());
|
||||
if (pm) {
|
||||
pm->ShowPopupAtScreenRect(
|
||||
this, aPosition, nsIntRect(aXPos, aYPos, aWidth, aHeight),
|
||||
aIsContextMenu, aAttributesOverride, aTriggerEvent);
|
||||
}
|
||||
diff --git a/layout/xul/nsMenuPopupFrame.h b/layout/xul/nsMenuPopupFrame.h
|
||||
--- a/layout/xul/nsMenuPopupFrame.h
|
||||
+++ b/layout/xul/nsMenuPopupFrame.h
|
||||
@@ -110,29 +168,29 @@ diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/Sta
|
||||
diff --git a/toolkit/themes/shared/global-shared.css b/toolkit/themes/shared/global-shared.css
|
||||
--- a/toolkit/themes/shared/global-shared.css
|
||||
+++ b/toolkit/themes/shared/global-shared.css
|
||||
@@ -100,10 +100,22 @@
|
||||
--panel-padding: var(--arrowpanel-padding);
|
||||
--panel-shadow-margin: var(--arrowpanel-shadow-margin);
|
||||
@@ -102,10 +102,22 @@
|
||||
--menuitem-border-radius: var(--arrowpanel-menuitem-border-radius);
|
||||
--menuitem-padding: var(--arrowpanel-menuitem-padding);
|
||||
--menuitem-margin: var(--arrowpanel-menuitem-margin);
|
||||
+
|
||||
+ /* stylelint-disable-next-line media-query-no-invalid */
|
||||
+ @media -moz-pref("widget.macos.native-popovers") and (-moz-platform: macos) {
|
||||
+ &:not([nonnativepopover="true"]) {
|
||||
+ background-color: transparent;
|
||||
+ --panel-background: transparent;
|
||||
+ --panel-shadow: none;
|
||||
+ --panel-border-color: transparent;
|
||||
+ --panel-shadow-margin: 0px;
|
||||
+ --panel-padding: 0px;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
+/* stylelint-disable-next-line media-query-no-invalid */
|
||||
+@media -moz-pref("widget.macos.native-popovers") and (-moz-platform: macos) {
|
||||
+ panel:not(:where([nonnativepopover="true"])) {
|
||||
+ background-color: transparent;
|
||||
+ --panel-background: transparent;
|
||||
+ --panel-shadow: none;
|
||||
+ --panel-border-color: transparent;
|
||||
+ --panel-shadow-margin: 0px;
|
||||
+ --panel-padding: 0px;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* Lightweight theme roots */
|
||||
|
||||
:root[lwtheme] {
|
||||
.browser-toolbox-background,
|
||||
toolbar,
|
||||
diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
|
||||
--- a/widget/cocoa/nsCocoaWindow.h
|
||||
+++ b/widget/cocoa/nsCocoaWindow.h
|
||||
@@ -176,7 +234,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
|
||||
@interface BorderlessWindow : BaseWindow {
|
||||
}
|
||||
|
||||
@@ -201,10 +216,13 @@
|
||||
@@ -201,10 +216,14 @@
|
||||
typedef nsIWidget Inherited;
|
||||
|
||||
public:
|
||||
@@ -184,6 +242,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
|
||||
|
||||
+ // Check if this window should use NSPopover for popup/menu display
|
||||
+ bool ShouldUseNSPopover() const;
|
||||
+ bool ShouldShowAsNSPopover() const override;
|
||||
+
|
||||
[[nodiscard]] nsresult Create(nsIWidget* aParent, const DesktopIntRect& aRect,
|
||||
const InitData&) override;
|
||||
@@ -281,18 +340,32 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
|
||||
|
||||
if (!mWindow) {
|
||||
@@ -5227,10 +5282,58 @@
|
||||
@@ -5185,10 +5240,17 @@
|
||||
}
|
||||
|
||||
NSWindow* nativeParentWindow =
|
||||
mParent ? (NSWindow*)mParent->GetNativeData(NS_NATIVE_WINDOW) : nil;
|
||||
|
||||
+ bool shouldUseNativePopover = false;
|
||||
+ if (mWindowType == WindowType::Popup && aState) {
|
||||
+ nsMenuPopupFrame* popupFrame = GetPopupFrame();
|
||||
+ popupFrame->PopupElement().SetXULBoolAttr(
|
||||
+ nsGkAtoms::nonnativepopover, !ShouldShowAsNSPopover(), IgnoreErrors());
|
||||
+ }
|
||||
+
|
||||
if (aState && !mBounds.IsEmpty()) {
|
||||
// If we had set the activationPolicy to accessory, then right now we won't
|
||||
// have a dock icon. Make sure that we undo that and show a dock icon now
|
||||
// that we're going to show a window.
|
||||
if (NSApp.activationPolicy != NSApplicationActivationPolicyRegular) {
|
||||
@@ -5227,10 +5289,54 @@
|
||||
mWindow.contentView.needsDisplay = YES;
|
||||
if (!nativeParentWindow || mPopupLevel != PopupLevel::Parent) {
|
||||
[mWindow orderFront:nil];
|
||||
}
|
||||
NS_OBJC_END_TRY_IGNORE_BLOCK;
|
||||
+ nsMenuPopupFrame* popupFrame = GetPopupFrame();
|
||||
+ if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
+ [(PopupWindow*)mWindow usePopover] && popupFrame &&
|
||||
+ popupFrame->ShouldFollowAnchor() &&
|
||||
+ !popupFrame->PopupElement().GetBoolAttr(
|
||||
+ nsGkAtoms::nonnativepopover)) {
|
||||
+ if (ShouldShowAsNSPopover()) {
|
||||
+ nsMenuPopupFrame* popupFrame = GetPopupFrame();
|
||||
+ if (nativeParentWindow) {
|
||||
+ NSRectEdge preferredEdge =
|
||||
+ AlignmentPositionToNSRectEdge(popupFrame->GetAlignmentPosition());
|
||||
@@ -340,7 +413,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
// close other programs' context menus when ours open.
|
||||
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
[(PopupWindow*)mWindow isContextMenu]) {
|
||||
@@ -5301,10 +5404,15 @@
|
||||
@@ -5301,10 +5407,15 @@
|
||||
// of a window it hides the parent window.
|
||||
if (mWindowType == WindowType::Popup && nativeParentWindow) {
|
||||
[nativeParentWindow removeChildWindow:mWindow];
|
||||
@@ -356,7 +429,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
// other programs) that a menu has closed.
|
||||
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
[(PopupWindow*)mWindow isContextMenu]) {
|
||||
@@ -5351,10 +5459,17 @@
|
||||
@@ -5351,10 +5462,28 @@
|
||||
return false;
|
||||
}
|
||||
return nsIWidget::ShouldUseOffMainThreadCompositing();
|
||||
@@ -365,8 +438,19 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
+bool nsCocoaWindow::ShouldUseNSPopover() const {
|
||||
+ // Use NSPopover for panel popups when the preference is enabled
|
||||
+ // But not for detached popups - they should use traditional window logic
|
||||
+ return mWindowType == WindowType::Popup && mPopupType == PopupType::Panel &&
|
||||
+ mozilla::StaticPrefs::widget_macos_native_popovers();
|
||||
+ return (mWindowType == WindowType::Popup && mPopupType == PopupType::Panel &&
|
||||
+ mozilla::StaticPrefs::widget_macos_native_popovers());
|
||||
+}
|
||||
+
|
||||
+bool nsCocoaWindow::ShouldShowAsNSPopover() const {
|
||||
+ if (!ShouldUseNSPopover()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ nsMenuPopupFrame* popupFrame = GetPopupFrame();
|
||||
+ return [mWindow isKindOfClass:[PopupWindow class]] &&
|
||||
+ [(PopupWindow*)mWindow usePopover] && popupFrame &&
|
||||
+ popupFrame->ShouldFollowAnchor() &&
|
||||
+ !popupFrame->PopupElement().GetBoolAttr(nsGkAtoms::nonnativepopover);
|
||||
+}
|
||||
+
|
||||
TransparencyMode nsCocoaWindow::GetTransparencyMode() {
|
||||
@@ -374,7 +458,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
|
||||
return mWindow.isOpaque ? TransparencyMode::Opaque
|
||||
: TransparencyMode::Transparent;
|
||||
@@ -6313,10 +6428,20 @@
|
||||
@@ -6313,10 +6442,20 @@
|
||||
// We ignore aRepaint -- we have to call display:YES, otherwise the
|
||||
// title bar doesn't immediately get repainted and is displayed in
|
||||
// the wrong place, leading to a visual jump.
|
||||
@@ -395,7 +479,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
|
||||
void nsCocoaWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
|
||||
DoResize(aRect.x, aRect.y, aRect.width, aRect.height, aRepaint, false);
|
||||
@@ -8277,18 +8402,27 @@
|
||||
@@ -8277,18 +8416,27 @@
|
||||
backing:(NSBackingStoreType)bufferingType
|
||||
defer:(BOOL)deferCreation {
|
||||
NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
|
||||
@@ -423,7 +507,7 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
// Return 0 in order to match what the system does for sheet windows and
|
||||
// _NSPopoverWindows.
|
||||
- (CGFloat)_backdropBleedAmount {
|
||||
@@ -8342,10 +8476,120 @@
|
||||
@@ -8342,10 +8490,120 @@
|
||||
|
||||
- (void)setIsContextMenu:(BOOL)flag {
|
||||
mIsContextMenu = flag;
|
||||
@@ -544,6 +628,25 @@ diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
|
||||
return NO;
|
||||
}
|
||||
|
||||
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
|
||||
--- a/widget/nsIWidget.h
|
||||
+++ b/widget/nsIWidget.h
|
||||
@@ -836,10 +836,15 @@
|
||||
virtual void SuppressAnimation(bool aSuppress) {}
|
||||
|
||||
/** Sets windows-specific mica backdrop on this widget. */
|
||||
virtual void SetMicaBackdrop(bool) {}
|
||||
|
||||
+ /**
|
||||
+ * Determine whether this widget should be shown as an NSPopover.
|
||||
+ */
|
||||
+ virtual bool ShouldShowAsNSPopover() const { return false; }
|
||||
+
|
||||
/**
|
||||
* Return size mode (minimized, maximized, normalized).
|
||||
* Returns a value from nsSizeMode (see nsIWidgetListener.h)
|
||||
*/
|
||||
virtual nsSizeMode SizeMode() = 0;
|
||||
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
|
||||
--- a/xpcom/ds/StaticAtoms.py
|
||||
+++ b/xpcom/ds/StaticAtoms.py
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
// Specifically trying to target FeatureCallout.sys.mjs's change.
|
||||
// IMPORTANT: Make sure Feature callouts STILL use native popopvers when
|
||||
// syncing from upstream, as this is a critical part of the patch.
|
||||
"+ nonnativepopover=\"true\"": "+ "
|
||||
"+ nonnativepopover=\"true\"": "+ ",
|
||||
"body,": ".browser-toolbox-background,"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
12
src/python/mozlint/mozlint/roller-py.patch
Normal file
12
src/python/mozlint/mozlint/roller-py.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/python/mozlint/mozlint/roller.py b/python/mozlint/mozlint/roller.py
|
||||
index aeafa93cc525d2846614b600e95fd817b832b0ef..69414ed032523f1b53b78ad867145efaea422c63 100644
|
||||
--- a/python/mozlint/mozlint/roller.py
|
||||
+++ b/python/mozlint/mozlint/roller.py
|
||||
@@ -92,7 +92,6 @@ def _run_worker(config, paths, **lintargs):
|
||||
res = res or []
|
||||
else:
|
||||
log.error(f"Unexpected result type received: {type(res)}")
|
||||
- assert False
|
||||
except Exception:
|
||||
log.exception(f"{config['name']} failed")
|
||||
res = 1
|
||||
@@ -1,28 +0,0 @@
|
||||
diff --git a/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs b/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs
|
||||
index 2aaef80411b2cef9563c49f23d36b08222b06b03..7bd15ebb0d9d09da57a287b47beb1f0e2e17d229 100644
|
||||
--- a/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs
|
||||
+++ b/toolkit/components/asyncshutdown/AsyncShutdown.sys.mjs
|
||||
@@ -492,6 +492,23 @@ function getPhase(topic) {
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
+
|
||||
+ /**
|
||||
+ * Reset the phase after a call to _trigger().
|
||||
+ * For testing purposes only.
|
||||
+ */
|
||||
+ get _reset() {
|
||||
+ let accepted = Services.prefs.getBoolPref(
|
||||
+ "toolkit.asyncshutdown.testing",
|
||||
+ false
|
||||
+ );
|
||||
+ if (accepted) {
|
||||
+ return () => {
|
||||
+ spinner = new Spinner(topic);
|
||||
+ };
|
||||
+ }
|
||||
+ return undefined;
|
||||
+ },
|
||||
});
|
||||
gPhases.set(topic, phase);
|
||||
return phase;
|
||||
13
src/tools/lint/eslint/__init__-py.patch
Normal file
13
src/tools/lint/eslint/__init__-py.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/tools/lint/eslint/__init__.py b/tools/lint/eslint/__init__.py
|
||||
index cd45822500a8b5e1112efad81ed34e01c0dbcc19..9f47b4a46bf1c36db06b45e047a939ae08bcb703 100644
|
||||
--- a/tools/lint/eslint/__init__.py
|
||||
+++ b/tools/lint/eslint/__init__.py
|
||||
@@ -114,7 +114,7 @@ def lint(paths, config, binary=None, fix=None, rules=[], setup=None, **lintargs)
|
||||
[
|
||||
binary,
|
||||
os.path.join(
|
||||
- module_path, "node_modules", "prettier", "bin", "prettier.cjs"
|
||||
+ module_path, "..", "node_modules", "@zen-browser", "prettier", "bin", "prettier.cjs"
|
||||
),
|
||||
"--list-different",
|
||||
"--no-error-on-unmatched-pattern",
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.mjs b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.mjs
|
||||
index 87fc32f6a1bdf21a56fb3ce18c767ebbb12c6d67..174fcc3a679ae655c9bce907461f9c3a9030c2a9 100644
|
||||
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.mjs
|
||||
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/require-jsdoc.mjs
|
||||
@@ -13,7 +13,7 @@ export default {
|
||||
"error",
|
||||
{
|
||||
require: {
|
||||
- ClassDeclaration: true,
|
||||
+ ClassDeclaration: false,
|
||||
FunctionDeclaration: false,
|
||||
},
|
||||
},
|
||||
12
src/tools/lint/ignorefile-yml.patch
Normal file
12
src/tools/lint/ignorefile-yml.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/tools/lint/ignorefile.yml b/tools/lint/ignorefile.yml
|
||||
index 5ae3b282a54c129bb16bca461470154e4a882618..f46c6256037cbef1392f8d070726d45dadac1289 100644
|
||||
--- a/tools/lint/ignorefile.yml
|
||||
+++ b/tools/lint/ignorefile.yml
|
||||
@@ -3,7 +3,6 @@ ignorefile:
|
||||
description: Linter for .gitignore and .hgignore files
|
||||
include:
|
||||
- '.gitignore'
|
||||
- - '.hgignore'
|
||||
support-files:
|
||||
- 'tools/lint/ignorefile**'
|
||||
type: external
|
||||
12
src/tools/lint/rejected-words-yml.patch
Normal file
12
src/tools/lint/rejected-words-yml.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/tools/lint/rejected-words.yml b/tools/lint/rejected-words.yml
|
||||
index d5ca2e05fb335fcd17d1559d5332ec4a43d7cd1d..1f34e8d5e05508fc541bc7aa6a779cd98206032a 100644
|
||||
--- a/tools/lint/rejected-words.yml
|
||||
+++ b/tools/lint/rejected-words.yml
|
||||
@@ -8,7 +8,6 @@ avoid-blacklist-and-whitelist:
|
||||
ignore-case: true
|
||||
# Based on codespell with idl and webidl added.
|
||||
extensions:
|
||||
- - js
|
||||
- mjs
|
||||
- jsx
|
||||
- idl
|
||||
38
src/zen/@types/lib.gecko.darwin.d.ts
vendored
38
src/zen/@types/lib.gecko.darwin.d.ts
vendored
@@ -53,9 +53,15 @@ declare global {
|
||||
dockMenu: nsIStandaloneNativeMenu;
|
||||
activateApplication(aIgnoreOtherApplications: boolean): void;
|
||||
badgeText: string;
|
||||
setBadgeImage(aBadgeImage: imgIContainer, aPaintContext?: nsISVGPaintContext): void;
|
||||
setBadgeImage(
|
||||
aBadgeImage: imgIContainer,
|
||||
aPaintContext?: nsISVGPaintContext
|
||||
): void;
|
||||
readonly isAppInDock: boolean;
|
||||
ensureAppIsPinnedToDock(aAppPath?: string, aAppToReplacePath?: string): boolean;
|
||||
ensureAppIsPinnedToDock(
|
||||
aAppPath?: string,
|
||||
aAppToReplacePath?: string
|
||||
): boolean;
|
||||
launchAppBundle(
|
||||
aAppBundle: nsIFile,
|
||||
aArgs: string[],
|
||||
@@ -70,7 +76,10 @@ declare global {
|
||||
}>;
|
||||
|
||||
interface nsIMacFinderProgress extends nsISupports {
|
||||
init(path: string, canceledCallback: nsIMacFinderProgressCanceledCallback): void;
|
||||
init(
|
||||
path: string,
|
||||
canceledCallback: nsIMacFinderProgressCanceledCallback
|
||||
): void;
|
||||
updateProgress(currentProgress: u64, totalProgress: u64): void;
|
||||
end(): void;
|
||||
}
|
||||
@@ -86,7 +95,11 @@ declare global {
|
||||
// https://searchfox.org/mozilla-central/source/widget/nsIMacUserActivityUpdater.idl
|
||||
|
||||
interface nsIMacUserActivityUpdater extends nsISupports {
|
||||
updateLocation(pageUrl: string, pageTitle: string, window: nsIBaseWindow): void;
|
||||
updateLocation(
|
||||
pageUrl: string,
|
||||
pageTitle: string,
|
||||
window: nsIBaseWindow
|
||||
): void;
|
||||
}
|
||||
|
||||
// https://searchfox.org/mozilla-central/source/widget/nsIMacWebAppUtils.idl
|
||||
@@ -120,7 +133,11 @@ declare global {
|
||||
readonly STATE_ERROR?: 3;
|
||||
readonly STATE_PAUSED?: 4;
|
||||
|
||||
setProgressState(state: nsTaskbarProgressState, currentValue?: u64, maxValue?: u64): void;
|
||||
setProgressState(
|
||||
state: nsTaskbarProgressState,
|
||||
currentValue?: u64,
|
||||
maxValue?: u64
|
||||
): void;
|
||||
}
|
||||
|
||||
// https://searchfox.org/mozilla-central/source/widget/nsITouchBarHelper.idl
|
||||
@@ -157,11 +174,18 @@ declare global {
|
||||
// https://searchfox.org/mozilla-central/source/widget/nsITouchBarUpdater.idl
|
||||
|
||||
interface nsITouchBarUpdater extends nsISupports {
|
||||
updateTouchBarInputs(aWindow: nsIBaseWindow, aInputs: nsITouchBarInput[]): void;
|
||||
updateTouchBarInputs(
|
||||
aWindow: nsIBaseWindow,
|
||||
aInputs: nsITouchBarInput[]
|
||||
): void;
|
||||
enterCustomizeMode(): void;
|
||||
isTouchBarInitialized(): boolean;
|
||||
setTouchBarInitialized(aIsInitialized: boolean): void;
|
||||
showPopover(aWindow: nsIBaseWindow, aPopover: nsITouchBarInput, aShowing: boolean): void;
|
||||
showPopover(
|
||||
aWindow: nsIBaseWindow,
|
||||
aPopover: nsITouchBarInput,
|
||||
aShowing: boolean
|
||||
): void;
|
||||
}
|
||||
|
||||
// https://searchfox.org/mozilla-central/source/xpcom/base/nsIMacPreferencesReader.idl
|
||||
|
||||
2827
src/zen/@types/lib.gecko.dom.d.ts
vendored
2827
src/zen/@types/lib.gecko.dom.d.ts
vendored
File diff suppressed because it is too large
Load Diff
1250
src/zen/@types/lib.gecko.glean.d.ts
vendored
1250
src/zen/@types/lib.gecko.glean.d.ts
vendored
File diff suppressed because it is too large
Load Diff
6
src/zen/@types/lib.gecko.linux.d.ts
vendored
6
src/zen/@types/lib.gecko.linux.d.ts
vendored
@@ -51,7 +51,11 @@ declare global {
|
||||
readonly STATE_ERROR?: 3;
|
||||
readonly STATE_PAUSED?: 4;
|
||||
|
||||
setProgressState(state: nsTaskbarProgressState, currentValue?: u64, maxValue?: u64): void;
|
||||
setProgressState(
|
||||
state: nsTaskbarProgressState,
|
||||
currentValue?: u64,
|
||||
maxValue?: u64
|
||||
): void;
|
||||
}
|
||||
|
||||
interface nsIXPCComponents_Interfaces {
|
||||
|
||||
3
src/zen/@types/lib.gecko.nsresult.d.ts
vendored
3
src/zen/@types/lib.gecko.nsresult.d.ts
vendored
@@ -705,4 +705,5 @@ interface nsIXPCComponents_Results {
|
||||
NS_ERROR_DOM_QM_CLIENT_INIT_ORIGIN_UNINITIALIZED: 0x80730001;
|
||||
}
|
||||
|
||||
type nsIXPCComponents_Values = nsIXPCComponents_Results[keyof nsIXPCComponents_Results];
|
||||
type nsIXPCComponents_Values =
|
||||
nsIXPCComponents_Results[keyof nsIXPCComponents_Results];
|
||||
|
||||
8
src/zen/@types/lib.gecko.tweaks.d.ts
vendored
8
src/zen/@types/lib.gecko.tweaks.d.ts
vendored
@@ -33,11 +33,15 @@ interface Document {
|
||||
}
|
||||
|
||||
type nsIGleanPingNoReason = {
|
||||
[K in keyof nsIGleanPing]: K extends "submit" ? (_?: never) => void : nsIGleanPing[K];
|
||||
[K in keyof nsIGleanPing]: K extends "submit"
|
||||
? (_?: never) => void
|
||||
: nsIGleanPing[K];
|
||||
};
|
||||
|
||||
type nsIGleanPingWithReason<T> = {
|
||||
[K in keyof nsIGleanPing]: K extends "submit" ? (reason: T) => void : nsIGleanPing[K];
|
||||
[K in keyof nsIGleanPing]: K extends "submit"
|
||||
? (reason: T) => void
|
||||
: nsIGleanPing[K];
|
||||
};
|
||||
|
||||
interface MessageListenerManagerMixin {
|
||||
|
||||
61
src/zen/@types/lib.gecko.win32.d.ts
vendored
61
src/zen/@types/lib.gecko.win32.d.ts
vendored
@@ -56,14 +56,18 @@ declare global {
|
||||
}
|
||||
|
||||
interface nsIWindowsAlertNotification
|
||||
extends nsIAlertNotification,
|
||||
extends
|
||||
nsIAlertNotification,
|
||||
Enums<typeof nsIWindowsAlertNotification_ImagePlacement> {
|
||||
imagePlacement: nsIWindowsAlertNotification.ImagePlacement;
|
||||
}
|
||||
|
||||
interface nsIWindowsAlertsService extends nsIAlertsService {
|
||||
handleWindowsTag(aWindowsTag: string): Promise<any>;
|
||||
getXmlStringForWindowsAlert(aAlert: nsIAlertNotification, aWindowsTag?: string): string;
|
||||
getXmlStringForWindowsAlert(
|
||||
aAlert: nsIAlertNotification,
|
||||
aWindowsTag?: string
|
||||
): string;
|
||||
removeAllNotificationsForInstall(): void;
|
||||
}
|
||||
|
||||
@@ -86,9 +90,18 @@ declare global {
|
||||
aNotificationAction: string,
|
||||
daysSinceLastAppLaunch: u32
|
||||
): void;
|
||||
setDefaultBrowserUserChoice(aAumid: string, aExtraFileExtensions: string[]): void;
|
||||
setDefaultBrowserUserChoiceAsync(aAumid: string, aExtraFileExtensions: string[]): Promise<any>;
|
||||
setDefaultExtensionHandlersUserChoice(aAumid: string, aFileExtensions: string[]): void;
|
||||
setDefaultBrowserUserChoice(
|
||||
aAumid: string,
|
||||
aExtraFileExtensions: string[]
|
||||
): void;
|
||||
setDefaultBrowserUserChoiceAsync(
|
||||
aAumid: string,
|
||||
aExtraFileExtensions: string[]
|
||||
): Promise<any>;
|
||||
setDefaultExtensionHandlersUserChoice(
|
||||
aAumid: string,
|
||||
aFileExtensions: string[]
|
||||
): void;
|
||||
agentDisabled(): boolean;
|
||||
}
|
||||
|
||||
@@ -124,11 +137,13 @@ declare enum nsIWindowsShellService_LaunchOnLoginEnabledEnumerator {
|
||||
|
||||
declare global {
|
||||
namespace nsIWindowsShellService {
|
||||
type LaunchOnLoginEnabledEnumerator = nsIWindowsShellService_LaunchOnLoginEnabledEnumerator;
|
||||
type LaunchOnLoginEnabledEnumerator =
|
||||
nsIWindowsShellService_LaunchOnLoginEnabledEnumerator;
|
||||
}
|
||||
|
||||
interface nsIWindowsShellService
|
||||
extends nsIShellService,
|
||||
extends
|
||||
nsIShellService,
|
||||
Enums<typeof nsIWindowsShellService_LaunchOnLoginEnabledEnumerator> {
|
||||
createShortcut(
|
||||
aBinary: nsIFile,
|
||||
@@ -149,13 +164,19 @@ declare global {
|
||||
pinCurrentAppToTaskbarAsync(aPrivateBrowsing: boolean): Promise<any>;
|
||||
checkPinCurrentAppToTaskbarAsync(aPrivateBrowsing: boolean): Promise<any>;
|
||||
isCurrentAppPinnedToTaskbarAsync(aumid: string): Promise<any>;
|
||||
pinShortcutToTaskbar(aAppUserModelId: string, aShortcutPath: string): Promise<any>;
|
||||
pinShortcutToTaskbar(
|
||||
aAppUserModelId: string,
|
||||
aShortcutPath: string
|
||||
): Promise<any>;
|
||||
createWindowsIcon(aFile: nsIFile, aContainer: imgIContainer): Promise<any>;
|
||||
unpinShortcutFromTaskbar(aShortcutPath: string): void;
|
||||
getTaskbarTabShortcutPath(aShortcutName: string): string;
|
||||
getTaskbarTabPins(): string[];
|
||||
classifyShortcut(aPath: string): string;
|
||||
hasPinnableShortcut(aAUMID: string, aPrivateBrowsing: boolean): Promise<any>;
|
||||
hasPinnableShortcut(
|
||||
aAUMID: string,
|
||||
aPrivateBrowsing: boolean
|
||||
): Promise<any>;
|
||||
canSetDefaultBrowserUserChoice(): boolean;
|
||||
checkAllProgIDsExist(): boolean;
|
||||
checkBrowserUserChoiceHashes(): boolean;
|
||||
@@ -241,7 +262,11 @@ declare global {
|
||||
readonly height: u32;
|
||||
readonly thumbnailAspectRatio: float;
|
||||
requestPreview(aCallback: nsITaskbarPreviewCallback): void;
|
||||
requestThumbnail(aCallback: nsITaskbarPreviewCallback, width: u32, height: u32): void;
|
||||
requestThumbnail(
|
||||
aCallback: nsITaskbarPreviewCallback,
|
||||
width: u32,
|
||||
height: u32
|
||||
): void;
|
||||
onClose(): void;
|
||||
onActivate(): boolean;
|
||||
onClick(button: nsITaskbarPreviewButton): void;
|
||||
@@ -256,7 +281,11 @@ declare global {
|
||||
readonly STATE_ERROR?: 3;
|
||||
readonly STATE_PAUSED?: 4;
|
||||
|
||||
setProgressState(state: nsTaskbarProgressState, currentValue?: u64, maxValue?: u64): void;
|
||||
setProgressState(
|
||||
state: nsTaskbarProgressState,
|
||||
currentValue?: u64,
|
||||
maxValue?: u64
|
||||
): void;
|
||||
}
|
||||
|
||||
// https://searchfox.org/mozilla-central/source/widget/nsITaskbarTabPreview.idl
|
||||
@@ -288,7 +317,9 @@ declare global {
|
||||
): nsITaskbarTabPreview;
|
||||
getTaskbarWindowPreview(shell: nsIDocShell): nsITaskbarWindowPreview;
|
||||
getTaskbarProgress(shell: nsIDocShell): nsITaskbarProgress;
|
||||
getOverlayIconController(shell: nsIDocShell): nsITaskbarOverlayIconController;
|
||||
getOverlayIconController(
|
||||
shell: nsIDocShell
|
||||
): nsITaskbarOverlayIconController;
|
||||
createJumpListBuilder(aPrivateBrowsing: boolean): nsIJumpListBuilder;
|
||||
getGroupIdForWindow(aParent: mozIDOMWindow): string;
|
||||
setGroupIdForWindow(aParent: mozIDOMWindow, aIdentifier: string): void;
|
||||
@@ -304,7 +335,11 @@ declare global {
|
||||
aSmallIcon: imgIContainer,
|
||||
aLargeIcon: imgIContainer
|
||||
): void;
|
||||
setWindowIconFromExe(aWindow: mozIDOMWindowProxy, aExe: string, aIndex: u16): void;
|
||||
setWindowIconFromExe(
|
||||
aWindow: mozIDOMWindowProxy,
|
||||
aExe: string,
|
||||
aIndex: u16
|
||||
): void;
|
||||
setWindowIconNoData(aWindow: mozIDOMWindowProxy): void;
|
||||
readonly inWin10TabletMode: boolean;
|
||||
readonly inWin11TabletMode: boolean;
|
||||
|
||||
2136
src/zen/@types/lib.gecko.xpcom.d.ts
vendored
2136
src/zen/@types/lib.gecko.xpcom.d.ts
vendored
File diff suppressed because it is too large
Load Diff
33
src/zen/@types/zen.d.ts
vendored
33
src/zen/@types/zen.d.ts
vendored
@@ -88,7 +88,9 @@ declare namespace MockedExports {
|
||||
*
|
||||
* Then add the file path to the KnownModules above.
|
||||
*/
|
||||
importESModule: <S extends keyof KnownModules>(module: S) => KnownModules[S];
|
||||
importESModule: <S extends keyof KnownModules>(
|
||||
module: S
|
||||
) => KnownModules[S];
|
||||
defineESModuleGetters: (target: any, mappings: any) => void;
|
||||
}
|
||||
|
||||
@@ -160,7 +162,11 @@ declare namespace MockedExports {
|
||||
setIntPref: SetPref<number>;
|
||||
getBoolPref: GetPref<boolean>;
|
||||
setBoolPref: SetPref<boolean>;
|
||||
addObserver: (aDomain: string, aObserver: PrefObserver, aHoldWeak?: boolean) => void;
|
||||
addObserver: (
|
||||
aDomain: string,
|
||||
aObserver: PrefObserver,
|
||||
aHoldWeak?: boolean
|
||||
) => void;
|
||||
removeObserver: (aDomain: string, aObserver: PrefObserver) => void;
|
||||
};
|
||||
|
||||
@@ -299,7 +305,11 @@ declare namespace MockedExports {
|
||||
class nsIFilePicker {}
|
||||
|
||||
interface FilePicker {
|
||||
init: (browsingContext: BrowsingContext, title: string, mode: number) => void;
|
||||
init: (
|
||||
browsingContext: BrowsingContext,
|
||||
title: string,
|
||||
mode: number
|
||||
) => void;
|
||||
open: (callback: (rv: number) => unknown) => void;
|
||||
// The following are enum values.
|
||||
modeGetFolder: number;
|
||||
@@ -330,7 +340,11 @@ declare namespace MockedExports {
|
||||
* This function sets the attributes data-l10n-id and possibly data-l10n-args
|
||||
* on the element.
|
||||
*/
|
||||
setAttributes(target: Element, id?: string, args?: Record<string, string>): void;
|
||||
setAttributes(
|
||||
target: Element,
|
||||
id?: string,
|
||||
args?: Record<string, string>
|
||||
): void;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +379,8 @@ declare interface ChromeDocument extends Document {
|
||||
* Create a XUL element of a specific type. Right now this function
|
||||
* only refines iframes, but more tags could be added.
|
||||
*/
|
||||
createXULElement: ((type: "iframe") => XULIframeElement) & ((type: string) => XULElement);
|
||||
createXULElement: ((type: "iframe") => XULIframeElement) &
|
||||
((type: string) => XULElement);
|
||||
|
||||
/**
|
||||
* This is a fluent instance connected to this document.
|
||||
@@ -406,7 +421,9 @@ declare interface Window {
|
||||
userContextId: number;
|
||||
forceNonPrivate: boolean;
|
||||
relatedToCurrent: boolean;
|
||||
resolveOnContentBrowserCreated: (contentBrowser: MockedExports.ChromeBrowser) => unknown;
|
||||
resolveOnContentBrowserCreated: (
|
||||
contentBrowser: MockedExports.ChromeBrowser
|
||||
) => unknown;
|
||||
}>
|
||||
) => void;
|
||||
openTrustedLinkIn: (
|
||||
@@ -417,7 +434,9 @@ declare interface Window {
|
||||
userContextId: number;
|
||||
forceNonPrivate: boolean;
|
||||
relatedToCurrent: boolean;
|
||||
resolveOnContentBrowserCreated: (contentBrowser: MockedExports.ChromeBrowser) => unknown;
|
||||
resolveOnContentBrowserCreated: (
|
||||
contentBrowser: MockedExports.ChromeBrowser
|
||||
) => unknown;
|
||||
}>
|
||||
) => void;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,9 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature {
|
||||
case "command":
|
||||
if (event.target.id === "PanelUI-zen-emojis-picker-none") {
|
||||
this.#selectEmoji(null);
|
||||
} else if (event.target.id === "PanelUI-zen-emojis-picker-change-emojis") {
|
||||
} else if (
|
||||
event.target.id === "PanelUI-zen-emojis-picker-change-emojis"
|
||||
) {
|
||||
this.#changePage(false);
|
||||
} else if (event.target.id === "PanelUI-zen-emojis-picker-change-svg") {
|
||||
this.#changePage(true);
|
||||
@@ -104,7 +106,9 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature {
|
||||
#changePage(toSvg = false) {
|
||||
const itemToScroll = toSvg
|
||||
? this.svgList
|
||||
: document.getElementById("PanelUI-zen-emojis-picker-pages").querySelector('[emojis="true"]');
|
||||
: document
|
||||
.getElementById("PanelUI-zen-emojis-picker-pages")
|
||||
.querySelector('[emojis="true"]');
|
||||
itemToScroll.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "nearest",
|
||||
@@ -137,15 +141,19 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature {
|
||||
const value = input.value.trim().toLowerCase();
|
||||
// search for emojis.tags and order by emojis.order
|
||||
const filteredEmojis = this.#emojis
|
||||
.filter((emoji) => {
|
||||
return emoji.tags.some((tag) => tag.toLowerCase().includes(value));
|
||||
.filter(emoji => {
|
||||
return emoji.tags.some(tag => tag.toLowerCase().includes(value));
|
||||
})
|
||||
.sort((a, b) => a.order - b.order);
|
||||
for (const button of this.emojiList.children) {
|
||||
const buttonEmoji = button.getAttribute("label");
|
||||
const emojiObject = filteredEmojis.find((emoji) => emoji.emoji === buttonEmoji);
|
||||
const emojiObject = filteredEmojis.find(
|
||||
emoji => emoji.emoji === buttonEmoji
|
||||
);
|
||||
if (emojiObject) {
|
||||
button.hidden = !emojiObject.tags.some((tag) => tag.toLowerCase().includes(value));
|
||||
button.hidden = !emojiObject.tags.some(tag =>
|
||||
tag.toLowerCase().includes(value)
|
||||
);
|
||||
button.style.order = emojiObject.order;
|
||||
} else {
|
||||
button.hidden = true;
|
||||
@@ -205,7 +213,9 @@ class nsZenEmojiPicker extends nsZenDOMOperatedFeature {
|
||||
this.svgList.innerHTML = "";
|
||||
|
||||
if (!this.#hasSelection) {
|
||||
this.#currentPromiseReject?.(new Error("Emoji picker closed without selection"));
|
||||
this.#currentPromiseReject?.(
|
||||
new Error("Emoji picker closed without selection")
|
||||
);
|
||||
} else if (!this.#closeOnSelect) {
|
||||
this.#currentPromiseResolve?.(this.#lastSelectedEmoji);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -78,7 +78,9 @@ export class nsZenDOMOperatedFeature {
|
||||
export class nsZenPreloadedFeature {
|
||||
constructor() {
|
||||
var initBound = this.init.bind(this);
|
||||
document.addEventListener("MozBeforeInitialXULLayout", initBound, { once: true });
|
||||
document.addEventListener("MozBeforeInitialXULLayout", initBound, {
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +94,7 @@ window.gZenCommonActions = {
|
||||
if (Services.zen.canShare() && displaySpec.startsWith("http")) {
|
||||
button = {
|
||||
id: "zen-copy-current-url-button",
|
||||
command: (event) => {
|
||||
command: event => {
|
||||
const buttonRect = event.target.getBoundingClientRect();
|
||||
/* eslint-disable mozilla/valid-services */
|
||||
Services.zen.share(
|
||||
@@ -107,7 +109,10 @@ window.gZenCommonActions = {
|
||||
},
|
||||
};
|
||||
}
|
||||
gZenUIManager.showToast("zen-copy-current-url-confirmation", { button, timeout: 3000 });
|
||||
gZenUIManager.showToast("zen-copy-current-url-confirmation", {
|
||||
button,
|
||||
timeout: 3000,
|
||||
});
|
||||
},
|
||||
|
||||
copyCurrentURLAsMarkdownToClipboard() {
|
||||
@@ -115,7 +120,9 @@ window.gZenCommonActions = {
|
||||
const tabTitle = gBrowser.selectedTab.label;
|
||||
const markdownLink = `[${tabTitle}](${currentUrl.displaySpec})`;
|
||||
ClipboardHelper.copyString(markdownLink);
|
||||
gZenUIManager.showToast("zen-copy-current-url-confirmation", { timeout: 3000 });
|
||||
gZenUIManager.showToast("zen-copy-current-url-as-markdown-confirmation", {
|
||||
timeout: 3000,
|
||||
});
|
||||
},
|
||||
|
||||
throttle(f, delay) {
|
||||
@@ -134,10 +141,17 @@ window.gZenCommonActions = {
|
||||
* @returns {boolean} True if the tab should be closed on back
|
||||
*/
|
||||
shouldCloseTabOnBack() {
|
||||
if (!Services.prefs.getBoolPref("zen.tabs.close-on-back-with-no-history", true)) {
|
||||
if (
|
||||
!Services.prefs.getBoolPref(
|
||||
"zen.tabs.close-on-back-with-no-history",
|
||||
true
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const tab = gBrowser.selectedTab;
|
||||
return Boolean(tab.owner && !tab.pinned && !tab.hasAttribute("zen-empty-tab"));
|
||||
return Boolean(
|
||||
tab.owner && !tab.pinned && !tab.hasAttribute("zen-empty-tab")
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,7 +14,12 @@ class nsHasPolyfill {
|
||||
* @param {string} stateAttribute
|
||||
* @param {Array<string>} attributeFilter
|
||||
*/
|
||||
observeSelectorExistence(element, descendantSelectors, stateAttribute, attributeFilter = []) {
|
||||
observeSelectorExistence(
|
||||
element,
|
||||
descendantSelectors,
|
||||
stateAttribute,
|
||||
attributeFilter = []
|
||||
) {
|
||||
const updateState = () => {
|
||||
const exists = descendantSelectors.some(({ selector }) => {
|
||||
let selected = element.querySelector(selector);
|
||||
@@ -26,10 +31,18 @@ class nsHasPolyfill {
|
||||
const { exists: shouldExist = true } = descendantSelectors;
|
||||
if (exists === shouldExist) {
|
||||
if (!element.hasAttribute(stateAttribute)) {
|
||||
gZenCompactModeManager._setElementExpandAttribute(element, true, stateAttribute);
|
||||
gZenCompactModeManager._setElementExpandAttribute(
|
||||
element,
|
||||
true,
|
||||
stateAttribute
|
||||
);
|
||||
}
|
||||
} else if (element.hasAttribute(stateAttribute)) {
|
||||
gZenCompactModeManager._setElementExpandAttribute(element, false, stateAttribute);
|
||||
gZenCompactModeManager._setElementExpandAttribute(
|
||||
element,
|
||||
false,
|
||||
stateAttribute
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,31 +59,35 @@ class nsHasPolyfill {
|
||||
}
|
||||
|
||||
disconnectObserver(observerId) {
|
||||
const index = this.observers.findIndex((o) => o.id === observerId);
|
||||
const index = this.observers.findIndex(o => o.id === observerId);
|
||||
if (index !== -1) {
|
||||
this.observers[index].observer.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
connectObserver(observerId) {
|
||||
const observer = this.observers.find((o) => o.id === observerId);
|
||||
const observer = this.observers.find(o => o.id === observerId);
|
||||
if (observer) {
|
||||
observer.observer.observe(observer.element, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
attributeFilter: observer.attributeFilter.length ? observer.attributeFilter : undefined,
|
||||
attributeFilter: observer.attributeFilter.length
|
||||
? observer.attributeFilter
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.observers.forEach((observer) => observer.observer.disconnect());
|
||||
this.observers.forEach(observer => observer.observer.disconnect());
|
||||
this.observers = [];
|
||||
}
|
||||
}
|
||||
|
||||
const hasPolyfillInstance = new nsHasPolyfill();
|
||||
window.addEventListener("unload", () => hasPolyfillInstance.destroy(), { once: true });
|
||||
window.addEventListener("unload", () => hasPolyfillInstance.destroy(), {
|
||||
once: true,
|
||||
});
|
||||
|
||||
window.ZenHasPolyfill = hasPolyfillInstance;
|
||||
|
||||
@@ -38,7 +38,7 @@ export class nsZenMenuBar {
|
||||
</menupopup>
|
||||
</menu>`);
|
||||
const menu = appearanceMenu.querySelector("menu");
|
||||
menu.addEventListener("command", (event) => {
|
||||
menu.addEventListener("command", event => {
|
||||
const type = event.target.getAttribute("data-type");
|
||||
const schemeValue = WINDOW_SCHEME_MAPPING[type];
|
||||
Services.prefs.setIntPref(WINDOW_SCHEME_PREF, schemeValue);
|
||||
@@ -97,15 +97,17 @@ export class nsZenMenuBar {
|
||||
</menupopup>
|
||||
</menu>`);
|
||||
document.getElementById("view-menu").after(spacesMenubar);
|
||||
document.getElementById("zen-spaces-menubar").addEventListener("popupshowing", () => {
|
||||
if (AppConstants.platform === "linux") {
|
||||
// On linux, there seems to be a bug where the menu freezes up and makes the browser
|
||||
// suppiciously unresponsive if we try to update the menu while it's opening.
|
||||
// See https://github.com/zen-browser/desktop/issues/12024
|
||||
return;
|
||||
}
|
||||
gZenWorkspaces.updateWorkspacesChangeContextMenu();
|
||||
});
|
||||
document
|
||||
.getElementById("zen-spaces-menubar")
|
||||
.addEventListener("popupshowing", () => {
|
||||
if (AppConstants.platform === "linux") {
|
||||
// On linux, there seems to be a bug where the menu freezes up and makes the browser
|
||||
// suppiciously unresponsive if we try to update the menu while it's opening.
|
||||
// See https://github.com/zen-browser/desktop/issues/12024
|
||||
return;
|
||||
}
|
||||
gZenWorkspaces.updateWorkspacesChangeContextMenu();
|
||||
});
|
||||
}
|
||||
|
||||
#initAppMenu() {
|
||||
@@ -133,7 +135,10 @@ export class nsZenMenuBar {
|
||||
if (!Services.prefs.getBoolPref("zen.window-sync.enabled", true)) {
|
||||
return;
|
||||
}
|
||||
const itemsToHide = ["appMenuRecentlyClosedWindows", "historyUndoWindowMenu"];
|
||||
const itemsToHide = [
|
||||
"appMenuRecentlyClosedWindows",
|
||||
"historyUndoWindowMenu",
|
||||
];
|
||||
for (const id of itemsToHide) {
|
||||
const element = PanelMultiView.getViewNode(document, id);
|
||||
element.setAttribute("hidden", "true");
|
||||
|
||||
@@ -9,7 +9,7 @@ class ZenSessionStore extends nsZenPreloadedFeature {
|
||||
this.#waitAndCleanup();
|
||||
}
|
||||
|
||||
promiseInitialized = new Promise((resolve) => {
|
||||
promiseInitialized = new Promise(resolve => {
|
||||
this._resolveInitialized = resolve;
|
||||
});
|
||||
|
||||
|
||||
@@ -47,19 +47,24 @@ class ZenSidebarNotification extends MozLitElement {
|
||||
return html`
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-sidebar-notification.css" />
|
||||
href="chrome://browser/content/zen-styles/zen-sidebar-notification.css"
|
||||
/>
|
||||
<div class="zen-sidebar-notification-header">
|
||||
<label
|
||||
class="zen-sidebar-notification-heading"
|
||||
flex="1"
|
||||
data-l10n-id=${this.headingL10nId}></label>
|
||||
<div class="zen-sidebar-notification-close-button" @click=${() => this.remove()}>
|
||||
data-l10n-id=${this.headingL10nId}
|
||||
></label>
|
||||
<div
|
||||
class="zen-sidebar-notification-close-button"
|
||||
@click=${() => this.remove()}
|
||||
>
|
||||
<img src="chrome://browser/skin/zen-icons/close.svg" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="zen-sidebar-notification-body">
|
||||
${this.links.map(
|
||||
(link) => html`
|
||||
link => html`
|
||||
<div
|
||||
class="zen-sidebar-notification-link-container"
|
||||
data-l10n-id="${link.l10nId}-tooltip"
|
||||
@@ -70,15 +75,21 @@ class ZenSidebarNotification extends MozLitElement {
|
||||
return;
|
||||
}
|
||||
window.openLinkIn(link.url, "tab", {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
triggeringPrincipal:
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
forceForeground: true,
|
||||
});
|
||||
this.remove();
|
||||
}}>
|
||||
<img class="zen-sidebar-notification-link-icon" src=${link.icon} />
|
||||
}}
|
||||
>
|
||||
<img
|
||||
class="zen-sidebar-notification-link-icon"
|
||||
src=${link.icon}
|
||||
/>
|
||||
<label
|
||||
class="zen-sidebar-notification-link-text"
|
||||
data-l10n-id="${link.l10nId}-label"></label>
|
||||
data-l10n-id="${link.l10nId}-label"
|
||||
></label>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
|
||||
@@ -11,10 +11,12 @@ class ZenStartup {
|
||||
#hasInitializedLayout = false;
|
||||
|
||||
isReady = false;
|
||||
promiseInitialized = new Promise(resolve => {
|
||||
this.promiseInitializedResolve = resolve;
|
||||
});
|
||||
|
||||
init() {
|
||||
this.openWatermark();
|
||||
this.#initBrowserBackground();
|
||||
this.#changeSidebarLocation();
|
||||
this.#zenInitBrowserLayout();
|
||||
}
|
||||
@@ -26,20 +28,6 @@ class ZenStartup {
|
||||
);
|
||||
}
|
||||
|
||||
#initBrowserBackground() {
|
||||
const background = document.createXULElement("box");
|
||||
background.id = "zen-browser-background";
|
||||
background.classList.add("zen-browser-generic-background");
|
||||
const grain = document.createXULElement("box");
|
||||
grain.classList.add("zen-browser-grain");
|
||||
background.appendChild(grain);
|
||||
document.getElementById("browser").prepend(background);
|
||||
const toolbarBackground = background.cloneNode(true);
|
||||
toolbarBackground.removeAttribute("id");
|
||||
toolbarBackground.classList.add("zen-toolbar-background");
|
||||
document.getElementById("titlebar").prepend(toolbarBackground);
|
||||
}
|
||||
|
||||
#zenInitBrowserLayout() {
|
||||
if (this.#hasInitializedLayout) {
|
||||
return;
|
||||
@@ -60,7 +48,9 @@ class ZenStartup {
|
||||
}
|
||||
|
||||
// Fix notification deck
|
||||
const deckTemplate = document.getElementById("tab-notification-deck-template");
|
||||
const deckTemplate = document.getElementById(
|
||||
"tab-notification-deck-template"
|
||||
);
|
||||
if (deckTemplate) {
|
||||
document.getElementById("zen-appcontent-wrapper").prepend(deckTemplate);
|
||||
}
|
||||
@@ -103,8 +93,12 @@ class ZenStartup {
|
||||
// Just in case we didn't get the right size.
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
this.closeWatermark();
|
||||
document.getElementById("tabbrowser-arrowscrollbox").setAttribute("orient", "vertical");
|
||||
document
|
||||
.getElementById("tabbrowser-arrowscrollbox")
|
||||
.setAttribute("orient", "vertical");
|
||||
this.isReady = true;
|
||||
this.promiseInitializedResolve();
|
||||
delete this.promiseInitializedResolve;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,10 +115,14 @@ class ZenStartup {
|
||||
closeWatermark() {
|
||||
document.documentElement.removeAttribute("zen-before-loaded");
|
||||
if (this.#shouldUseWatermark) {
|
||||
let elementsToIgnore = this.#watermarkIgnoreElements.map((id) => "#" + id).join(", ");
|
||||
let elementsToIgnore = this.#watermarkIgnoreElements
|
||||
.map(id => "#" + id)
|
||||
.join(", ");
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
"#browser > *:not(" + elementsToIgnore + "), #urlbar, #tabbrowser-tabbox > *",
|
||||
"#browser > *:not(" +
|
||||
elementsToIgnore +
|
||||
"), #urlbar, #tabbrowser-tabbox > *",
|
||||
{
|
||||
opacity: [0, 1],
|
||||
},
|
||||
@@ -163,8 +161,14 @@ class ZenStartup {
|
||||
#checkForWelcomePage() {
|
||||
if (!Services.prefs.getBoolPref("zen.welcome-screen.seen", false)) {
|
||||
Services.prefs.setBoolPref("zen.welcome-screen.seen", true);
|
||||
Services.prefs.setStringPref("zen.updates.last-build-id", Services.appinfo.appBuildID);
|
||||
Services.prefs.setStringPref("zen.updates.last-version", Services.appinfo.version);
|
||||
Services.prefs.setStringPref(
|
||||
"zen.updates.last-build-id",
|
||||
Services.appinfo.appBuildID
|
||||
);
|
||||
Services.prefs.setStringPref(
|
||||
"zen.updates.last-version",
|
||||
Services.appinfo.version
|
||||
);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://browser/content/zen-components/ZenWelcome.mjs",
|
||||
window
|
||||
|
||||
@@ -10,7 +10,10 @@ window.gZenUIManager = {
|
||||
_hoverPausedForExpand: false,
|
||||
_hasLoadedDOM: false,
|
||||
testingEnabled: Services.prefs.getBoolPref("zen.testing.enabled", false),
|
||||
profilingEnabled: Services.prefs.getBoolPref("zen.testing.profiling.enabled", false),
|
||||
profilingEnabled: Services.prefs.getBoolPref(
|
||||
"zen.testing.profiling.enabled",
|
||||
false
|
||||
),
|
||||
|
||||
_lastClickPosition: null,
|
||||
|
||||
@@ -22,7 +25,11 @@ window.gZenUIManager = {
|
||||
document.addEventListener("popupshowing", this.onPopupShowing.bind(this));
|
||||
document.addEventListener("popuphidden", this.onPopupHidden.bind(this));
|
||||
|
||||
document.addEventListener("mousedown", this.handleMouseDown.bind(this), true);
|
||||
document.addEventListener(
|
||||
"mousedown",
|
||||
this.handleMouseDown.bind(this),
|
||||
true
|
||||
);
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, "motion", () => {
|
||||
Services.scriptloader.loadSubScript(
|
||||
@@ -40,7 +47,9 @@ window.gZenUIManager = {
|
||||
|
||||
new ResizeObserver(
|
||||
gZenCommonActions.throttle(
|
||||
gZenCompactModeManager.getAndApplySidebarWidth.bind(gZenCompactModeManager),
|
||||
gZenCompactModeManager.getAndApplySidebarWidth.bind(
|
||||
gZenCompactModeManager
|
||||
),
|
||||
Services.prefs.getIntPref("zen.view.sidebar-height-throttle", 500)
|
||||
)
|
||||
).observe(gNavToolbox);
|
||||
@@ -82,7 +91,10 @@ window.gZenUIManager = {
|
||||
rawKeyframes = { ...rawKeyframes };
|
||||
// Convert 'y' property to 'transform' with translateY and 'x' to translateX,
|
||||
// and 'scale' to 'transform' with scale.
|
||||
if ((rawKeyframes.y || rawKeyframes.x || rawKeyframes.scale) && !rawKeyframes.transform) {
|
||||
if (
|
||||
(rawKeyframes.y || rawKeyframes.x || rawKeyframes.scale) &&
|
||||
!rawKeyframes.transform
|
||||
) {
|
||||
const yValues = rawKeyframes.y || [];
|
||||
const xValues = rawKeyframes.x || [];
|
||||
const scaleValues = rawKeyframes.scale || [];
|
||||
@@ -90,14 +102,23 @@ window.gZenUIManager = {
|
||||
delete rawKeyframes.x;
|
||||
delete rawKeyframes.scale;
|
||||
rawKeyframes.transform = [];
|
||||
if (yValues.length !== 0 && xValues.length !== 0 && yValues.length !== xValues.length) {
|
||||
if (
|
||||
yValues.length !== 0 &&
|
||||
xValues.length !== 0 &&
|
||||
yValues.length !== xValues.length
|
||||
) {
|
||||
console.error("y and x keyframes must have the same length");
|
||||
}
|
||||
const keyframeLength = Math.max(yValues.length, xValues.length, scaleValues.length);
|
||||
const keyframeLength = Math.max(
|
||||
yValues.length,
|
||||
xValues.length,
|
||||
scaleValues.length
|
||||
);
|
||||
for (let i = 0; i < keyframeLength; i++) {
|
||||
const y = yValues[i] !== undefined ? `translateY(${yValues[i]}px)` : "";
|
||||
const x = xValues[i] !== undefined ? `translateX(${xValues[i]}px)` : "";
|
||||
const scale = scaleValues[i] !== undefined ? `scale(${scaleValues[i]})` : "";
|
||||
const scale =
|
||||
scaleValues[i] !== undefined ? `scale(${scaleValues[i]})` : "";
|
||||
rawKeyframes.transform.push(`${x} ${y} ${scale}`.trim());
|
||||
}
|
||||
}
|
||||
@@ -109,7 +130,7 @@ window.gZenUIManager = {
|
||||
}
|
||||
keyframes.push(frame);
|
||||
}
|
||||
return await new Promise((resolve) => {
|
||||
return await new Promise(resolve => {
|
||||
const animation = element.animate(keyframes, ...args);
|
||||
animation.onfinish = () => resolve();
|
||||
});
|
||||
@@ -117,10 +138,19 @@ window.gZenUIManager = {
|
||||
|
||||
_addNewCustomizableButtonsIfNeeded() {
|
||||
const kPref = "zen.ui.migration.compact-mode-button-added";
|
||||
let navbarPlacements = CustomizableUI.getWidgetIdsInArea("zen-sidebar-top-buttons");
|
||||
let navbarPlacements = CustomizableUI.getWidgetIdsInArea(
|
||||
"zen-sidebar-top-buttons"
|
||||
);
|
||||
try {
|
||||
if (!navbarPlacements.length && !Services.prefs.getBoolPref(kPref, false)) {
|
||||
CustomizableUI.addWidgetToArea("zen-toggle-compact-mode", "zen-sidebar-top-buttons", 0);
|
||||
if (
|
||||
!navbarPlacements.length &&
|
||||
!Services.prefs.getBoolPref(kPref, false)
|
||||
) {
|
||||
CustomizableUI.addWidgetToArea(
|
||||
"zen-toggle-compact-mode",
|
||||
"zen-sidebar-top-buttons",
|
||||
0
|
||||
);
|
||||
gZenVerticalTabsManager._topButtonsSeparatorElement.before(
|
||||
document.getElementById("zen-toggle-compact-mode")
|
||||
);
|
||||
@@ -138,7 +168,7 @@ window.gZenUIManager = {
|
||||
// is ran before this function.
|
||||
document.documentElement.setAttribute("zen-has-bookmarks", "true");
|
||||
}
|
||||
bookmarkToolbar.addEventListener("toolbarvisibilitychange", (event) => {
|
||||
bookmarkToolbar.addEventListener("toolbarvisibilitychange", event => {
|
||||
const visible = event.detail.visible;
|
||||
if (visible) {
|
||||
document.documentElement.setAttribute("zen-has-bookmarks", "true");
|
||||
@@ -221,11 +251,16 @@ window.gZenUIManager = {
|
||||
const kUrlbarHeight = 335;
|
||||
gURLBar.style.setProperty(
|
||||
"--zen-urlbar-top",
|
||||
`${window.innerHeight / 2 - Math.max(kUrlbarHeight, gURLBar.getBoundingClientRect().height) / 2}px`
|
||||
`${window.innerHeight / 2 - Math.max(kUrlbarHeight, window.windowUtils.getBoundsWithoutFlushing(gURLBar).height) / 2}px`
|
||||
);
|
||||
gURLBar.style.setProperty("--zen-urlbar-width", `${Math.min(window.innerWidth / 2, 750)}px`);
|
||||
gZenVerticalTabsManager.actualWindowButtons.removeAttribute("zen-has-hover");
|
||||
gZenVerticalTabsManager.recalculateURLBarHeight();
|
||||
gURLBar.style.setProperty(
|
||||
"--zen-urlbar-width",
|
||||
`${Math.min(window.innerWidth / 2, 750)}px`
|
||||
);
|
||||
gZenVerticalTabsManager.actualWindowButtons.removeAttribute(
|
||||
"zen-has-hover"
|
||||
);
|
||||
gZenVerticalTabsManager.recalculateURLBarHeight(true);
|
||||
if (!this._preventToolbarRebuild) {
|
||||
setTimeout(() => {
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
@@ -256,7 +291,10 @@ window.gZenUIManager = {
|
||||
|
||||
openAndChangeToTab(url, options) {
|
||||
if (window.ownerGlobal.parent) {
|
||||
const tab = window.ownerGlobal.parent.gBrowser.addTrustedTab(url, options);
|
||||
const tab = window.ownerGlobal.parent.gBrowser.addTrustedTab(
|
||||
url,
|
||||
options
|
||||
);
|
||||
window.ownerGlobal.parent.gBrowser.selectedTab = tab;
|
||||
return tab;
|
||||
}
|
||||
@@ -270,7 +308,10 @@ window.gZenUIManager = {
|
||||
},
|
||||
|
||||
createValidXULText(text) {
|
||||
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||
return text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -302,7 +343,11 @@ window.gZenUIManager = {
|
||||
continue;
|
||||
}
|
||||
document.removeEventListener("mousemove", this.__removeHasPopupAttribute);
|
||||
gZenCompactModeManager._setElementExpandAttribute(el, true, "has-popup-menu");
|
||||
gZenCompactModeManager._setElementExpandAttribute(
|
||||
el,
|
||||
true,
|
||||
"has-popup-menu"
|
||||
);
|
||||
this.__currentPopup = showEvent.target;
|
||||
this.__currentPopupTrackElement = el;
|
||||
break;
|
||||
@@ -315,11 +360,21 @@ window.gZenUIManager = {
|
||||
}
|
||||
const element = this.__currentPopupTrackElement;
|
||||
if (document.getElementById("main-window").matches(":hover")) {
|
||||
gZenCompactModeManager._setElementExpandAttribute(element, false, "has-popup-menu");
|
||||
gZenCompactModeManager._setElementExpandAttribute(
|
||||
element,
|
||||
false,
|
||||
"has-popup-menu"
|
||||
);
|
||||
} else {
|
||||
this.__removeHasPopupAttribute = () =>
|
||||
gZenCompactModeManager._setElementExpandAttribute(element, false, "has-popup-menu");
|
||||
document.addEventListener("mousemove", this.__removeHasPopupAttribute, { once: true });
|
||||
gZenCompactModeManager._setElementExpandAttribute(
|
||||
element,
|
||||
false,
|
||||
"has-popup-menu"
|
||||
);
|
||||
document.addEventListener("mousemove", this.__removeHasPopupAttribute, {
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
this.__currentPopup = null;
|
||||
this.__currentPopupTrackElement = null;
|
||||
@@ -347,9 +402,11 @@ window.gZenUIManager = {
|
||||
const input = gURLBar;
|
||||
if (gURLBar.hasAttribute("breakout-extend") && !this._animatingSearchMode) {
|
||||
this._animatingSearchMode = true;
|
||||
this.motion.animate(input, { scale: [1, 0.98, 1] }, { duration: 0.25 }).then(() => {
|
||||
delete this._animatingSearchMode;
|
||||
});
|
||||
this.motion
|
||||
.animate(input, { scale: [1, 0.98, 1] }, { duration: 0.25 })
|
||||
.then(() => {
|
||||
delete this._animatingSearchMode;
|
||||
});
|
||||
if (searchMode) {
|
||||
gURLBar.setAttribute("animate-searchmode", "true");
|
||||
this._animatingSearchModeTimeout = setTimeout(() => {
|
||||
@@ -416,7 +473,12 @@ window.gZenUIManager = {
|
||||
return true;
|
||||
},
|
||||
|
||||
handleNewTab(werePassedURL, searchClipboard, where, overridePreferance = false) {
|
||||
handleNewTab(
|
||||
werePassedURL,
|
||||
searchClipboard,
|
||||
where,
|
||||
overridePreferance = false
|
||||
) {
|
||||
// Validate browser state first
|
||||
if (!this._validateBrowserState()) {
|
||||
console.warn("Browser state invalid for new tab operation");
|
||||
@@ -548,7 +610,9 @@ window.gZenUIManager = {
|
||||
if (isFocusedBefore) {
|
||||
setTimeout(() => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("ZenURLBarClosed", { detail: { onSwitch, onElementPicked } })
|
||||
new CustomEvent("ZenURLBarClosed", {
|
||||
detail: { onSwitch, onElementPicked },
|
||||
})
|
||||
);
|
||||
gURLBar.view.close({ elementPicked: onElementPicked });
|
||||
gURLBar.updateTextOverflow();
|
||||
@@ -559,8 +623,15 @@ window.gZenUIManager = {
|
||||
|
||||
// Ensure tab and browser are valid before updating state
|
||||
const selectedTab = gBrowser.selectedTab;
|
||||
if (selectedTab && selectedTab.linkedBrowser && !selectedTab.closing && onSwitch) {
|
||||
const browserState = gURLBar.getBrowserState(selectedTab.linkedBrowser);
|
||||
if (
|
||||
selectedTab &&
|
||||
selectedTab.linkedBrowser &&
|
||||
!selectedTab.closing &&
|
||||
onSwitch
|
||||
) {
|
||||
const browserState = gURLBar.getBrowserState(
|
||||
selectedTab.linkedBrowser
|
||||
);
|
||||
if (browserState) {
|
||||
browserState.urlbarFocused = false;
|
||||
}
|
||||
@@ -574,7 +645,10 @@ window.gZenUIManager = {
|
||||
if (gURLBar.hasAttribute("breakout-extend")) {
|
||||
return aURL;
|
||||
}
|
||||
if (gZenVerticalTabsManager._hasSetSingleToolbar && this.urlbarShowDomainOnly) {
|
||||
if (
|
||||
gZenVerticalTabsManager._hasSetSingleToolbar &&
|
||||
this.urlbarShowDomainOnly
|
||||
) {
|
||||
let url = BrowserUIUtils.removeSingleTrailingSlashFromURL(aURL);
|
||||
return url.startsWith("https://") ? url.split("/")[2] : url;
|
||||
}
|
||||
@@ -639,7 +713,11 @@ window.gZenUIManager = {
|
||||
return;
|
||||
}
|
||||
this.motion
|
||||
.animate(toast, { opacity: [1, 0], scale: [1, 0.5] }, { duration: 0.2, bounce: 0 })
|
||||
.animate(
|
||||
toast,
|
||||
{ opacity: [1, 0], scale: [1, 0.5] },
|
||||
{ duration: 0.2, bounce: 0 }
|
||||
)
|
||||
.then(() => {
|
||||
toast.remove();
|
||||
if (this._toastContainer.children.length === 0) {
|
||||
@@ -648,7 +726,11 @@ window.gZenUIManager = {
|
||||
});
|
||||
};
|
||||
if (reused) {
|
||||
await this.motion.animate(toast, { scale: 0.2 }, { duration: 0.1, bounce: 0 });
|
||||
await this.motion.animate(
|
||||
toast,
|
||||
{ scale: 0.2 },
|
||||
{ duration: 0.1, bounce: 0 }
|
||||
);
|
||||
} else {
|
||||
toast.addEventListener("mouseover", () => {
|
||||
if (this._toastTimeouts[messageId]) {
|
||||
@@ -659,17 +741,27 @@ window.gZenUIManager = {
|
||||
if (this._toastTimeouts[messageId]) {
|
||||
clearTimeout(this._toastTimeouts[messageId]);
|
||||
}
|
||||
this._toastTimeouts[messageId] = setTimeout(timeoutFunction, options.timeout || 2000);
|
||||
this._toastTimeouts[messageId] = setTimeout(
|
||||
timeoutFunction,
|
||||
options.timeout || 2000
|
||||
);
|
||||
});
|
||||
}
|
||||
if (!toast.style.transform) {
|
||||
toast.style.transform = "scale(0)";
|
||||
}
|
||||
await this.motion.animate(toast, { scale: 1 }, { type: "spring", bounce: 0.2, duration: 0.5 });
|
||||
await this.motion.animate(
|
||||
toast,
|
||||
{ scale: 1 },
|
||||
{ type: "spring", bounce: 0.2, duration: 0.5 }
|
||||
);
|
||||
if (this._toastTimeouts[messageId]) {
|
||||
clearTimeout(this._toastTimeouts[messageId]);
|
||||
}
|
||||
this._toastTimeouts[messageId] = setTimeout(timeoutFunction, options.timeout || 2000);
|
||||
this._toastTimeouts[messageId] = setTimeout(
|
||||
timeoutFunction,
|
||||
options.timeout || 2000
|
||||
);
|
||||
},
|
||||
|
||||
panelUIPosition(panel, anchor) {
|
||||
@@ -722,10 +814,12 @@ window.gZenUIManager = {
|
||||
block = "topleft";
|
||||
}
|
||||
if (
|
||||
(gZenVerticalTabsManager._hasSetSingleToolbar && gZenVerticalTabsManager._prefsRightSide) ||
|
||||
(gZenVerticalTabsManager._hasSetSingleToolbar &&
|
||||
gZenVerticalTabsManager._prefsRightSide) ||
|
||||
(panel?.id === "zen-unified-site-data-panel" &&
|
||||
!gZenVerticalTabsManager._hasSetSingleToolbar) ||
|
||||
(panel?.id === "unified-extensions-panel" && gZenVerticalTabsManager._hasSetSingleToolbar)
|
||||
(panel?.id === "unified-extensions-panel" &&
|
||||
gZenVerticalTabsManager._hasSetSingleToolbar)
|
||||
) {
|
||||
block = "bottomright";
|
||||
inline = "topright";
|
||||
@@ -787,14 +881,20 @@ window.gZenVerticalTabsManager = {
|
||||
return !(
|
||||
window.AppConstants.platform === "macosx" ||
|
||||
window.matchMedia("(-moz-gtk-csd-reversed-placement)").matches ||
|
||||
Services.prefs.getBoolPref("zen.view.experimental-force-window-controls-left")
|
||||
Services.prefs.getBoolPref(
|
||||
"zen.view.experimental-force-window-controls-left"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(this, "hidesTabsToolbar", () => {
|
||||
return (
|
||||
document.documentElement.getAttribute("chromehidden")?.includes("toolbar") ||
|
||||
document.documentElement.getAttribute("chromehidden")?.includes("menubar")
|
||||
document.documentElement
|
||||
.getAttribute("chromehidden")
|
||||
?.includes("toolbar") ||
|
||||
document.documentElement
|
||||
.getAttribute("chromehidden")
|
||||
?.includes("menubar")
|
||||
);
|
||||
});
|
||||
|
||||
@@ -808,22 +908,35 @@ window.gZenVerticalTabsManager = {
|
||||
var onPrefChange = this._onPrefChange.bind(this);
|
||||
|
||||
this.initializePreferences(onPrefChange);
|
||||
this._toolbarOriginalParent = document.getElementById("nav-bar").parentElement;
|
||||
this._toolbarOriginalParent =
|
||||
document.getElementById("nav-bar").parentElement;
|
||||
|
||||
gZenCompactModeManager.addEventListener(updateEvent);
|
||||
this.initRightSideOrderContextMenu();
|
||||
|
||||
window.addEventListener("customizationstarting", this._preCustomize.bind(this));
|
||||
window.addEventListener("aftercustomization", this._postCustomize.bind(this));
|
||||
window.addEventListener(
|
||||
"customizationstarting",
|
||||
this._preCustomize.bind(this)
|
||||
);
|
||||
window.addEventListener(
|
||||
"aftercustomization",
|
||||
this._postCustomize.bind(this)
|
||||
);
|
||||
|
||||
this._updateEvent();
|
||||
|
||||
if (!this.isWindowsStyledButtons) {
|
||||
document.documentElement.setAttribute("zen-window-buttons-reversed", true);
|
||||
document.documentElement.setAttribute(
|
||||
"zen-window-buttons-reversed",
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
this._renameTabHalt = this.renameTabHalt.bind(this);
|
||||
gBrowser.tabContainer.addEventListener("dblclick", this.renameTabStart.bind(this));
|
||||
gBrowser.tabContainer.addEventListener(
|
||||
"dblclick",
|
||||
this.renameTabStart.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
toggleExpand() {
|
||||
@@ -896,7 +1009,7 @@ window.gZenVerticalTabsManager = {
|
||||
}
|
||||
)
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -905,7 +1018,8 @@ window.gZenVerticalTabsManager = {
|
||||
aItem.style.removeProperty("opacity");
|
||||
});
|
||||
const itemLabel =
|
||||
aItem.querySelector(".tab-group-label-container") || aItem.querySelector(".tab-content");
|
||||
aItem.querySelector(".tab-group-label-container") ||
|
||||
aItem.querySelector(".tab-content");
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
itemLabel,
|
||||
@@ -918,7 +1032,7 @@ window.gZenVerticalTabsManager = {
|
||||
}
|
||||
)
|
||||
.then(() => {})
|
||||
.catch((err) => {
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -971,7 +1085,7 @@ window.gZenVerticalTabsManager = {
|
||||
},
|
||||
|
||||
async _preCustomize() {
|
||||
await this._multiWindowFeature.foreachWindowAsActive(async (browser) => {
|
||||
await this._multiWindowFeature.foreachWindowAsActive(async browser => {
|
||||
browser.gZenVerticalTabsManager._updateEvent({
|
||||
forCustomizableMode: true,
|
||||
dontRebuildAreas: true,
|
||||
@@ -984,7 +1098,7 @@ window.gZenVerticalTabsManager = {
|
||||
|
||||
_postCustomize() {
|
||||
// No need to use `await` here, because the customization is already done
|
||||
this._multiWindowFeature.foreachWindowAsActive(async (browser) => {
|
||||
this._multiWindowFeature.foreachWindowAsActive(async browser => {
|
||||
browser.gZenVerticalTabsManager._updateEvent({ dontRebuildAreas: true });
|
||||
});
|
||||
},
|
||||
@@ -1028,7 +1142,7 @@ window.gZenVerticalTabsManager = {
|
||||
},
|
||||
|
||||
_initWaitPromise() {
|
||||
this._waitPromise = new Promise((resolve) => {
|
||||
this._waitPromise = new Promise(resolve => {
|
||||
this._resolveWaitPromise = resolve;
|
||||
});
|
||||
},
|
||||
@@ -1037,8 +1151,12 @@ window.gZenVerticalTabsManager = {
|
||||
this._resolveWaitPromise();
|
||||
|
||||
// only run if we are in the active window
|
||||
await this._multiWindowFeature.foreachWindowAsActive(async (browser) => {
|
||||
if (browser.gZenVerticalTabsManager._multiWindowFeature.windowIsActive(browser)) {
|
||||
await this._multiWindowFeature.foreachWindowAsActive(async browser => {
|
||||
if (
|
||||
browser.gZenVerticalTabsManager._multiWindowFeature.windowIsActive(
|
||||
browser
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
await browser.gZenVerticalTabsManager._waitPromise;
|
||||
@@ -1052,7 +1170,7 @@ window.gZenVerticalTabsManager = {
|
||||
}
|
||||
},
|
||||
|
||||
recalculateURLBarHeight() {
|
||||
recalculateURLBarHeight(updateFormat = false) {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
gURLBar.removeAttribute("--urlbar-height");
|
||||
@@ -1065,7 +1183,9 @@ window.gZenVerticalTabsManager = {
|
||||
if (typeof height !== "undefined") {
|
||||
gURLBar.style.setProperty("--urlbar-height", `${height}px`);
|
||||
}
|
||||
gURLBar.zenFormatURLValue();
|
||||
if (updateFormat) {
|
||||
gURLBar.zenFormatURLValue();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -1087,17 +1207,22 @@ window.gZenVerticalTabsManager = {
|
||||
}
|
||||
|
||||
const topButtons = document.getElementById("zen-sidebar-top-buttons");
|
||||
const isCompactMode = gZenCompactModeManager.preference && !forCustomizableMode;
|
||||
const isCompactMode =
|
||||
gZenCompactModeManager.preference && !forCustomizableMode;
|
||||
const isVerticalTabs = this._prefsVerticalTabs || forCustomizableMode;
|
||||
const isSidebarExpanded = this._prefsSidebarExpanded || !isVerticalTabs;
|
||||
const isRightSide = this._prefsRightSide && isVerticalTabs;
|
||||
const isSingleToolbar =
|
||||
((this._prefsUseSingleToolbar && isVerticalTabs && isSidebarExpanded) || !isVerticalTabs) &&
|
||||
((this._prefsUseSingleToolbar && isVerticalTabs && isSidebarExpanded) ||
|
||||
!isVerticalTabs) &&
|
||||
!forCustomizableMode &&
|
||||
!this.hidesTabsToolbar;
|
||||
const titlebar = document.getElementById("titlebar");
|
||||
|
||||
gBrowser.tabContainer.setAttribute("orient", isVerticalTabs ? "vertical" : "horizontal");
|
||||
gBrowser.tabContainer.setAttribute(
|
||||
"orient",
|
||||
isVerticalTabs ? "vertical" : "horizontal"
|
||||
);
|
||||
gBrowser.tabContainer.arrowScrollbox.setAttribute(
|
||||
"orient",
|
||||
isVerticalTabs ? "vertical" : "horizontal"
|
||||
@@ -1108,7 +1233,9 @@ window.gZenVerticalTabsManager = {
|
||||
isVerticalTabs ? "vertical" : "horizontal"
|
||||
);
|
||||
|
||||
const buttonsTarget = document.getElementById("zen-sidebar-top-buttons-customization-target");
|
||||
const buttonsTarget = document.getElementById(
|
||||
"zen-sidebar-top-buttons-customization-target"
|
||||
);
|
||||
if (isRightSide) {
|
||||
this.navigatorToolbox.setAttribute("zen-right-side", "true");
|
||||
document.documentElement.setAttribute("zen-right-side", "true");
|
||||
@@ -1119,7 +1246,9 @@ window.gZenVerticalTabsManager = {
|
||||
|
||||
delete this._hadSidebarCollapse;
|
||||
if (isSidebarExpanded) {
|
||||
this._hadSidebarCollapse = !document.documentElement.hasAttribute("zen-sidebar-expanded");
|
||||
this._hadSidebarCollapse = !document.documentElement.hasAttribute(
|
||||
"zen-sidebar-expanded"
|
||||
);
|
||||
this.navigatorToolbox.setAttribute("zen-sidebar-expanded", "true");
|
||||
document.documentElement.setAttribute("zen-sidebar-expanded", "true");
|
||||
gBrowser.tabContainer.setAttribute("expanded", "true");
|
||||
@@ -1129,8 +1258,12 @@ window.gZenVerticalTabsManager = {
|
||||
gBrowser.tabContainer.removeAttribute("expanded");
|
||||
}
|
||||
|
||||
const appContentNavbarContaienr = document.getElementById("zen-appcontent-navbar-container");
|
||||
const appContentNavbarWrapper = document.getElementById("zen-appcontent-navbar-wrapper");
|
||||
const appContentNavbarContaienr = document.getElementById(
|
||||
"zen-appcontent-navbar-container"
|
||||
);
|
||||
const appContentNavbarWrapper = document.getElementById(
|
||||
"zen-appcontent-navbar-wrapper"
|
||||
);
|
||||
appContentNavbarWrapper.style.transition = "none";
|
||||
let shouldHide = false;
|
||||
if (
|
||||
@@ -1146,12 +1279,16 @@ window.gZenVerticalTabsManager = {
|
||||
}
|
||||
|
||||
// Check if the sidebar is in hover mode
|
||||
if (!this.navigatorToolbox.hasAttribute("zen-right-side") && !isCompactMode) {
|
||||
if (
|
||||
!this.navigatorToolbox.hasAttribute("zen-right-side") &&
|
||||
!isCompactMode
|
||||
) {
|
||||
this.navigatorToolbox.prepend(topButtons);
|
||||
}
|
||||
|
||||
let windowButtons = this.actualWindowButtons;
|
||||
let doNotChangeWindowButtons = !isCompactMode && isRightSide && this.isWindowsStyledButtons;
|
||||
let doNotChangeWindowButtons =
|
||||
!isCompactMode && isRightSide && this.isWindowsStyledButtons;
|
||||
const navBar = document.getElementById("nav-bar");
|
||||
|
||||
if (isSingleToolbar) {
|
||||
@@ -1167,20 +1304,24 @@ window.gZenVerticalTabsManager = {
|
||||
for (const button of elements) {
|
||||
this._topButtonsSeparatorElement.after(button);
|
||||
}
|
||||
buttonsTarget.prepend(document.getElementById("unified-extensions-button"));
|
||||
buttonsTarget.prepend(
|
||||
document.getElementById("unified-extensions-button")
|
||||
);
|
||||
const panelUIButton = document.getElementById("PanelUI-button");
|
||||
buttonsTarget.prepend(panelUIButton);
|
||||
panelUIButton.setAttribute("overflows", "false");
|
||||
buttonsTarget.parentElement.append(document.getElementById("nav-bar-overflow-button"));
|
||||
buttonsTarget.parentElement.append(
|
||||
document.getElementById("nav-bar-overflow-button")
|
||||
);
|
||||
if (this.isWindowsStyledButtons && !doNotChangeWindowButtons) {
|
||||
appContentNavbarContaienr.append(windowButtons);
|
||||
}
|
||||
if (isCompactMode) {
|
||||
titlebar.prepend(navBar);
|
||||
titlebar.prepend(topButtons);
|
||||
titlebar.moveBefore(navBar, titlebar.firstChild);
|
||||
titlebar.moveBefore(topButtons, titlebar.firstChild);
|
||||
} else {
|
||||
titlebar.before(topButtons);
|
||||
titlebar.before(navBar);
|
||||
titlebar.parentNode.moveBefore(topButtons, titlebar);
|
||||
titlebar.parentNode.moveBefore(navBar, titlebar);
|
||||
}
|
||||
document.documentElement.setAttribute("zen-single-toolbar", true);
|
||||
this._hasSetSingleToolbar = true;
|
||||
@@ -1192,7 +1333,9 @@ window.gZenVerticalTabsManager = {
|
||||
'#zen-sidebar-top-buttons-customization-target > :is([cui-areatype="toolbar"], .chromeclass-toolbar-additional)'
|
||||
);
|
||||
for (const button of elements) {
|
||||
document.getElementById("nav-bar-customization-target").append(button);
|
||||
document
|
||||
.getElementById("nav-bar-customization-target")
|
||||
.append(button);
|
||||
}
|
||||
this._topButtonsSeparatorElement.remove();
|
||||
document.documentElement.removeAttribute("zen-single-toolbar");
|
||||
@@ -1225,7 +1368,9 @@ window.gZenVerticalTabsManager = {
|
||||
topButtons.prepend(windowButtons);
|
||||
}
|
||||
|
||||
const canHideTabBarPref = Services.prefs.getBoolPref("zen.view.compact.hide-tabbar");
|
||||
const canHideTabBarPref = Services.prefs.getBoolPref(
|
||||
"zen.view.compact.hide-tabbar"
|
||||
);
|
||||
const captionsShouldStayOnSidebar =
|
||||
!canHideTabBarPref &&
|
||||
((!this.isWindowsStyledButtons && !isRightSide) ||
|
||||
@@ -1238,7 +1383,12 @@ window.gZenVerticalTabsManager = {
|
||||
}
|
||||
|
||||
// Case: single toolbar, compact mode, right side and windows styled buttons
|
||||
if (isSingleToolbar && isCompactMode && isRightSide && this.isWindowsStyledButtons) {
|
||||
if (
|
||||
isSingleToolbar &&
|
||||
isCompactMode &&
|
||||
isRightSide &&
|
||||
this.isWindowsStyledButtons
|
||||
) {
|
||||
topButtons.prepend(windowButtons);
|
||||
}
|
||||
|
||||
@@ -1284,9 +1434,15 @@ window.gZenVerticalTabsManager = {
|
||||
this._hasSetSingleToolbar &&
|
||||
Services.prefs.getBoolPref("zen.view.overflow-webext-toolbar", true)
|
||||
) {
|
||||
topButtons.setAttribute("addon-webext-overflowtarget", "zen-overflow-extensions-list");
|
||||
topButtons.setAttribute(
|
||||
"addon-webext-overflowtarget",
|
||||
"zen-overflow-extensions-list"
|
||||
);
|
||||
} else {
|
||||
topButtons.setAttribute("addon-webext-overflowtarget", "overflowed-extensions-list");
|
||||
topButtons.setAttribute(
|
||||
"addon-webext-overflowtarget",
|
||||
"overflowed-extensions-list"
|
||||
);
|
||||
}
|
||||
|
||||
gZenCompactModeManager.updateCompactModeContext(isSingleToolbar);
|
||||
@@ -1319,11 +1475,15 @@ window.gZenVerticalTabsManager = {
|
||||
},
|
||||
|
||||
rebuildAreas() {
|
||||
CustomizableUI.zenInternalCU._rebuildRegisteredAreas(/* zenDontRebuildCollapsed */ true);
|
||||
CustomizableUI.zenInternalCU._rebuildRegisteredAreas(
|
||||
/* zenDontRebuildCollapsed */ true
|
||||
);
|
||||
},
|
||||
|
||||
_updateMaxWidth() {
|
||||
const maxWidth = Services.prefs.getIntPref("zen.view.sidebar-expanded.max-width");
|
||||
const maxWidth = Services.prefs.getIntPref(
|
||||
"zen.view.sidebar-expanded.max-width"
|
||||
);
|
||||
const toolbox = gNavToolbox;
|
||||
if (!this._prefsCompactMode) {
|
||||
toolbox.style.maxWidth = `${maxWidth}px`;
|
||||
@@ -1396,7 +1556,9 @@ window.gZenVerticalTabsManager = {
|
||||
);
|
||||
}
|
||||
|
||||
const editorContainer = this._tabEdited.querySelector(".tab-editor-container");
|
||||
const editorContainer = this._tabEdited.querySelector(
|
||||
".tab-editor-container"
|
||||
);
|
||||
if (editorContainer) {
|
||||
editorContainer.remove();
|
||||
}
|
||||
@@ -1424,21 +1586,30 @@ window.gZenVerticalTabsManager = {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (isTab && !target.closest(".tab-label-container") && event.type === "dblclick") {
|
||||
if (
|
||||
isTab &&
|
||||
!target.closest(".tab-label-container") &&
|
||||
event.type === "dblclick"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this._tabEdited =
|
||||
target.closest(".tabbrowser-tab") ||
|
||||
target.closest(".zen-current-workspace-indicator-name") ||
|
||||
(event.explicit && target.closest(".tab-group-label"));
|
||||
if (!this._tabEdited || (this._tabEdited.hasAttribute("zen-essential") && isTab)) {
|
||||
if (
|
||||
!this._tabEdited ||
|
||||
(this._tabEdited.hasAttribute("zen-essential") && isTab)
|
||||
) {
|
||||
this._tabEdited = null;
|
||||
return;
|
||||
}
|
||||
gZenFolders.cancelPopupTimer();
|
||||
event.stopPropagation?.();
|
||||
document.documentElement.setAttribute("zen-renaming-tab", "true");
|
||||
const label = isTab ? this._tabEdited.querySelector(".tab-label-container") : this._tabEdited;
|
||||
const label = isTab
|
||||
? this._tabEdited.querySelector(".tab-label-container")
|
||||
: this._tabEdited;
|
||||
label.classList.add("tab-label-container-editing");
|
||||
|
||||
if (isTab) {
|
||||
@@ -1455,7 +1626,9 @@ window.gZenVerticalTabsManager = {
|
||||
input.addEventListener("keydown", this.renameTabKeydown.bind(this));
|
||||
|
||||
if (isTab) {
|
||||
const containerHtml = this._tabEdited.querySelector(".tab-editor-container");
|
||||
const containerHtml = this._tabEdited.querySelector(
|
||||
".tab-editor-container"
|
||||
);
|
||||
containerHtml.appendChild(input);
|
||||
} else {
|
||||
this._tabEdited.after(input);
|
||||
@@ -1471,7 +1644,9 @@ window.gZenVerticalTabsManager = {
|
||||
return;
|
||||
}
|
||||
document.documentElement.removeAttribute("zen-renaming-tab");
|
||||
const editorContainer = this._tabEdited.querySelector(".tab-editor-container");
|
||||
const editorContainer = this._tabEdited.querySelector(
|
||||
".tab-editor-container"
|
||||
);
|
||||
let input = document.getElementById("tab-label-input");
|
||||
input.remove();
|
||||
if (editorContainer) {
|
||||
|
||||
@@ -17,12 +17,17 @@ export default function checkForZenUpdates() {
|
||||
!gZenUIManager.testingEnabled &&
|
||||
Services.prefs.getBoolPref(ZEN_UPDATE_SHOW, true)
|
||||
) {
|
||||
const updateUrl = Services.prefs.getStringPref("app.releaseNotesURL.prompt", "");
|
||||
const updateUrl = Services.prefs.getStringPref(
|
||||
"app.releaseNotesURL.prompt",
|
||||
""
|
||||
);
|
||||
createSidebarNotification({
|
||||
headingL10nId: "zen-sidebar-notification-updated-heading",
|
||||
links: [
|
||||
{
|
||||
url: Services.urlFormatter.formatURL(updateUrl.replace("%VERSION%", version)),
|
||||
url: Services.urlFormatter.formatURL(
|
||||
updateUrl.replace("%VERSION%", version)
|
||||
),
|
||||
l10nId: "zen-sidebar-notification-updated",
|
||||
special: true,
|
||||
icon: "chrome://browser/skin/zen-icons/heart-circle-fill.svg",
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media not -moz-pref("layout.css.prefers-color-scheme.content-override", 2) {
|
||||
& browser[type="content"] {
|
||||
color-scheme: env(-moz-content-preferred-color-scheme);
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.theme.acrylic-elements") {
|
||||
& browser[type="content"] {
|
||||
/* For the rendering engine to apply layering optimizations. This
|
||||
@@ -37,6 +39,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media (not -moz-pref("zen.view.shift-down-site-on-hover")) and (not ((-moz-pref("zen.view.experimental-no-window-controls") or (not -moz-pref("zen.view.hide-window-controls"))) and -moz-pref("zen.view.use-single-toolbar"))) {
|
||||
.browserSidebarContainer:is(.deck-selected, [zen-split="true"]) .browserContainer {
|
||||
transition: margin var(--zen-hidden-toolbar-transition);
|
||||
|
||||
@@ -142,9 +142,10 @@
|
||||
|
||||
#zen-main-app-wrapper {
|
||||
background: var(--zen-themed-toolbar-bg-transparent);
|
||||
/* See bug #8814, don't an overflow here as it causes issues
|
||||
/* See bug #8814, don't add overflow here as it causes issues
|
||||
* with firefox's rendering of the tab bar */
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media (-moz-pref("zen.view.grey-out-inactive-windows")) {
|
||||
&:-moz-window-inactive {
|
||||
background: InactiveCaption;
|
||||
@@ -155,6 +156,7 @@
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media (-moz-windows-accent-color-in-titlebar) and ((-moz-windows-mica) or -moz-pref("browser.theme.windows.accent-color-in-tabs.enabled")) {
|
||||
background: ActiveCaption;
|
||||
color: CaptionText;
|
||||
@@ -207,6 +209,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.widget.mac.mono-window-controls") {
|
||||
:root:not([window-modal-open="true"]) .titlebar-buttonbox-container {
|
||||
color: var(--toolbox-textcolor);
|
||||
@@ -220,7 +223,7 @@
|
||||
/* Draw 3 dots as background to represent the window controls,
|
||||
all with the same cololr as the titlebar */
|
||||
background-image: radial-gradient(circle, var(--zen-toolbar-element-bg) var(--zen-traffic-light-size), transparent 0.5px);
|
||||
background-size: 20px 22px;
|
||||
background-size: var(--icon-size-medium) 22px;
|
||||
background-position: 53% 50%;
|
||||
|
||||
@media (-moz-mac-tahoe-theme) {
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
}
|
||||
|
||||
#urlbar .urlbar-input {
|
||||
border-radius: 0px !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
#urlbar .urlbar-input-box {
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
& #identity-box {
|
||||
order: 999;
|
||||
margin: 0px !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,12 +189,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.urlbar.single-toolbar-show-copy-url", false) {
|
||||
:root[zen-single-toolbar="true"] #zen-copy-url-button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media not -moz-pref("zen.urlbar.show-pip-button") {
|
||||
#picture-in-picture-button {
|
||||
display: none !important;
|
||||
@@ -259,14 +261,17 @@
|
||||
|
||||
& .urlbar-background {
|
||||
--zen-urlbar-background-base: light-dark(#fbfbfb, color-mix(in srgb, hsl(0, 0%, 6.7%), var(--zen-colors-primary) 30%));
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.theme.acrylic-elements") {
|
||||
--zen-urlbar-background-transparent: color-mix(in srgb, var(--zen-urlbar-background-base) 70%, transparent 30%);
|
||||
}
|
||||
background-color: var(--zen-urlbar-background-transparent, var(--zen-urlbar-background-base)) !important;
|
||||
box-shadow: 0px 30px 140px -15px light-dark(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.6)) !important;
|
||||
box-shadow: 0 30px 140px -15px light-dark(rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.6)) !important;
|
||||
backdrop-filter: none !important;
|
||||
outline: 0.5px solid light-dark(rgba(0, 0, 0, 0.2), rgba(255, 255, 255, 0.2)) !important;
|
||||
outline-offset: var(--zen-urlbar-outline-offset) !important;
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.theme.acrylic-elements") {
|
||||
backdrop-filter: blur(42px) saturate(110%) brightness(0.25) contrast(100%) !important;
|
||||
}
|
||||
@@ -324,8 +329,8 @@
|
||||
& > image {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
height: 24px; /* double 12px */
|
||||
width: 24px;
|
||||
height: var(--size-item-medium); /* double 12px */
|
||||
width: var(--size-item-medium);
|
||||
padding: 4px !important;
|
||||
|
||||
&:hover {
|
||||
@@ -502,13 +507,14 @@
|
||||
height: var(--urlbar-height) !important;
|
||||
margin-inline: 0.15rem !important;
|
||||
:root:not([zen-single-toolbar="true"]) & {
|
||||
max-height: 32px !important;
|
||||
max-height: var(--size-item-large) !important;
|
||||
min-height: unset !important;
|
||||
margin-block: -1px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media not -moz-pref("zen.urlbar.show-protections-icon") {
|
||||
#tracking-protection-icon-container {
|
||||
display: none !important;
|
||||
@@ -573,8 +579,8 @@
|
||||
& img {
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
}
|
||||
|
||||
&[hidden] {
|
||||
@@ -702,7 +708,7 @@
|
||||
}
|
||||
|
||||
#identity-box {
|
||||
margin-inline-end: 0px;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,7 +720,7 @@
|
||||
|
||||
#urlbar-search-mode-indicator-title {
|
||||
font-weight: 600;
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* These are buttons that we dont need to be
|
||||
@@ -727,6 +733,7 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media not -moz-pref("zen.urlbar.show-contextual-id") {
|
||||
#userContext-icons {
|
||||
display: none !important;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px 2px;
|
||||
padding-bottom: 0px;
|
||||
padding-bottom: 0;
|
||||
|
||||
& .unified-extensions-item {
|
||||
flex: 1;
|
||||
|
||||
@@ -22,7 +22,7 @@ panel[type="arrow"]:not(#feature-callout) {
|
||||
transition-duration: 0s !important;
|
||||
|
||||
&::part(content) {
|
||||
/* Refrain from animating for now as we haven't found a
|
||||
/* Refrain from animating for now as we haven't found a
|
||||
* way to properly animate the popup without having the mica
|
||||
* backdrop staying still while the popup animates */
|
||||
animation: none !important;
|
||||
@@ -30,7 +30,7 @@ panel[type="arrow"]:not(#feature-callout) {
|
||||
}
|
||||
|
||||
@media (-moz-platform: macos) {
|
||||
&:where([followanchor="false"], [nonnativepopover="true"]) {
|
||||
&:where([nonnativepopover="true"], :not([type="arrow"])) {
|
||||
appearance: auto !important;
|
||||
-moz-default-appearance: menupopup;
|
||||
/* We set the default background here, rather than on ::part(content),
|
||||
@@ -45,7 +45,7 @@ panel[type="arrow"]:not(#feature-callout) {
|
||||
|
||||
/* Remove the shadow for the native panels, as macos already
|
||||
* adds the shadows to the window. This is specially important
|
||||
* on Tahoe, where we *dont* apply an image mask, meaning that
|
||||
* on Tahoe, where we *don't* apply an image mask, meaning that
|
||||
* trying to render a shadow would end up in having weird borders
|
||||
* around the panel */
|
||||
--panel-shadow: none;
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
}
|
||||
|
||||
#zenEditBookmarkPanelFavicon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: var(--icon-size-medium);
|
||||
height: var(--icon-size-medium);
|
||||
}
|
||||
|
||||
#editBookmarkPanel .panel-header {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
.dialogBox {
|
||||
border: none;
|
||||
outline: 1px solid light-dark(transparent, #646464);
|
||||
animation: zen-dialog-fade-in 0.3s ease-out;
|
||||
border-radius: 12px !important;
|
||||
|
||||
@@ -92,8 +92,8 @@ panel {
|
||||
#appMenu-fxa-label2::before {
|
||||
content: "";
|
||||
display: -moz-box;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
height: var(--size-item-small);
|
||||
width: var(--size-item-small);
|
||||
background: var(--avatar-image-url) 0/16px;
|
||||
scale: 1.25;
|
||||
border-radius: 99px;
|
||||
@@ -139,7 +139,7 @@ panel {
|
||||
border-inline-start: 1px solid var(--panel-separator-color);
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 32px;
|
||||
height: var(--size-item-large);
|
||||
margin-block: calc(var(--uc-panel-zoom-button-padding) * -1);
|
||||
transform: translateX(
|
||||
calc(var(--uc-panel-zoom-button-inline-padding) * -1 - (var(--panel-separator-margin-vertical) + var(--uc-arrowpanel-menuitem-margin-block)) - 1px)
|
||||
@@ -147,8 +147,8 @@ panel {
|
||||
}
|
||||
|
||||
#appMenu-zoomReset-button2 {
|
||||
height: calc(16px + var(--uc-panel-zoom-button-padding) * 2);
|
||||
min-height: calc(16px + var(--uc-panel-zoom-button-padding) * 2);
|
||||
height: calc(var(--size-item-small) + var(--uc-panel-zoom-button-padding) * 2);
|
||||
min-height: calc(var(--size-item-small) + var(--uc-panel-zoom-button-padding) * 2);
|
||||
}
|
||||
|
||||
#appMenu-zoomReduce-button2:not([disabled], [open], :active):is(:hover),
|
||||
@@ -191,7 +191,7 @@ panel {
|
||||
#identity-popup-mainView-panel-header,
|
||||
#protections-popup-mainView-panel-header,
|
||||
.panel-header {
|
||||
min-height: calc((var(--arrowpanel-menuitem-padding-block) + 4px) * 2 + 16px);
|
||||
min-height: calc((var(--arrowpanel-menuitem-padding-block) + 4px) * 2 + var(--size-item-small));
|
||||
}
|
||||
|
||||
/* URL bar popup */
|
||||
@@ -223,7 +223,7 @@ panel {
|
||||
.permission-popup-permission-item,
|
||||
#permission-popup-storage-access-permission-list-header {
|
||||
padding-block: 4px;
|
||||
margin-block: 0px;
|
||||
margin-block: 0;
|
||||
}
|
||||
|
||||
#editBookmarkPanel > #editBookmarkHeaderSeparator,
|
||||
@@ -353,7 +353,7 @@ menuseparator {
|
||||
padding: var(--zen-toast-padding);
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(to bottom, var(--zen-primary-color) -40%, color-mix(in srgb, var(--zen-primary-color), #0f0f0f 20%));
|
||||
box-shadow: light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4)) 0px 0px 22px 2px;
|
||||
box-shadow: light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4)) 0 0 22px 2px;
|
||||
border: none;
|
||||
display: flex;
|
||||
font-weight: 600;
|
||||
@@ -386,10 +386,10 @@ menuseparator {
|
||||
|
||||
& button {
|
||||
width: min-content;
|
||||
padding: 0px 8px !important;
|
||||
padding: 0 8px !important;
|
||||
min-width: unset !important;
|
||||
min-height: 28px;
|
||||
margin: 0px !important;
|
||||
margin: 0 !important;
|
||||
border-radius: 6px !important;
|
||||
border-top: 2px solid light-dark(transparent, rgba(255, 255, 255, 0.1));
|
||||
color: light-dark(rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0.8)) !important;
|
||||
|
||||
@@ -107,8 +107,8 @@
|
||||
|
||||
& .zen-sidebar-notification-link-icon {
|
||||
pointer-events: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: var(--special-color, currentColor);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.theme.disable-lightweight") {
|
||||
#customization-lwtheme-link {
|
||||
display: none !important;
|
||||
@@ -60,7 +61,7 @@
|
||||
#PanelUI-zen-emojis-picker-header {
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
padding: 0px 10px;
|
||||
padding: 0 10px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
@@ -147,7 +148,7 @@
|
||||
|
||||
.zen-emojis-picker-emoji {
|
||||
font-size: 14px;
|
||||
padding: 0px !important;
|
||||
padding: 0 !important;
|
||||
& image {
|
||||
display: none;
|
||||
}
|
||||
@@ -262,6 +263,7 @@
|
||||
|
||||
/* Status panel */
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media (-moz-pref("zen.theme.styled-status-panel")) {
|
||||
#statuspanel {
|
||||
padding: 6px;
|
||||
@@ -334,8 +336,8 @@
|
||||
|
||||
& > * {
|
||||
background-color: color-mix(in srgb, currentcolor 6%, transparent);
|
||||
width: 48px;
|
||||
height: 32px;
|
||||
width: var(--size-item-xlarge);
|
||||
height: var(--size-item-large);
|
||||
margin: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -377,6 +379,7 @@
|
||||
|
||||
.zen-site-data-section-header {
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
|
||||
& label {
|
||||
margin: 0;
|
||||
@@ -415,7 +418,7 @@
|
||||
}
|
||||
|
||||
.permission-popup-permission-label {
|
||||
margin: 0px;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@@ -446,8 +449,8 @@
|
||||
position: absolute;
|
||||
inset: 1px;
|
||||
border-radius: 99px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: var(--size-item-large);
|
||||
height: var(--size-item-large);
|
||||
background: var(--button-background-color-primary);
|
||||
opacity: 0.6;
|
||||
transition:
|
||||
@@ -490,12 +493,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media -moz-pref("zen.theme.hide-unified-extensions-button") {
|
||||
#unified-extensions-button:not([showing]) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line media-query-no-invalid */
|
||||
@media not -moz-pref("zen.theme.hide-unified-extensions-button") {
|
||||
#zen-site-data-section-addons {
|
||||
display: none;
|
||||
@@ -518,8 +523,8 @@
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
color: light-dark(rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0.8));
|
||||
width: 48px;
|
||||
height: 32px;
|
||||
width: var(--size-item-xlarge);
|
||||
height: var(--size-item-large);
|
||||
position: relative;
|
||||
|
||||
&[disabled] {
|
||||
@@ -546,11 +551,11 @@
|
||||
background: linear-gradient(to bottom, light-dark(rgb(255, 255, 255), rgb(34, 34, 34)), light-dark(rgb(246, 246, 246), rgb(21, 21, 21)));
|
||||
|
||||
box-shadow:
|
||||
0px 2px 4px rgba(0, 0, 0, 0.1),
|
||||
inset 0px 1px 0px light-dark(transparent, rgba(255, 255, 255, 0.15));
|
||||
0 1px 2px rgba(0, 0, 0, 0.1),
|
||||
inset 0 1px 0 light-dark(transparent, rgba(255, 255, 255, 0.15));
|
||||
border-radius: 6px;
|
||||
--base-border-color: light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.1));
|
||||
border: 1px solid light-dark(var(--base-border-color), rgb(21, 21, 21));
|
||||
border: 0.5px solid light-dark(var(--base-border-color), rgb(21, 21, 21));
|
||||
}
|
||||
|
||||
@media not (-moz-platform: macos) {
|
||||
|
||||
@@ -8,7 +8,11 @@ export const ZenCustomizableUI = new (class {
|
||||
constructor() {}
|
||||
|
||||
TYPE_TOOLBAR = "toolbar";
|
||||
defaultSidebarIcons = ["downloads-button", "zen-workspaces-button", "zen-create-new-button"];
|
||||
defaultSidebarIcons = [
|
||||
"downloads-button",
|
||||
"zen-workspaces-button",
|
||||
"zen-create-new-button",
|
||||
];
|
||||
|
||||
startup(CustomizableUIInternal) {
|
||||
CustomizableUIInternal.registerArea(
|
||||
@@ -39,7 +43,8 @@ export const ZenCustomizableUI = new (class {
|
||||
}
|
||||
|
||||
#addSidebarButtons(window) {
|
||||
const kDefaultSidebarWidth = AppConstants.platform === "macosx" ? "230px" : "186px";
|
||||
const kDefaultSidebarWidth =
|
||||
AppConstants.platform === "macosx" ? "230px" : "186px";
|
||||
const toolbox = window.gNavToolbox;
|
||||
|
||||
// Set a splitter to navigator-toolbox
|
||||
@@ -81,7 +86,7 @@ export const ZenCustomizableUI = new (class {
|
||||
</toolbar>
|
||||
`);
|
||||
toolbox.prepend(sidebarBox);
|
||||
new window.MutationObserver((e) => {
|
||||
new window.MutationObserver(e => {
|
||||
if (e[0].type !== "attributes" || e[0].attributeName !== "width") {
|
||||
return;
|
||||
}
|
||||
@@ -96,7 +101,7 @@ export const ZenCustomizableUI = new (class {
|
||||
toolbox.style.width = width;
|
||||
toolbox.setAttribute("width", width);
|
||||
|
||||
splitter.addEventListener("dblclick", (e) => {
|
||||
splitter.addEventListener("dblclick", e => {
|
||||
if (e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
@@ -104,7 +109,9 @@ export const ZenCustomizableUI = new (class {
|
||||
toolbox.setAttribute("width", kDefaultSidebarWidth);
|
||||
});
|
||||
|
||||
const newTab = window.document.getElementById("vertical-tabs-newtab-button");
|
||||
const newTab = window.document.getElementById(
|
||||
"vertical-tabs-newtab-button"
|
||||
);
|
||||
newTab.classList.add("zen-sidebar-action-button");
|
||||
|
||||
for (let id of this.defaultSidebarIcons) {
|
||||
@@ -124,7 +131,7 @@ export const ZenCustomizableUI = new (class {
|
||||
// If we use "mousedown" event for private windows (which open a new tab on "click"), we might end up with
|
||||
// the urlbar flicking and therefore we use "command" event to avoid that.
|
||||
let isPrivateMode = window.gZenWorkspaces.privateWindowOrDisabled;
|
||||
button.addEventListener(isPrivateMode ? "command" : "mousedown", (event) => {
|
||||
button.addEventListener(isPrivateMode ? "command" : "mousedown", event => {
|
||||
if (isPrivateMode) {
|
||||
window.document.getElementById("cmd_newNavigatorTab").doCommand();
|
||||
return;
|
||||
@@ -146,7 +153,9 @@ export const ZenCustomizableUI = new (class {
|
||||
}
|
||||
|
||||
#moveWindowButtons(window) {
|
||||
const windowControls = window.document.getElementsByClassName("titlebar-buttonbox-container");
|
||||
const windowControls = window.document.getElementsByClassName(
|
||||
"titlebar-buttonbox-container"
|
||||
);
|
||||
const toolboxIcons = window.document.getElementById(
|
||||
"zen-sidebar-top-buttons-customization-target"
|
||||
);
|
||||
@@ -173,7 +182,9 @@ export const ZenCustomizableUI = new (class {
|
||||
wrapper.prepend(elem);
|
||||
}
|
||||
}
|
||||
window.document.getElementById("stop-reload-button").removeAttribute("overflows");
|
||||
window.document
|
||||
.getElementById("stop-reload-button")
|
||||
.removeAttribute("overflows");
|
||||
}
|
||||
|
||||
_dispatchResizeEvent(window) {
|
||||
|
||||
@@ -24,7 +24,9 @@ class nsZenUIMigration {
|
||||
}
|
||||
this.clearVariables();
|
||||
if (this.shouldRestart) {
|
||||
Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
|
||||
Services.startup.quit(
|
||||
Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,13 +63,24 @@ class nsZenUIMigration {
|
||||
userContentFile.append("userContent.css");
|
||||
Services.prefs.setBoolPref(
|
||||
"zen.workspaces.separate-essentials",
|
||||
Services.prefs.getBoolPref("zen.workspaces.container-specific-essentials-enabled", false)
|
||||
Services.prefs.getBoolPref(
|
||||
"zen.workspaces.container-specific-essentials-enabled",
|
||||
false
|
||||
)
|
||||
);
|
||||
const theme = Services.prefs.getIntPref(
|
||||
"layout.css.prefers-color-scheme.content-override",
|
||||
0
|
||||
);
|
||||
const theme = Services.prefs.getIntPref("layout.css.prefers-color-scheme.content-override", 0);
|
||||
Services.prefs.setIntPref("zen.view.window.scheme", theme);
|
||||
if (userChromeFile.exists() || userContentFile.exists()) {
|
||||
Services.prefs.setBoolPref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
|
||||
console.warn("ZenUIMigration: User stylesheets detected, enabling legacy stylesheets.");
|
||||
Services.prefs.setBoolPref(
|
||||
"toolkit.legacyUserProfileCustomizations.stylesheets",
|
||||
true
|
||||
);
|
||||
console.warn(
|
||||
"ZenUIMigration: User stylesheets detected, enabling legacy stylesheets."
|
||||
);
|
||||
this.shouldRestart = true;
|
||||
}
|
||||
}
|
||||
@@ -79,7 +92,11 @@ class nsZenUIMigration {
|
||||
}
|
||||
|
||||
_migrateV3() {
|
||||
if (Services.prefs.getStringPref("zen.theme.accent-color", "").startsWith("system")) {
|
||||
if (
|
||||
Services.prefs
|
||||
.getStringPref("zen.theme.accent-color", "")
|
||||
.startsWith("system")
|
||||
) {
|
||||
Services.prefs.setStringPref("zen.theme.accent-color", "AccentColor");
|
||||
}
|
||||
}
|
||||
@@ -100,20 +117,23 @@ class nsZenUIMigration {
|
||||
lazy.SessionStore.promiseAllWindowsRestored.then(() => {
|
||||
const win = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
win.setTimeout(async () => {
|
||||
const [title, message, learnMore, accept] = await win.document.l10n.formatMessages([
|
||||
"zen-window-sync-migration-dialog-title",
|
||||
"zen-window-sync-migration-dialog-message",
|
||||
"zen-window-sync-migration-dialog-learn-more",
|
||||
"zen-window-sync-migration-dialog-accept",
|
||||
]);
|
||||
const [title, message, learnMore, accept] =
|
||||
await win.document.l10n.formatMessages([
|
||||
"zen-window-sync-migration-dialog-title",
|
||||
"zen-window-sync-migration-dialog-message",
|
||||
"zen-window-sync-migration-dialog-learn-more",
|
||||
"zen-window-sync-migration-dialog-accept",
|
||||
]);
|
||||
|
||||
// buttonPressed will be 0 for cancel, 1 for "more info"
|
||||
let buttonPressed = Services.prompt.confirmEx(
|
||||
win,
|
||||
title.value,
|
||||
message.value,
|
||||
Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
|
||||
Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_IS_STRING,
|
||||
Services.prompt.BUTTON_POS_0 *
|
||||
Services.prompt.BUTTON_TITLE_IS_STRING +
|
||||
Services.prompt.BUTTON_POS_1 *
|
||||
Services.prompt.BUTTON_TITLE_IS_STRING,
|
||||
learnMore.value,
|
||||
accept.value,
|
||||
null,
|
||||
@@ -122,7 +142,10 @@ class nsZenUIMigration {
|
||||
);
|
||||
// User has clicked on "Learn More"
|
||||
if (buttonPressed === 0) {
|
||||
win.openTrustedLinkIn("https://docs.zen-browser.app/user-manual/window-sync", "tab");
|
||||
win.openTrustedLinkIn(
|
||||
"https://docs.zen-browser.app/user-manual/window-sync",
|
||||
"tab"
|
||||
);
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
@@ -6,146 +6,152 @@ document.addEventListener(
|
||||
"MozBeforeInitialXULLayout",
|
||||
() => {
|
||||
// <commandset id="mainCommandSet"> defined in browser-sets.inc
|
||||
// eslint-disable-next-line complexity
|
||||
document.getElementById("zenCommandSet").addEventListener("command", (event) => {
|
||||
switch (event.target.id) {
|
||||
case "cmd_zenCompactModeToggle":
|
||||
gZenCompactModeManager.toggle();
|
||||
break;
|
||||
case "cmd_toggleCompactModeIgnoreHover":
|
||||
gZenCompactModeManager.toggle(true);
|
||||
break;
|
||||
case "cmd_zenCompactModeShowSidebar":
|
||||
gZenCompactModeManager.toggleSidebar();
|
||||
break;
|
||||
case "cmd_zenWorkspaceForward":
|
||||
gZenWorkspaces.changeWorkspaceShortcut();
|
||||
break;
|
||||
case "cmd_zenWorkspaceBackward":
|
||||
gZenWorkspaces.changeWorkspaceShortcut(-1);
|
||||
break;
|
||||
case "cmd_zenSplitViewGrid":
|
||||
gZenViewSplitter.toggleShortcut("grid");
|
||||
break;
|
||||
case "cmd_zenSplitViewVertical":
|
||||
gZenViewSplitter.toggleShortcut("vsep");
|
||||
break;
|
||||
case "cmd_zenSplitViewHorizontal":
|
||||
gZenViewSplitter.toggleShortcut("hsep");
|
||||
break;
|
||||
case "cmd_zenSplitViewUnsplit":
|
||||
gZenViewSplitter.toggleShortcut("unsplit");
|
||||
break;
|
||||
case "cmd_zenSplitViewContextMenu":
|
||||
gZenViewSplitter.contextSplitTabs();
|
||||
break;
|
||||
case "cmd_zenCopyCurrentURLMarkdown":
|
||||
gZenCommonActions.copyCurrentURLAsMarkdownToClipboard();
|
||||
break;
|
||||
case "cmd_zenCopyCurrentURL":
|
||||
gZenCommonActions.copyCurrentURLToClipboard();
|
||||
break;
|
||||
case "cmd_zenPinnedTabReset":
|
||||
gZenPinnedTabManager.resetPinnedTab(gBrowser.selectedTab);
|
||||
break;
|
||||
case "cmd_zenPinnedTabResetNoTab":
|
||||
gZenPinnedTabManager.resetPinnedTab();
|
||||
break;
|
||||
case "cmd_zenToggleSidebar":
|
||||
gZenVerticalTabsManager.toggleExpand();
|
||||
break;
|
||||
case "cmd_zenOpenZenThemePicker":
|
||||
gZenThemePicker.openThemePicker(event);
|
||||
break;
|
||||
case "cmd_zenChangeWorkspaceTab":
|
||||
gZenWorkspaces.changeTabWorkspace(
|
||||
event.sourceEvent.target.getAttribute("zen-workspace-id")
|
||||
);
|
||||
break;
|
||||
case "cmd_zenToggleTabsOnRight":
|
||||
gZenVerticalTabsManager.toggleTabsOnRight();
|
||||
break;
|
||||
case "cmd_zenSplitViewLinkInNewTab":
|
||||
gZenViewSplitter.splitLinkInNewTab();
|
||||
break;
|
||||
case "cmd_zenNewEmptySplit":
|
||||
setTimeout(() => {
|
||||
gZenViewSplitter.createEmptySplit();
|
||||
}, 0);
|
||||
break;
|
||||
case "cmd_zenReplacePinnedUrlWithCurrent":
|
||||
gZenPinnedTabManager.replacePinnedUrlWithCurrent();
|
||||
break;
|
||||
case "cmd_contextZenAddToEssentials":
|
||||
gZenPinnedTabManager.addToEssentials();
|
||||
break;
|
||||
case "cmd_contextZenRemoveFromEssentials":
|
||||
gZenPinnedTabManager.removeEssentials();
|
||||
break;
|
||||
case "cmd_zenCtxDeleteWorkspace":
|
||||
gZenWorkspaces.contextDeleteWorkspace(event);
|
||||
break;
|
||||
case "cmd_zenChangeWorkspaceName":
|
||||
gZenVerticalTabsManager.renameTabStart({
|
||||
target: gZenWorkspaces.activeWorkspaceIndicator.querySelector(
|
||||
".zen-current-workspace-indicator-name"
|
||||
),
|
||||
});
|
||||
break;
|
||||
case "cmd_zenChangeWorkspaceIcon":
|
||||
gZenWorkspaces.changeWorkspaceIcon();
|
||||
break;
|
||||
case "cmd_zenReorderWorkspaces":
|
||||
gZenUIManager.showToast("zen-workspaces-how-to-reorder-title", {
|
||||
timeout: 9000,
|
||||
descriptionId: "zen-workspaces-how-to-reorder-desc",
|
||||
});
|
||||
break;
|
||||
case "cmd_zenOpenWorkspaceCreation":
|
||||
gZenWorkspaces.openWorkspaceCreation(event);
|
||||
break;
|
||||
case "cmd_zenOpenFolderCreation":
|
||||
gZenFolders.createFolder([], {
|
||||
renameFolder: true,
|
||||
});
|
||||
break;
|
||||
case "cmd_zenTogglePinTab": {
|
||||
const currentTab = gBrowser.selectedTab;
|
||||
if (currentTab && !currentTab.hasAttribute("zen-empty-tab")) {
|
||||
if (currentTab.pinned) {
|
||||
gBrowser.unpinTab(currentTab);
|
||||
} else {
|
||||
gBrowser.pinTab(currentTab);
|
||||
document
|
||||
.getElementById("zenCommandSet")
|
||||
// eslint-disable-next-line complexity
|
||||
.addEventListener("command", event => {
|
||||
switch (event.target.id) {
|
||||
case "cmd_zenCompactModeToggle":
|
||||
gZenCompactModeManager.toggle();
|
||||
break;
|
||||
case "cmd_toggleCompactModeIgnoreHover":
|
||||
gZenCompactModeManager.toggle(true);
|
||||
break;
|
||||
case "cmd_zenCompactModeShowSidebar":
|
||||
gZenCompactModeManager.toggleSidebar();
|
||||
break;
|
||||
case "cmd_zenWorkspaceForward":
|
||||
gZenWorkspaces.changeWorkspaceShortcut();
|
||||
break;
|
||||
case "cmd_zenWorkspaceBackward":
|
||||
gZenWorkspaces.changeWorkspaceShortcut(-1);
|
||||
break;
|
||||
case "cmd_zenSplitViewGrid":
|
||||
gZenViewSplitter.toggleShortcut("grid");
|
||||
break;
|
||||
case "cmd_zenSplitViewVertical":
|
||||
gZenViewSplitter.toggleShortcut("vsep");
|
||||
break;
|
||||
case "cmd_zenSplitViewHorizontal":
|
||||
gZenViewSplitter.toggleShortcut("hsep");
|
||||
break;
|
||||
case "cmd_zenSplitViewUnsplit":
|
||||
gZenViewSplitter.toggleShortcut("unsplit");
|
||||
break;
|
||||
case "cmd_zenSplitViewContextMenu":
|
||||
gZenViewSplitter.contextSplitTabs();
|
||||
break;
|
||||
case "cmd_zenCopyCurrentURLMarkdown":
|
||||
gZenCommonActions.copyCurrentURLAsMarkdownToClipboard();
|
||||
break;
|
||||
case "cmd_zenCopyCurrentURL":
|
||||
gZenCommonActions.copyCurrentURLToClipboard();
|
||||
break;
|
||||
case "cmd_zenPinnedTabReset":
|
||||
gZenPinnedTabManager.resetPinnedTab(gBrowser.selectedTab);
|
||||
break;
|
||||
case "cmd_zenPinnedTabResetNoTab":
|
||||
gZenPinnedTabManager.resetPinnedTab();
|
||||
break;
|
||||
case "cmd_zenToggleSidebar":
|
||||
gZenVerticalTabsManager.toggleExpand();
|
||||
break;
|
||||
case "cmd_zenOpenZenThemePicker":
|
||||
gZenThemePicker.openThemePicker(event);
|
||||
break;
|
||||
case "cmd_zenChangeWorkspaceTab":
|
||||
gZenWorkspaces.changeTabWorkspace(
|
||||
event.sourceEvent.target.getAttribute("zen-workspace-id")
|
||||
);
|
||||
break;
|
||||
case "cmd_zenToggleTabsOnRight":
|
||||
gZenVerticalTabsManager.toggleTabsOnRight();
|
||||
break;
|
||||
case "cmd_zenSplitViewLinkInNewTab":
|
||||
gZenViewSplitter.splitLinkInNewTab();
|
||||
break;
|
||||
case "cmd_zenNewEmptySplit":
|
||||
setTimeout(() => {
|
||||
gZenViewSplitter.createEmptySplit();
|
||||
}, 0);
|
||||
break;
|
||||
case "cmd_zenReplacePinnedUrlWithCurrent":
|
||||
gZenPinnedTabManager.replacePinnedUrlWithCurrent();
|
||||
break;
|
||||
case "cmd_contextZenAddToEssentials":
|
||||
gZenPinnedTabManager.addToEssentials();
|
||||
break;
|
||||
case "cmd_contextZenRemoveFromEssentials":
|
||||
gZenPinnedTabManager.removeEssentials();
|
||||
break;
|
||||
case "cmd_zenCtxDeleteWorkspace":
|
||||
gZenWorkspaces.contextDeleteWorkspace(event);
|
||||
break;
|
||||
case "cmd_zenChangeWorkspaceName":
|
||||
gZenVerticalTabsManager.renameTabStart({
|
||||
target: gZenWorkspaces.activeWorkspaceIndicator.querySelector(
|
||||
".zen-current-workspace-indicator-name"
|
||||
),
|
||||
});
|
||||
break;
|
||||
case "cmd_zenChangeWorkspaceIcon":
|
||||
gZenWorkspaces.changeWorkspaceIcon();
|
||||
break;
|
||||
case "cmd_zenReorderWorkspaces":
|
||||
gZenUIManager.showToast("zen-workspaces-how-to-reorder-title", {
|
||||
timeout: 9000,
|
||||
descriptionId: "zen-workspaces-how-to-reorder-desc",
|
||||
});
|
||||
break;
|
||||
case "cmd_zenOpenWorkspaceCreation":
|
||||
gZenWorkspaces.openWorkspaceCreation(event);
|
||||
break;
|
||||
case "cmd_zenOpenFolderCreation":
|
||||
gZenFolders.createFolder([], {
|
||||
renameFolder: true,
|
||||
});
|
||||
break;
|
||||
case "cmd_zenTogglePinTab": {
|
||||
const currentTab = gBrowser.selectedTab;
|
||||
if (currentTab && !currentTab.hasAttribute("zen-empty-tab")) {
|
||||
if (currentTab.pinned) {
|
||||
gBrowser.unpinTab(currentTab);
|
||||
} else {
|
||||
gBrowser.pinTab(currentTab);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "cmd_zenCloseUnpinnedTabs":
|
||||
gZenWorkspaces.closeAllUnpinnedTabs();
|
||||
break;
|
||||
case "cmd_zenUnloadWorkspace": {
|
||||
gZenWorkspaces.unloadWorkspace();
|
||||
break;
|
||||
}
|
||||
case "cmd_zenNewNavigatorUnsynced":
|
||||
OpenBrowserWindow({ zenSyncedWindow: false });
|
||||
break;
|
||||
case "cmd_zenNewLiveFolder": {
|
||||
const { ZenLiveFoldersManager } = ChromeUtils.importESModule(
|
||||
"resource:///modules/zen/ZenLiveFoldersManager.sys.mjs"
|
||||
);
|
||||
ZenLiveFoldersManager.handleEvent(event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gZenGlanceManager.handleMainCommandSet(event);
|
||||
if (event.target.id.startsWith("cmd_zenWorkspaceSwitch")) {
|
||||
const index = parseInt(event.target.id.replace("cmd_zenWorkspaceSwitch", ""), 10) - 1;
|
||||
gZenWorkspaces.shortcutSwitchTo(index);
|
||||
case "cmd_zenCloseUnpinnedTabs":
|
||||
gZenWorkspaces.closeAllUnpinnedTabs();
|
||||
break;
|
||||
case "cmd_zenUnloadWorkspace": {
|
||||
gZenWorkspaces.unloadWorkspace();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
case "cmd_zenNewNavigatorUnsynced":
|
||||
OpenBrowserWindow({ zenSyncedWindow: false });
|
||||
break;
|
||||
case "cmd_zenNewLiveFolder": {
|
||||
const { ZenLiveFoldersManager } = ChromeUtils.importESModule(
|
||||
"resource:///modules/zen/ZenLiveFoldersManager.sys.mjs"
|
||||
);
|
||||
ZenLiveFoldersManager.handleEvent(event);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gZenGlanceManager.handleMainCommandSet(event);
|
||||
if (event.target.id.startsWith("cmd_zenWorkspaceSwitch")) {
|
||||
const index =
|
||||
parseInt(
|
||||
event.target.id.replace("cmd_zenWorkspaceSwitch", ""),
|
||||
10
|
||||
) - 1;
|
||||
gZenWorkspaces.shortcutSwitchTo(index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
* begin listening to changes in preferred color scheme.
|
||||
*/
|
||||
init() {
|
||||
this._inMainBrowserWindow = window.location.href == "chrome://browser/content/browser.xhtml";
|
||||
this._inMainBrowserWindow =
|
||||
window.location.href == "chrome://browser/content/browser.xhtml";
|
||||
this.listenForEvents();
|
||||
this.updateAllThemeBasics();
|
||||
},
|
||||
@@ -91,14 +92,23 @@
|
||||
},
|
||||
|
||||
updateBorderRadius() {
|
||||
const borderRadius = Services.prefs.getIntPref("zen.theme.border-radius", -1);
|
||||
const borderRadius = Services.prefs.getIntPref(
|
||||
"zen.theme.border-radius",
|
||||
-1
|
||||
);
|
||||
|
||||
// -1 is the default value, will use platform-native values
|
||||
// otherwise, use the custom value
|
||||
if (borderRadius == -1) {
|
||||
if (AppConstants.platform == "macosx") {
|
||||
const targetRadius = window.matchMedia("(-moz-mac-tahoe-theme)").matches ? 16 : 10;
|
||||
document.documentElement.style.setProperty("--zen-border-radius", targetRadius + "px");
|
||||
const targetRadius = window.matchMedia("(-moz-mac-tahoe-theme)")
|
||||
.matches
|
||||
? 16
|
||||
: 10;
|
||||
document.documentElement.style.setProperty(
|
||||
"--zen-border-radius",
|
||||
targetRadius + "px"
|
||||
);
|
||||
} else if (AppConstants.platform == "linux") {
|
||||
// Linux uses GTK CSD titlebar radius, default to 8px
|
||||
document.documentElement.style.setProperty(
|
||||
@@ -107,11 +117,17 @@
|
||||
);
|
||||
} else {
|
||||
// Windows defaults to 8px
|
||||
document.documentElement.style.setProperty("--zen-border-radius", "8px");
|
||||
document.documentElement.style.setProperty(
|
||||
"--zen-border-radius",
|
||||
"8px"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Use the overridden value
|
||||
document.documentElement.style.setProperty("--zen-border-radius", borderRadius + "px");
|
||||
document.documentElement.style.setProperty(
|
||||
"--zen-border-radius",
|
||||
borderRadius + "px"
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -121,14 +137,19 @@
|
||||
if (
|
||||
document.documentElement.hasAttribute("inFullscreen") &&
|
||||
window.gZenCompactModeManager?.preference &&
|
||||
!document.getElementById("tabbrowser-tabbox")?.hasAttribute("zen-split-view") &&
|
||||
!document
|
||||
.getElementById("tabbrowser-tabbox")
|
||||
?.hasAttribute("zen-split-view") &&
|
||||
Services.prefs.getBoolPref("zen.view.borderless-fullscreen", true)
|
||||
) {
|
||||
separation = 0;
|
||||
}
|
||||
// In order to still use it on fullscreen, even if it's 0px, add .1px (almost invisible)
|
||||
separation = Math.max(kMinElementSeparation, separation);
|
||||
document.documentElement.style.setProperty("--zen-element-separation", separation + "px");
|
||||
document.documentElement.style.setProperty(
|
||||
"--zen-element-separation",
|
||||
separation + "px"
|
||||
);
|
||||
if (separation == kMinElementSeparation) {
|
||||
document.documentElement.setAttribute("zen-no-padding", true);
|
||||
} else {
|
||||
@@ -147,8 +168,13 @@
|
||||
* Update the accent color.
|
||||
*/
|
||||
updateAccentColor() {
|
||||
const accentColor = Services.prefs.getStringPref("zen.theme.accent-color");
|
||||
document.documentElement.style.setProperty("--zen-primary-color", accentColor);
|
||||
const accentColor = Services.prefs.getStringPref(
|
||||
"zen.theme.accent-color"
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
"--zen-primary-color",
|
||||
accentColor
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -44,14 +44,20 @@ window.gZenCompactModeManager = {
|
||||
_removeHoverFrames: {},
|
||||
|
||||
// Delay to avoid flickering when hovering over the sidebar
|
||||
HOVER_HACK_DELAY: Services.prefs.getIntPref("zen.view.compact.hover-hack-delay", 0),
|
||||
HOVER_HACK_DELAY: Services.prefs.getIntPref(
|
||||
"zen.view.compact.hover-hack-delay",
|
||||
0
|
||||
),
|
||||
|
||||
preInit() {
|
||||
this._wasInCompactMode = Services.prefs.getBoolPref(
|
||||
"zen.view.compact.enable-at-startup",
|
||||
false
|
||||
);
|
||||
this._canDebugLog = Services.prefs.getBoolPref("zen.view.compact.debug", false);
|
||||
this._canDebugLog = Services.prefs.getBoolPref(
|
||||
"zen.view.compact.debug",
|
||||
false
|
||||
);
|
||||
|
||||
this.addContextMenu();
|
||||
},
|
||||
@@ -60,12 +66,18 @@ window.gZenCompactModeManager = {
|
||||
this.addMouseActions();
|
||||
|
||||
const tabIsRightObserver = this._updateSidebarIsOnRight.bind(this);
|
||||
Services.prefs.addObserver("zen.tabs.vertical.right-side", tabIsRightObserver);
|
||||
Services.prefs.addObserver(
|
||||
"zen.tabs.vertical.right-side",
|
||||
tabIsRightObserver
|
||||
);
|
||||
|
||||
window.addEventListener(
|
||||
"unload",
|
||||
() => {
|
||||
Services.prefs.removeObserver("zen.tabs.vertical.right-side", tabIsRightObserver);
|
||||
Services.prefs.removeObserver(
|
||||
"zen.tabs.vertical.right-side",
|
||||
tabIsRightObserver
|
||||
);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
@@ -78,7 +90,9 @@ window.gZenCompactModeManager = {
|
||||
this.addHasPolyfillObserver();
|
||||
|
||||
// Clear hover states when window state changes (minimize, maximize, etc.)
|
||||
window.addEventListener("sizemodechange", () => this._clearAllHoverStates());
|
||||
window.addEventListener("sizemodechange", () =>
|
||||
this._clearAllHoverStates()
|
||||
);
|
||||
|
||||
this._canShowBackgroundTabToast = Services.prefs.getBoolPref(
|
||||
"zen.view.compact.show-background-tab-toast",
|
||||
@@ -86,7 +100,7 @@ window.gZenCompactModeManager = {
|
||||
);
|
||||
|
||||
if (AppConstants.platform == "macosx") {
|
||||
window.addEventListener("mouseover", (event) => {
|
||||
window.addEventListener("mouseover", event => {
|
||||
const buttons = gZenVerticalTabsManager.actualWindowButtons;
|
||||
if (event.target.closest(".titlebar-buttonbox-container") === buttons) {
|
||||
return;
|
||||
@@ -112,7 +126,9 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
get shouldBeCompact() {
|
||||
return !document.documentElement.getAttribute("chromehidden")?.includes("toolbar");
|
||||
return !document.documentElement
|
||||
.getAttribute("chromehidden")
|
||||
?.includes("toolbar");
|
||||
},
|
||||
|
||||
set preference(value) {
|
||||
@@ -147,7 +163,9 @@ window.gZenCompactModeManager = {
|
||||
if (typeof this._sidebarIsOnRight !== "undefined") {
|
||||
return this._sidebarIsOnRight;
|
||||
}
|
||||
this._sidebarIsOnRight = Services.prefs.getBoolPref("zen.tabs.vertical.right-side");
|
||||
this._sidebarIsOnRight = Services.prefs.getBoolPref(
|
||||
"zen.tabs.vertical.right-side"
|
||||
);
|
||||
return this._sidebarIsOnRight;
|
||||
},
|
||||
|
||||
@@ -156,7 +174,12 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
addHasPolyfillObserver() {
|
||||
const attributes = ["panelopen", "open", "breakout-extend", "zen-floating-urlbar"];
|
||||
const attributes = [
|
||||
"panelopen",
|
||||
"open",
|
||||
"breakout-extend",
|
||||
"zen-floating-urlbar",
|
||||
];
|
||||
this.sidebarObserverId = ZenHasPolyfill.observeSelectorExistence(
|
||||
this.sidebar,
|
||||
[
|
||||
@@ -187,7 +210,7 @@ window.gZenCompactModeManager = {
|
||||
// This function is called after exiting DOM fullscreen mode,
|
||||
// so we do a bit of a hack to re-calculate the URL height
|
||||
if (aInstant) {
|
||||
gZenVerticalTabsManager.recalculateURLBarHeight();
|
||||
gZenVerticalTabsManager.recalculateURLBarHeight(true);
|
||||
}
|
||||
if (
|
||||
!aInstant &&
|
||||
@@ -230,7 +253,9 @@ window.gZenCompactModeManager = {
|
||||
|
||||
updateCompactModeContext(isSingleToolbar) {
|
||||
const isIllegalState = this.checkIfIllegalState();
|
||||
const menuitem = document.getElementById("zen-context-menu-compact-mode-toggle");
|
||||
const menuitem = document.getElementById(
|
||||
"zen-context-menu-compact-mode-toggle"
|
||||
);
|
||||
const menu = document.getElementById("zen-context-menu-compact-mode");
|
||||
if (!menu) {
|
||||
return;
|
||||
@@ -292,7 +317,8 @@ window.gZenCompactModeManager = {
|
||||
// on macos: collapsed + left side + only toolbar
|
||||
// on windows: collapsed + right side + only toolbar
|
||||
const closelyIllegalState =
|
||||
(isLeftSideButtons && !isRightSidebar) || (!isLeftSideButtons && isRightSidebar);
|
||||
(isLeftSideButtons && !isRightSidebar) ||
|
||||
(!isLeftSideButtons && isRightSidebar);
|
||||
if (closelyIllegalState && canHideToolbar && !canHideSidebar) {
|
||||
// This state is illegal
|
||||
Services.prefs.setBoolPref("zen.view.compact.hide-tabbar", true);
|
||||
@@ -304,7 +330,7 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
callAllEventListeners() {
|
||||
this._eventListeners.forEach((callback) => callback());
|
||||
this._eventListeners.forEach(callback => callback());
|
||||
},
|
||||
|
||||
addEventListener(callback) {
|
||||
@@ -330,7 +356,6 @@ window.gZenCompactModeManager = {
|
||||
await this.animateCompactMode();
|
||||
this.callAllEventListeners();
|
||||
}
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
if (isUrlbarFocused) {
|
||||
gURLBar.focus();
|
||||
}
|
||||
@@ -339,7 +364,9 @@ window.gZenCompactModeManager = {
|
||||
} else {
|
||||
ZenHasPolyfill.disconnectObserver(this.sidebarObserverId);
|
||||
}
|
||||
window.dispatchEvent(new CustomEvent("ZenCompactMode:Toggled", { detail: this.preference }));
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("ZenCompactMode:Toggled", { detail: this.preference })
|
||||
);
|
||||
},
|
||||
|
||||
// NOTE: Dont actually use event, it's just so we make sure
|
||||
@@ -351,14 +378,20 @@ window.gZenCompactModeManager = {
|
||||
}
|
||||
let sidebarWidth = this.sidebar.getBoundingClientRect().width;
|
||||
const shouldRecalculate =
|
||||
this.preference || document.documentElement.hasAttribute("zen-creating-workspace");
|
||||
const sidebarExpanded = document.documentElement.hasAttribute("zen-sidebar-expanded");
|
||||
this.preference ||
|
||||
document.documentElement.hasAttribute("zen-creating-workspace");
|
||||
const sidebarExpanded = document.documentElement.hasAttribute(
|
||||
"zen-sidebar-expanded"
|
||||
);
|
||||
if (sidebarWidth > 1) {
|
||||
if (shouldRecalculate && sidebarExpanded) {
|
||||
sidebarWidth = Math.max(sidebarWidth, 150);
|
||||
}
|
||||
// Second variable to get the genuine width of the sidebar
|
||||
this.sidebar.style.setProperty("--actual-zen-sidebar-width", `${sidebarWidth}px`);
|
||||
this.sidebar.style.setProperty(
|
||||
"--actual-zen-sidebar-width",
|
||||
`${sidebarWidth}px`
|
||||
);
|
||||
window.dispatchEvent(new window.Event("resize")); // To recalculate the layout
|
||||
if (
|
||||
event &&
|
||||
@@ -369,7 +402,10 @@ window.gZenCompactModeManager = {
|
||||
return;
|
||||
}
|
||||
delete gZenVerticalTabsManager._hadSidebarCollapse;
|
||||
this.sidebar.style.setProperty("--zen-sidebar-width", `${sidebarWidth}px`);
|
||||
this.sidebar.style.setProperty(
|
||||
"--zen-sidebar-width",
|
||||
`${sidebarWidth}px`
|
||||
);
|
||||
}
|
||||
return sidebarWidth;
|
||||
},
|
||||
@@ -391,14 +427,16 @@ window.gZenCompactModeManager = {
|
||||
animateCompactMode() {
|
||||
// Get the splitter width before hiding it (we need to hide it before animating on right)
|
||||
document.documentElement.setAttribute("zen-compact-animating", "true");
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(resolve => {
|
||||
// We need to set the splitter width before hiding it
|
||||
let splitterWidth = document
|
||||
.getElementById("zen-sidebar-splitter")
|
||||
.getBoundingClientRect().width;
|
||||
const isCompactMode = this.preference;
|
||||
const canHideSidebar = this.canHideSidebar;
|
||||
let canAnimate = lazy.COMPACT_MODE_CAN_ANIMATE_SIDEBAR && !this.isSidebarPotentiallyOpen();
|
||||
let canAnimate =
|
||||
lazy.COMPACT_MODE_CAN_ANIMATE_SIDEBAR &&
|
||||
!this.isSidebarPotentiallyOpen();
|
||||
if (typeof this._wasInCompactMode !== "undefined") {
|
||||
canAnimate = false;
|
||||
delete this._wasInCompactMode;
|
||||
@@ -444,8 +482,14 @@ window.gZenCompactModeManager = {
|
||||
.animate(
|
||||
this.sidebar,
|
||||
{
|
||||
marginRight: [0, this.sidebarIsOnRight ? `-${sidebarWidth}px` : 0],
|
||||
marginLeft: [0, this.sidebarIsOnRight ? 0 : `-${sidebarWidth}px`],
|
||||
marginRight: [
|
||||
0,
|
||||
this.sidebarIsOnRight ? `-${sidebarWidth}px` : 0,
|
||||
],
|
||||
marginLeft: [
|
||||
0,
|
||||
this.sidebarIsOnRight ? 0 : `-${sidebarWidth}px`,
|
||||
],
|
||||
},
|
||||
{
|
||||
ease: "easeIn",
|
||||
@@ -512,7 +556,9 @@ window.gZenCompactModeManager = {
|
||||
)
|
||||
.then(() => {
|
||||
this.sidebar.removeAttribute("animate");
|
||||
document.getElementById("browser").style.removeProperty("overflow");
|
||||
document
|
||||
.getElementById("browser")
|
||||
.style.removeProperty("overflow");
|
||||
this.sidebar.style.transition = "none";
|
||||
this.sidebar.style.removeProperty("margin-right");
|
||||
this.sidebar.style.removeProperty("margin-left");
|
||||
@@ -534,7 +580,9 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
updateContextMenu() {
|
||||
const toggle = document.getElementById("zen-context-menu-compact-mode-toggle");
|
||||
const toggle = document.getElementById(
|
||||
"zen-context-menu-compact-mode-toggle"
|
||||
);
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
@@ -570,7 +618,9 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
_updateSidebarIsOnRight() {
|
||||
this._sidebarIsOnRight = Services.prefs.getBoolPref("zen.tabs.vertical.right-side");
|
||||
this._sidebarIsOnRight = Services.prefs.getBoolPref(
|
||||
"zen.tabs.vertical.right-side"
|
||||
);
|
||||
},
|
||||
|
||||
toggleSidebar() {
|
||||
@@ -581,7 +631,9 @@ window.gZenCompactModeManager = {
|
||||
if (this._hideAfterHoverDuration) {
|
||||
return this._hideAfterHoverDuration;
|
||||
}
|
||||
return Services.prefs.getIntPref("zen.view.compact.toolbar-hide-after-hover.duration");
|
||||
return Services.prefs.getIntPref(
|
||||
"zen.view.compact.toolbar-hide-after-hover.duration"
|
||||
);
|
||||
},
|
||||
|
||||
get hoverableElements() {
|
||||
@@ -589,7 +641,9 @@ window.gZenCompactModeManager = {
|
||||
{
|
||||
element: this.sidebar,
|
||||
screenEdge: this.sidebarIsOnRight ? "right" : "left",
|
||||
keepHoverDuration: 100,
|
||||
keepHoverDuration: Services.prefs.getIntPref(
|
||||
"zen.view.compact.sidebar-keep-hover.duration"
|
||||
),
|
||||
},
|
||||
{
|
||||
element: document.getElementById("zen-appcontent-navbar-wrapper"),
|
||||
@@ -612,7 +666,9 @@ window.gZenCompactModeManager = {
|
||||
if (this._flashTimeouts[id]) {
|
||||
clearTimeout(this._flashTimeouts[id]);
|
||||
} else {
|
||||
requestAnimationFrame(() => this._setElementExpandAttribute(element, true, attrName));
|
||||
requestAnimationFrame(() =>
|
||||
this._setElementExpandAttribute(element, true, attrName)
|
||||
);
|
||||
}
|
||||
this._flashTimeouts[id] = setTimeout(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
@@ -628,11 +684,18 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
_setElementExpandAttribute(element, value, attr = "zen-has-hover") {
|
||||
const kVerifiedAttributes = ["zen-has-hover", "has-popup-menu", "zen-compact-mode-active"];
|
||||
const kVerifiedAttributes = [
|
||||
"zen-has-hover",
|
||||
"has-popup-menu",
|
||||
"zen-compact-mode-active",
|
||||
];
|
||||
const isToolbar = element.id === "zen-appcontent-navbar-wrapper";
|
||||
this.log("Setting", attr, "to", value, "on element", element?.id);
|
||||
if (value) {
|
||||
if (attr === "zen-has-hover" && element !== gZenVerticalTabsManager.actualWindowButtons) {
|
||||
if (
|
||||
attr === "zen-has-hover" &&
|
||||
element !== gZenVerticalTabsManager.actualWindowButtons
|
||||
) {
|
||||
element.setAttribute("zen-has-implicit-hover", "true");
|
||||
if (!lazy.COMPACT_MODE_SHOW_SIDEBAR_AND_TOOLBAR_ON_HOVER) {
|
||||
return;
|
||||
@@ -658,7 +721,9 @@ window.gZenCompactModeManager = {
|
||||
// Only remove if none of the verified attributes are present
|
||||
if (
|
||||
isToolbar &&
|
||||
!kVerifiedAttributes.some((verifiedAttr) => element.hasAttribute(verifiedAttr))
|
||||
!kVerifiedAttributes.some(verifiedAttr =>
|
||||
element.hasAttribute(verifiedAttr)
|
||||
)
|
||||
) {
|
||||
gBrowser.tabpanels.removeAttribute("has-toolbar-hovered");
|
||||
}
|
||||
@@ -666,11 +731,14 @@ window.gZenCompactModeManager = {
|
||||
},
|
||||
|
||||
addMouseActions() {
|
||||
gURLBar.addEventListener("mouseenter", (event) => {
|
||||
gURLBar.addEventListener("mouseenter", event => {
|
||||
this.log("Mouse entered URL bar:", event.target);
|
||||
if (event.target.closest("#urlbar[zen-floating-urlbar]")) {
|
||||
window.requestAnimationFrame(() => {
|
||||
this._setElementExpandAttribute(gZenVerticalTabsManager.actualWindowButtons, false);
|
||||
this._setElementExpandAttribute(
|
||||
gZenVerticalTabsManager.actualWindowButtons,
|
||||
false
|
||||
);
|
||||
});
|
||||
this._hasHoveredUrlbar = true;
|
||||
}
|
||||
@@ -684,7 +752,7 @@ window.gZenCompactModeManager = {
|
||||
this._setElementExpandAttribute(target, true);
|
||||
}
|
||||
|
||||
const onEnter = (event) => {
|
||||
const onEnter = event => {
|
||||
setTimeout(() => {
|
||||
if (event.type === "mouseenter" && !event.target.matches(":hover")) {
|
||||
return;
|
||||
@@ -696,7 +764,9 @@ window.gZenCompactModeManager = {
|
||||
this.clearFlashTimeout("has-hover" + target.id);
|
||||
window.requestAnimationFrame(() => {
|
||||
if (
|
||||
document.documentElement.getAttribute("supress-primary-adjustment") === "true" ||
|
||||
document.documentElement.getAttribute(
|
||||
"supress-primary-adjustment"
|
||||
) === "true" ||
|
||||
this._hasHoveredUrlbar ||
|
||||
this._ignoreNextHover ||
|
||||
target.hasAttribute("zen-has-hover")
|
||||
@@ -708,9 +778,10 @@ window.gZenCompactModeManager = {
|
||||
}, this.HOVER_HACK_DELAY);
|
||||
};
|
||||
|
||||
const onLeave = (event) => {
|
||||
const onLeave = event => {
|
||||
if (AppConstants.platform == "macosx") {
|
||||
const buttonRect = gZenVerticalTabsManager.actualWindowButtons.getBoundingClientRect();
|
||||
const buttonRect =
|
||||
gZenVerticalTabsManager.actualWindowButtons.getBoundingClientRect();
|
||||
const MAC_WINDOW_BUTTONS_X_BORDER = buttonRect.width + buttonRect.x;
|
||||
const MAC_WINDOW_BUTTONS_Y_BORDER = buttonRect.height + buttonRect.y;
|
||||
if (
|
||||
@@ -733,8 +804,12 @@ window.gZenCompactModeManager = {
|
||||
}
|
||||
|
||||
if (
|
||||
event.explicitOriginalTarget?.closest?.("#urlbar[zen-floating-urlbar]") ||
|
||||
(document.documentElement.getAttribute("supress-primary-adjustment") === "true" &&
|
||||
event.explicitOriginalTarget?.closest?.(
|
||||
"#urlbar[zen-floating-urlbar]"
|
||||
) ||
|
||||
(document.documentElement.getAttribute(
|
||||
"supress-primary-adjustment"
|
||||
) === "true" &&
|
||||
gZenVerticalTabsManager._hasSetSingleToolbar) ||
|
||||
this._hasHoveredUrlbar ||
|
||||
this._ignoreNextHover ||
|
||||
@@ -757,8 +832,8 @@ window.gZenCompactModeManager = {
|
||||
"zen-has-hover"
|
||||
);
|
||||
} else {
|
||||
this._removeHoverFrames[target.id] = window.requestAnimationFrame(() =>
|
||||
this._setElementExpandAttribute(target, false)
|
||||
this._removeHoverFrames[target.id] = window.requestAnimationFrame(
|
||||
() => this._setElementExpandAttribute(target, false)
|
||||
);
|
||||
}
|
||||
}, this.HOVER_HACK_DELAY);
|
||||
@@ -771,9 +846,12 @@ window.gZenCompactModeManager = {
|
||||
target.addEventListener("dragleave", onLeave);
|
||||
}
|
||||
|
||||
document.documentElement.addEventListener("mouseleave", (event) => {
|
||||
document.documentElement.addEventListener("mouseleave", event => {
|
||||
setTimeout(() => {
|
||||
const screenEdgeCrossed = this._getCrossedEdge(event.pageX, event.pageY);
|
||||
const screenEdgeCrossed = this._getCrossedEdge(
|
||||
event.pageX,
|
||||
event.pageY
|
||||
);
|
||||
if (!screenEdgeCrossed) {
|
||||
return;
|
||||
}
|
||||
@@ -782,8 +860,19 @@ window.gZenCompactModeManager = {
|
||||
continue;
|
||||
}
|
||||
const target = entry.element;
|
||||
const boundAxis = entry.screenEdge === "right" || entry.screenEdge === "left" ? "y" : "x";
|
||||
if (!this._positionInBounds(boundAxis, target, event.pageX, event.pageY, 7)) {
|
||||
const boundAxis =
|
||||
entry.screenEdge === "right" || entry.screenEdge === "left"
|
||||
? "y"
|
||||
: "x";
|
||||
if (
|
||||
!this._positionInBounds(
|
||||
boundAxis,
|
||||
target,
|
||||
event.pageX,
|
||||
event.pageY,
|
||||
7
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
window.cancelAnimationFrame(this._removeHoverFrames[target.id]);
|
||||
@@ -820,7 +909,12 @@ window.gZenCompactModeManager = {
|
||||
});
|
||||
},
|
||||
|
||||
_getCrossedEdge(posX, posY, element = document.documentElement, maxDistance = 10) {
|
||||
_getCrossedEdge(
|
||||
posX,
|
||||
posY,
|
||||
element = document.documentElement,
|
||||
maxDistance = 10
|
||||
) {
|
||||
const targetBox = element.getBoundingClientRect();
|
||||
posX = Math.max(targetBox.left, Math.min(posX, targetBox.right));
|
||||
posY = Math.max(targetBox.top, Math.min(posY, targetBox.bottom));
|
||||
@@ -842,7 +936,11 @@ window.gZenCompactModeManager = {
|
||||
// Clear hover attributes from all hoverable elements
|
||||
for (let entry of this.hoverableElements) {
|
||||
const target = entry.element;
|
||||
if (target && !target.matches(":hover") && target.hasAttribute("zen-has-hover")) {
|
||||
if (
|
||||
target &&
|
||||
!target.matches(":hover") &&
|
||||
target.hasAttribute("zen-has-hover")
|
||||
) {
|
||||
this._setElementExpandAttribute(target, false);
|
||||
this.clearFlashTimeout("has-hover" + target.id);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#navigator-toolbox {
|
||||
--zen-toolbox-max-width: 74px !important;
|
||||
--zen-compact-float: var(--zen-element-separation);
|
||||
|
||||
|
||||
:root[zen-no-padding='true'] & {
|
||||
--zen-compact-float: 10px;
|
||||
--zen-compact-top-toolbar-hidden-fix: var(--zen-compact-float);
|
||||
@@ -78,7 +78,7 @@
|
||||
}
|
||||
:root:not([zen-single-toolbar='true']) & {
|
||||
bottom: calc(var(--zen-compact-float) / 2);
|
||||
height: calc(100% - var(--zen-toolbar-height-with-bookmarks));
|
||||
height: calc(100% - var(--zen-toolbar-height-with-bookmarks));
|
||||
@media -moz-pref('zen.view.compact.hide-toolbar') {
|
||||
height: calc(100% - var(--zen-compact-top-toolbar-hidden-fix, 0px));
|
||||
}
|
||||
@@ -145,9 +145,9 @@
|
||||
}
|
||||
|
||||
#navigator-toolbox:is(
|
||||
[zen-has-hover], [zen-user-show],
|
||||
[zen-has-hover], [zen-user-show],
|
||||
[zen-has-empty-tab], [flash-popup],
|
||||
[has-popup-menu], [movingtab],
|
||||
[has-popup-menu], [movingtab],
|
||||
[zen-compact-mode-active]
|
||||
),
|
||||
&[zen-renaming-tab='true'] #navigator-toolbox {
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
display: flex;
|
||||
}
|
||||
transition: height var(--zen-hidden-toolbar-transition);
|
||||
|
||||
|
||||
height: var(--zen-element-separation);
|
||||
overflow: clip;
|
||||
|
||||
|
||||
@@ -86,7 +86,9 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
);
|
||||
this.shadowRoot.appendChild(link);
|
||||
} catch (error) {
|
||||
console.error(`[${nsZenDownloadAnimationElement.name}] Error loading arc styles: ${error}`);
|
||||
console.error(
|
||||
`[${nsZenDownloadAnimationElement.name}] Error loading arc styles: ${error}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +101,8 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
}
|
||||
|
||||
// Determine animation target position
|
||||
const { endPosition, isDownloadButtonVisible } = this.#determineEndPosition();
|
||||
const { endPosition, isDownloadButtonVisible } =
|
||||
this.#determineEndPosition();
|
||||
const areTabsPositionedRight = this.#areTabsOnRightSide();
|
||||
|
||||
// Create and prepare the arc animation element
|
||||
@@ -131,7 +134,10 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
}
|
||||
|
||||
#areTabsOnRightSide() {
|
||||
const position = Services.prefs.getIntPref("zen.downloads.icon-popup-position", 0);
|
||||
const position = Services.prefs.getIntPref(
|
||||
"zen.downloads.icon-popup-position",
|
||||
0
|
||||
);
|
||||
if (position === 1) {
|
||||
return false;
|
||||
}
|
||||
@@ -143,7 +149,8 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
|
||||
#determineEndPosition() {
|
||||
const downloadsButton = document.getElementById("downloads-button");
|
||||
const isDownloadButtonVisible = downloadsButton && this.#isElementVisible(downloadsButton);
|
||||
const isDownloadButtonVisible =
|
||||
downloadsButton && this.#isElementVisible(downloadsButton);
|
||||
|
||||
let endPosition = { clientX: 0, clientY: 0 };
|
||||
|
||||
@@ -161,7 +168,9 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
const wrapperRect = wrapper.getBoundingClientRect();
|
||||
|
||||
endPosition = {
|
||||
clientX: areTabsPositionedRight ? wrapperRect.right - 42 : wrapperRect.left + 42,
|
||||
clientX: areTabsPositionedRight
|
||||
? wrapperRect.right - 42
|
||||
: wrapperRect.left + 42,
|
||||
clientY: wrapperRect.bottom - 40,
|
||||
};
|
||||
}
|
||||
@@ -179,7 +188,9 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
`;
|
||||
|
||||
const fragment = window.MozXULElement.parseXULToFragment(arcAnimationHTML);
|
||||
const animationElement = fragment.querySelector(".zen-download-arc-animation");
|
||||
const animationElement = fragment.querySelector(
|
||||
".zen-download-arc-animation"
|
||||
);
|
||||
|
||||
Object.assign(animationElement.style, {
|
||||
left: `${startPosition.clientX}px`,
|
||||
@@ -194,7 +205,10 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
|
||||
#calculateOptimalArc(startPosition, endPosition, distance) {
|
||||
// Calculate available space for the arc
|
||||
const availableTopSpace = Math.min(startPosition.clientY, endPosition.clientY);
|
||||
const availableTopSpace = Math.min(
|
||||
startPosition.clientY,
|
||||
endPosition.clientY
|
||||
);
|
||||
const viewportHeight = window.innerHeight;
|
||||
const availableBottomSpace =
|
||||
viewportHeight - Math.max(startPosition.clientY, endPosition.clientY);
|
||||
@@ -203,7 +217,9 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
const shouldArcDownward = availableBottomSpace > availableTopSpace;
|
||||
|
||||
// Use the space in the direction we're arcing
|
||||
const availableSpace = shouldArcDownward ? availableBottomSpace : availableTopSpace;
|
||||
const availableSpace = shouldArcDownward
|
||||
? availableBottomSpace
|
||||
: availableTopSpace;
|
||||
|
||||
// Limit arc height to a percentage of the available space
|
||||
const arcHeight = Math.min(
|
||||
@@ -233,19 +249,30 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
}
|
||||
|
||||
await gZenUIManager.motion.animate(arcAnimationElement, sequence, {
|
||||
duration: Services.prefs.getIntPref("zen.downloads.download-animation-duration") / 1000,
|
||||
duration:
|
||||
Services.prefs.getIntPref(
|
||||
"zen.downloads.download-animation-duration"
|
||||
) / 1000,
|
||||
easing: "cubic-bezier(0.37, 0, 0.63, 1)",
|
||||
fill: "forwards",
|
||||
});
|
||||
|
||||
this.#cleanArcAnimation(arcAnimationElement);
|
||||
} catch (error) {
|
||||
console.error("[nsZenDownloadAnimationElement] Error in animation sequence:", error);
|
||||
console.error(
|
||||
"[nsZenDownloadAnimationElement] Error in animation sequence:",
|
||||
error
|
||||
);
|
||||
this.#cleanArcAnimation(arcAnimationElement);
|
||||
}
|
||||
}
|
||||
|
||||
#createArcAnimationSequence(distanceX, distanceY, arcHeight, shouldArcDownward) {
|
||||
#createArcAnimationSequence(
|
||||
distanceX,
|
||||
distanceY,
|
||||
arcHeight,
|
||||
shouldArcDownward
|
||||
) {
|
||||
const sequence = { offset: [], opacity: [], transform: [] };
|
||||
|
||||
const arcDirection = shouldArcDownward ? 1 : -1;
|
||||
@@ -284,7 +311,9 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
|
||||
// Position on arc
|
||||
const x = distanceX * eased;
|
||||
const y = distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
||||
const y =
|
||||
distanceY * eased +
|
||||
arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
||||
|
||||
// Calculate rotation to point in the direction of movement
|
||||
let rotation = previousRotation;
|
||||
@@ -293,10 +322,12 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
|
||||
const prevX = distanceX * prevEased;
|
||||
const prevAdjustedProgress = prevEased * 2 - 1;
|
||||
const prevVerticalOffset = arcDirection * arcHeight * (1 - prevAdjustedProgress * 2);
|
||||
const prevVerticalOffset =
|
||||
arcDirection * arcHeight * (1 - prevAdjustedProgress * 2);
|
||||
const prevY = distanceY * prevEased + prevVerticalOffset;
|
||||
|
||||
const targetRotation = Math.atan2(y - prevY, x - prevX) * (180 / Math.PI);
|
||||
const targetRotation =
|
||||
Math.atan2(y - prevY, x - prevX) * (180 / Math.PI);
|
||||
|
||||
rotation += (targetRotation - previousRotation) * 0.01;
|
||||
previousRotation = rotation;
|
||||
@@ -353,8 +384,11 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
|
||||
const sideProp = areTabsPositionedRight ? "right" : "left";
|
||||
|
||||
const fragment = window.MozXULElement.parseXULToFragment(boxAnimationHTML);
|
||||
this.#boxAnimationElement = fragment.querySelector(".zen-download-box-animation");
|
||||
const fragment =
|
||||
window.MozXULElement.parseXULToFragment(boxAnimationHTML);
|
||||
this.#boxAnimationElement = fragment.querySelector(
|
||||
".zen-download-box-animation"
|
||||
);
|
||||
|
||||
Object.assign(this.#boxAnimationElement.style, {
|
||||
bottom: "24px",
|
||||
@@ -405,7 +439,10 @@ class nsZenDownloadAnimationElement extends HTMLElement {
|
||||
}
|
||||
|
||||
#getBoxAnimationDurationMs() {
|
||||
return Services.prefs.getIntPref("zen.downloads.download-animation-duration") + 200;
|
||||
return (
|
||||
Services.prefs.getIntPref("zen.downloads.download-animation-duration") +
|
||||
200
|
||||
);
|
||||
}
|
||||
|
||||
async #finishBoxAnimation(areTabsPositionedRight) {
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
|
||||
// Wrap in a block to prevent leaking to window scope.
|
||||
{
|
||||
const isTab = (element) => gBrowser.isTab(element);
|
||||
const isTabGroupLabel = (element) => gBrowser.isTabGroupLabel(element);
|
||||
const isEssentialsPromo = (element) => element?.tagName.toUpperCase() == "ZEN-ESSENTIALS-PROMO";
|
||||
const isTab = element => gBrowser.isTab(element);
|
||||
const isTabGroupLabel = element => gBrowser.isTabGroupLabel(element);
|
||||
const isEssentialsPromo = element =>
|
||||
element?.tagName.toUpperCase() == "ZEN-ESSENTIALS-PROMO";
|
||||
|
||||
/**
|
||||
* The elements in the tab strip from `this.ariaFocusableItems` that contain
|
||||
@@ -34,7 +35,7 @@
|
||||
* @param {MozTabbrowserTab|typeof MozTabbrowserTabGroup.labelElement} element
|
||||
* @returns {MozTabbrowserTab|vbox}
|
||||
*/
|
||||
const elementToMove = (element) => {
|
||||
const elementToMove = element => {
|
||||
if (
|
||||
!element ||
|
||||
element.closest(".zen-current-workspace-indicator") ||
|
||||
@@ -118,9 +119,13 @@
|
||||
init() {
|
||||
super.init();
|
||||
this.handle_windowDragEnter = this.handle_windowDragEnter.bind(this);
|
||||
window.addEventListener("dragleave", this.handle_windowDragLeave.bind(this), {
|
||||
capture: true,
|
||||
});
|
||||
window.addEventListener(
|
||||
"dragleave",
|
||||
this.handle_windowDragLeave.bind(this),
|
||||
{
|
||||
capture: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
startTabDrag(event, tab, ...args) {
|
||||
@@ -133,7 +138,11 @@
|
||||
tab = tab.group;
|
||||
}
|
||||
const draggingTabs = tab.multiselected ? gBrowser.selectedTabs : [tab];
|
||||
const { offsetX, offsetY } = this.#getDragImageOffset(event, tab, draggingTabs);
|
||||
const { offsetX, offsetY } = this.#getDragImageOffset(
|
||||
event,
|
||||
tab,
|
||||
draggingTabs
|
||||
);
|
||||
const dragImage = this.#createDragImageForTabs(draggingTabs);
|
||||
this.originalDragImageArgs = [dragImage, offsetX, offsetY];
|
||||
dt.setDragImage(...this.originalDragImageArgs);
|
||||
@@ -146,7 +155,9 @@
|
||||
const periphery = gZenWorkspaces.activeWorkspaceElement.querySelector(
|
||||
"#tabbrowser-arrowscrollbox-periphery"
|
||||
);
|
||||
const tabRect = window.windowUtils.getBoundsWithoutFlushing(movingTabs[0]);
|
||||
const tabRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
movingTabs[0]
|
||||
);
|
||||
const wrapper = document.createElement("div");
|
||||
let movingTabsCount = Math.min(movingTabs.length, 3);
|
||||
wrapper.style.width = tabRect.width + "px";
|
||||
@@ -160,7 +171,8 @@
|
||||
if (tab.hasAttribute("zen-essential")) {
|
||||
const rect = tab.getBoundingClientRect();
|
||||
tabClone.style.minWidth = tabClone.style.maxWidth = `${rect.width}px`;
|
||||
tabClone.style.minHeight = tabClone.style.maxHeight = `${rect.height}px`;
|
||||
tabClone.style.minHeight =
|
||||
tabClone.style.maxHeight = `${rect.height}px`;
|
||||
if (tabClone.hasAttribute("visuallyselected")) {
|
||||
tabClone.style.transform = "translate(-50%, -50%)";
|
||||
}
|
||||
@@ -181,9 +193,16 @@
|
||||
if (isTab(tabClone)) {
|
||||
// We need to limit the label content so the drag image doesn't grow too big.
|
||||
const label = tabClone.textLabel;
|
||||
const tabLabelParentWidth = label.parentElement.getBoundingClientRect().width;
|
||||
label.textContent = label.textContent.slice(0, Math.floor(tabLabelParentWidth / 6));
|
||||
} else if (gBrowser.isTabGroup(tabClone) && tabClone.hasAttribute("split-view-group")) {
|
||||
const tabLabelParentWidth =
|
||||
label.parentElement.getBoundingClientRect().width;
|
||||
label.textContent = label.textContent.slice(
|
||||
0,
|
||||
Math.floor(tabLabelParentWidth / 6)
|
||||
);
|
||||
} else if (
|
||||
gBrowser.isTabGroup(tabClone) &&
|
||||
tabClone.hasAttribute("split-view-group")
|
||||
) {
|
||||
let tabs = tab.tabs;
|
||||
for (let j = 0; j < tabs.length; j++) {
|
||||
const tabInGroup = tabs[j];
|
||||
@@ -220,7 +239,10 @@
|
||||
// eslint-disable-next-line complexity
|
||||
_animateTabMove(event) {
|
||||
let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
if (event.target.closest("#zen-essentials") && !isEssentialsPromo(event.target)) {
|
||||
if (
|
||||
event.target.closest("#zen-essentials") &&
|
||||
!isEssentialsPromo(event.target)
|
||||
) {
|
||||
if (!isTab(draggedTab)) {
|
||||
this.clearDragOverVisuals();
|
||||
return;
|
||||
@@ -242,7 +264,9 @@
|
||||
tabs = [...movingTabs];
|
||||
}
|
||||
|
||||
let screen = this._tabbrowserTabs.verticalMode ? event.screenY : event.screenX;
|
||||
let screen = this._tabbrowserTabs.verticalMode
|
||||
? event.screenY
|
||||
: event.screenX;
|
||||
if (screen == dragData.animLastScreenPos) {
|
||||
return;
|
||||
}
|
||||
@@ -255,9 +279,11 @@
|
||||
tabs.reverse();
|
||||
}
|
||||
|
||||
let bounds = (ele) => window.windowUtils.getBoundsWithoutFlushing(ele);
|
||||
let bounds = ele => window.windowUtils.getBoundsWithoutFlushing(ele);
|
||||
let logicalForward = screenForward != this._rtlMode;
|
||||
let screenAxis = this._tabbrowserTabs.verticalMode ? "screenY" : "screenX";
|
||||
let screenAxis = this._tabbrowserTabs.verticalMode
|
||||
? "screenY"
|
||||
: "screenX";
|
||||
let size = this._tabbrowserTabs.verticalMode ? "height" : "width";
|
||||
let { width: tabWidth, height: tabHeight } = bounds(draggedTab);
|
||||
let tabSize = this._tabbrowserTabs.verticalMode ? tabHeight : tabWidth;
|
||||
@@ -275,7 +301,7 @@
|
||||
);
|
||||
let lastMovingTab = movingTabs.at(-1);
|
||||
let firstMovingTab = movingTabs[0];
|
||||
let endEdge = (ele) => ele[screenAxis] + bounds(ele)[size];
|
||||
let endEdge = ele => ele[screenAxis] + bounds(ele)[size];
|
||||
let lastMovingTabScreen = endEdge(lastMovingTab);
|
||||
let firstMovingTabScreen = firstMovingTab[screenAxis];
|
||||
let shiftSize = lastMovingTabScreen - firstMovingTabScreen;
|
||||
@@ -298,7 +324,8 @@
|
||||
// Center the tab under the cursor if the tab is not under the cursor while dragging
|
||||
let draggedTabScreenAxis = draggedTab[screenAxis] + translate;
|
||||
if (
|
||||
(screen < draggedTabScreenAxis || screen > draggedTabScreenAxis + tabSize) &&
|
||||
(screen < draggedTabScreenAxis ||
|
||||
screen > draggedTabScreenAxis + tabSize) &&
|
||||
draggedTabScreenAxis + tabSize < endBound &&
|
||||
draggedTabScreenAxis > startBound
|
||||
) {
|
||||
@@ -309,7 +336,7 @@
|
||||
|
||||
dragData.translatePos = translate;
|
||||
|
||||
tabs = tabs.filter((t) => !movingTabsSet.has(t) || t == draggedTab);
|
||||
tabs = tabs.filter(t => !movingTabsSet.has(t) || t == draggedTab);
|
||||
|
||||
/**
|
||||
* When the `draggedTab` is just starting to move, the `draggedTab` is in
|
||||
@@ -333,16 +360,23 @@
|
||||
* @returns {number}
|
||||
*/
|
||||
let getTabShift = (item, dropElementIndex) => {
|
||||
if (item.elementIndex < draggedTab.elementIndex && item.elementIndex >= dropElementIndex) {
|
||||
if (
|
||||
item.elementIndex < draggedTab.elementIndex &&
|
||||
item.elementIndex >= dropElementIndex
|
||||
) {
|
||||
return this._rtlMode ? -shiftSize : shiftSize;
|
||||
}
|
||||
if (item.elementIndex > draggedTab.elementIndex && item.elementIndex < dropElementIndex) {
|
||||
if (
|
||||
item.elementIndex > draggedTab.elementIndex &&
|
||||
item.elementIndex < dropElementIndex
|
||||
) {
|
||||
return this._rtlMode ? shiftSize : -shiftSize;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
let oldDropElementIndex = dragData.animDropElementIndex ?? movingTabs[0].elementIndex;
|
||||
let oldDropElementIndex =
|
||||
dragData.animDropElementIndex ?? movingTabs[0].elementIndex;
|
||||
|
||||
/**
|
||||
* Returns the higher % by which one element overlaps another
|
||||
@@ -423,7 +457,9 @@
|
||||
* time.
|
||||
*/
|
||||
let getOverlappedElement = () => {
|
||||
let point = (screenForward ? lastMovingTabScreen : firstMovingTabScreen) + translate;
|
||||
let point =
|
||||
(screenForward ? lastMovingTabScreen : firstMovingTabScreen) +
|
||||
translate;
|
||||
let low = 0;
|
||||
let high = tabs.length - 1;
|
||||
while (low <= high) {
|
||||
@@ -433,7 +469,9 @@
|
||||
}
|
||||
let element = tabs[mid];
|
||||
let elementForSize = elementToMove(element);
|
||||
screen = elementForSize[screenAxis] + getTabShift(element, oldDropElementIndex);
|
||||
screen =
|
||||
elementForSize[screenAxis] +
|
||||
getTabShift(element, oldDropElementIndex);
|
||||
|
||||
if (screen > point) {
|
||||
high = mid - 1;
|
||||
@@ -489,11 +527,18 @@
|
||||
// 4) we just started dragging and the `oldDropElementIndex` has its default
|
||||
// valuë of `movingTabs[0].elementIndex`. In this case, the drop element
|
||||
// shouldn't be a moving tab, so keep it `undefined`.
|
||||
let lastPossibleDropElement = this._rtlMode ? tabs.find((t) => t != draggedTab) : undefined;
|
||||
let maxElementIndexForDropElement = lastPossibleDropElement?.elementIndex;
|
||||
let lastPossibleDropElement = this._rtlMode
|
||||
? tabs.find(t => t != draggedTab)
|
||||
: undefined;
|
||||
let maxElementIndexForDropElement =
|
||||
lastPossibleDropElement?.elementIndex;
|
||||
if (Number.isInteger(maxElementIndexForDropElement)) {
|
||||
let index = Math.min(oldDropElementIndex, maxElementIndexForDropElement);
|
||||
let oldDropElementCandidate = this._tabbrowserTabs.ariaFocusableItems.at(index);
|
||||
let index = Math.min(
|
||||
oldDropElementIndex,
|
||||
maxElementIndexForDropElement
|
||||
);
|
||||
let oldDropElementCandidate =
|
||||
this._tabbrowserTabs.ariaFocusableItems.at(index);
|
||||
if (!movingTabsSet.has(oldDropElementCandidate)) {
|
||||
dropElement = oldDropElementCandidate;
|
||||
}
|
||||
@@ -507,7 +552,8 @@
|
||||
let dropElementForOverlap = elementToMove(dropElement);
|
||||
|
||||
let dropElementScreen = dropElementForOverlap[screenAxis];
|
||||
let dropElementPos = dropElementScreen + getTabShift(dropElement, oldDropElementIndex);
|
||||
let dropElementPos =
|
||||
dropElementScreen + getTabShift(dropElement, oldDropElementIndex);
|
||||
let dropElementSize = bounds(dropElementForOverlap)[size];
|
||||
let firstMovingTabPos = firstMovingTabScreen + translate;
|
||||
overlapPercent = greatestOverlap(
|
||||
@@ -518,7 +564,9 @@
|
||||
);
|
||||
|
||||
moveOverThreshold = gBrowser._tabGroupsEnabled
|
||||
? Services.prefs.getIntPref("browser.tabs.dragDrop.moveOverThresholdPercent") / 100
|
||||
? Services.prefs.getIntPref(
|
||||
"browser.tabs.dragDrop.moveOverThresholdPercent"
|
||||
) / 100
|
||||
: 0.5;
|
||||
moveOverThreshold = Math.min(1, Math.max(0, moveOverThreshold));
|
||||
let shouldMoveOver = overlapPercent > moveOverThreshold;
|
||||
@@ -536,7 +584,8 @@
|
||||
|
||||
// Recalculate the overlap with the updated drop index for when the
|
||||
// drop element moves over.
|
||||
dropElementPos = dropElementScreen + getTabShift(dropElement, newDropElementIndex);
|
||||
dropElementPos =
|
||||
dropElementScreen + getTabShift(dropElement, newDropElementIndex);
|
||||
overlapPercent = greatestOverlap(
|
||||
firstMovingTabPos,
|
||||
shiftSize,
|
||||
@@ -611,17 +660,25 @@
|
||||
}
|
||||
|
||||
#shouldSwitchSpace(event) {
|
||||
const padding = Services.prefs.getIntPref("zen.workspaces.dnd-switch-padding");
|
||||
const padding = Services.prefs.getIntPref(
|
||||
"zen.workspaces.dnd-switch-padding"
|
||||
);
|
||||
// If we are hovering over the edges of the gNavToolbox or the splitter, we
|
||||
// can change the workspace after a short delay.
|
||||
const splitter = document.getElementById("zen-sidebar-splitter");
|
||||
let rect = window.windowUtils.getBoundsWithoutFlushing(gNavToolbox);
|
||||
if (!(gZenCompactModeManager.preference && gZenCompactModeManager.canHideSidebar)) {
|
||||
rect.width += window.windowUtils.getBoundsWithoutFlushing(splitter).width;
|
||||
if (!(
|
||||
gZenCompactModeManager.preference &&
|
||||
gZenCompactModeManager.canHideSidebar
|
||||
)) {
|
||||
rect.width +=
|
||||
window.windowUtils.getBoundsWithoutFlushing(splitter).width;
|
||||
}
|
||||
const { clientX } = event;
|
||||
const isNearLeftEdge = clientX >= rect.left - padding && clientX <= rect.left + padding;
|
||||
const isNearRightEdge = clientX >= rect.right - padding && clientX <= rect.right + padding;
|
||||
const isNearLeftEdge =
|
||||
clientX >= rect.left - padding && clientX <= rect.left + padding;
|
||||
const isNearRightEdge =
|
||||
clientX >= rect.right - padding && clientX <= rect.right + padding;
|
||||
return { isNearLeftEdge, isNearRightEdge };
|
||||
}
|
||||
|
||||
@@ -639,14 +696,19 @@
|
||||
this.clearSpaceSwitchTimer();
|
||||
return;
|
||||
}
|
||||
const { isNearLeftEdge, isNearRightEdge } = this.#shouldSwitchSpace(event);
|
||||
const { isNearLeftEdge, isNearRightEdge } =
|
||||
this.#shouldSwitchSpace(event);
|
||||
if (isNearLeftEdge || isNearRightEdge) {
|
||||
if (!this.#changeSpaceTimer) {
|
||||
this.#changeSpaceTimer = setTimeout(() => {
|
||||
this.clearDragOverVisuals();
|
||||
gZenWorkspaces
|
||||
.changeWorkspaceShortcut(isNearLeftEdge ? -1 : 1, false, /* Disable wrapping */ true)
|
||||
.then((spaceChanged) => {
|
||||
.changeWorkspaceShortcut(
|
||||
isNearLeftEdge ? -1 : 1,
|
||||
false,
|
||||
/* Disable wrapping */ true
|
||||
)
|
||||
.then(spaceChanged => {
|
||||
if (AppConstants.platform !== "macosx") {
|
||||
// See the hack in #createDragImageForTabs for more details which
|
||||
// explains why we need to do this on non-macOS platforms.
|
||||
@@ -654,7 +716,9 @@
|
||||
}
|
||||
let tabs = this.originalDragImageArgs[0].children;
|
||||
const { isDarkMode, isExplicitMode } =
|
||||
gZenThemePicker.getGradientForWorkspace(spaceChanged);
|
||||
gZenThemePicker.getGradientForWorkspace(spaceChanged, {
|
||||
getGradient: false,
|
||||
});
|
||||
for (let tab of tabs) {
|
||||
if (isExplicitMode) {
|
||||
tab.style.colorScheme = isDarkMode ? "dark" : "light";
|
||||
@@ -725,7 +789,10 @@
|
||||
const edgeZoneThreshold = this._dndSplitThreshold / 100;
|
||||
|
||||
const overlapRatioY = (clientY - targetTop) / targetHeight;
|
||||
if (overlapRatioY < edgeZoneThreshold || overlapRatioY > 1 - edgeZoneThreshold) {
|
||||
if (
|
||||
overlapRatioY < edgeZoneThreshold ||
|
||||
overlapRatioY > 1 - edgeZoneThreshold
|
||||
) {
|
||||
this._clearDragOverSplit();
|
||||
return;
|
||||
}
|
||||
@@ -815,7 +882,10 @@
|
||||
return;
|
||||
}
|
||||
const { innerWidth: winWidth, innerHeight: winHeight } = window;
|
||||
let allowedMargin = Services.prefs.getIntPref("zen.tabs.dnd-outside-window-margin", 5);
|
||||
let allowedMargin = Services.prefs.getIntPref(
|
||||
"zen.tabs.dnd-outside-window-margin",
|
||||
5
|
||||
);
|
||||
const isOutOfWindow =
|
||||
clientX <= allowedMargin ||
|
||||
clientX >= winWidth - allowedMargin ||
|
||||
@@ -881,7 +951,9 @@
|
||||
gBrowser.selectedTab = draggedTab;
|
||||
} else if (isTabGroupLabel(draggedTab)) {
|
||||
draggedTab = draggedTab.group;
|
||||
gZenFolders.changeFolderToSpace(draggedTab, activeWorkspace, { hasDndSwitch: true });
|
||||
gZenFolders.changeFolderToSpace(draggedTab, activeWorkspace, {
|
||||
hasDndSwitch: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -922,7 +994,8 @@
|
||||
}
|
||||
if (
|
||||
isTabGroupLabel(draggedTab) ||
|
||||
(isTab(draggedTab) && draggedTab.group?.hasAttribute("split-view-group"))
|
||||
(isTab(draggedTab) &&
|
||||
draggedTab.group?.hasAttribute("split-view-group"))
|
||||
) {
|
||||
draggedTab = draggedTab.group;
|
||||
}
|
||||
@@ -939,7 +1012,8 @@
|
||||
!dropElement ||
|
||||
dropElement.hasAttribute("zen-essential") ||
|
||||
draggedTab.hasAttribute("zen-essential") ||
|
||||
draggedTab.getAttribute("zen-workspace-id") != gZenWorkspaces.activeWorkspace ||
|
||||
draggedTab.getAttribute("zen-workspace-id") !=
|
||||
gZenWorkspaces.activeWorkspace ||
|
||||
!dropElement.visible ||
|
||||
!draggedTab.visible ||
|
||||
draggedTab.ownerGlobal !== window
|
||||
@@ -949,7 +1023,7 @@
|
||||
this.#isAnimatingTabMove = true;
|
||||
const animateElement = (ele, translateY) => {
|
||||
ele.style.transform = `translateY(${translateY}px)`;
|
||||
let animateInternal = (resolve) => {
|
||||
let animateInternal = resolve => {
|
||||
const clearStyles = () => {
|
||||
ele.style.transform = "";
|
||||
ele.style.zIndex = "";
|
||||
@@ -960,7 +1034,11 @@
|
||||
return;
|
||||
}
|
||||
gZenUIManager
|
||||
.elementAnimate(ele, { y: [translateY, 0] }, { duration: 100, easing: "ease-out" })
|
||||
.elementAnimate(
|
||||
ele,
|
||||
{ y: [translateY, 0] },
|
||||
{ duration: 100, easing: "ease-out" }
|
||||
)
|
||||
.then(() => {
|
||||
clearStyles();
|
||||
})
|
||||
@@ -969,7 +1047,7 @@
|
||||
// Wait for the next event loop tick to ensure the initial transform style is applied.
|
||||
// We need to ensure the element has already been moved in the DOM before starting the animation.
|
||||
animations.push(
|
||||
new Promise((resolve) =>
|
||||
new Promise(resolve =>
|
||||
setTimeout(() => {
|
||||
setTimeout(() => animateInternal(resolve), 0);
|
||||
})
|
||||
@@ -1025,7 +1103,9 @@
|
||||
: -rect.height * tabsInBetween.length;
|
||||
draggedTabTranslateY +=
|
||||
extraTranslate *
|
||||
(focusableDraggedTab.elementIndex > focusableDropElement.elementIndex ? 1 : -1);
|
||||
(focusableDraggedTab.elementIndex > focusableDropElement.elementIndex
|
||||
? 1
|
||||
: -1);
|
||||
draggedTab.style.zIndex = "9";
|
||||
animateElement(draggedTab, draggedTabTranslateY);
|
||||
} catch (e) {
|
||||
@@ -1043,7 +1123,8 @@
|
||||
let ownerGlobal = draggedTab?.ownerGlobal;
|
||||
draggedTab.style.visibility = "";
|
||||
let thisFromGlobal = ownerGlobal?.gBrowser.tabContainer.tabDragAndDrop;
|
||||
let currentEssenialContainer = ownerGlobal.gZenWorkspaces.getCurrentEssentialsContainer();
|
||||
let currentEssenialContainer =
|
||||
ownerGlobal.gZenWorkspaces.getCurrentEssentialsContainer();
|
||||
if (currentEssenialContainer?.essentialsPromo) {
|
||||
currentEssenialContainer.essentialsPromo.remove();
|
||||
}
|
||||
@@ -1057,9 +1138,13 @@
|
||||
thisFromGlobal._clearDragOverSplit();
|
||||
this.#maybeClearVerticalPinnedGridDragOver();
|
||||
thisFromGlobal.originalDragImageArgs = [];
|
||||
window.removeEventListener("dragenter", thisFromGlobal.handle_windowDragEnter, {
|
||||
capture: true,
|
||||
});
|
||||
window.removeEventListener(
|
||||
"dragenter",
|
||||
thisFromGlobal.handle_windowDragEnter,
|
||||
{
|
||||
capture: true,
|
||||
}
|
||||
);
|
||||
this.#isOutOfWindow = false;
|
||||
if (thisFromGlobal._browserDragImageWrapper) {
|
||||
thisFromGlobal._browserDragImageWrapper.remove();
|
||||
@@ -1119,8 +1204,13 @@
|
||||
return true;
|
||||
}
|
||||
if (folder.isLiveFolder) {
|
||||
const liveFolderItemId = draggedTab.getAttribute("zen-live-folder-item-id");
|
||||
if (!liveFolderItemId || !liveFolderItemId.startsWith(`${folder.id}:`)) {
|
||||
const liveFolderItemId = draggedTab.getAttribute(
|
||||
"zen-live-folder-item-id"
|
||||
);
|
||||
if (
|
||||
!liveFolderItemId ||
|
||||
!liveFolderItemId.startsWith(`${folder.id}:`)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1139,17 +1229,25 @@
|
||||
let showIndicatorUnderNewTabButton = false;
|
||||
let dropBefore = false;
|
||||
let dropElementFromEvent = event.target.closest(dropZoneSelector);
|
||||
if (!dropElement && dropElementFromEvent?.isZenFolder) {
|
||||
// If we're dragging over a folder, we want to show the indicator on the folder itself, not the label.
|
||||
dropElementFromEvent = dropElementFromEvent.labelElement;
|
||||
}
|
||||
dropElement = dropElementFromEvent || dropElement;
|
||||
if (!dropElementFromEvent) {
|
||||
let hoveringPeriphery = !!event.target.closest(
|
||||
":is(#tabbrowser-arrowscrollbox-periphery, .pinned-tabs-container-separator)"
|
||||
);
|
||||
if (event.target.classList.contains("zen-workspace-empty-space") || hoveringPeriphery) {
|
||||
if (
|
||||
event.target.classList.contains("zen-workspace-empty-space") ||
|
||||
hoveringPeriphery
|
||||
) {
|
||||
let lastTab = gBrowser.tabs.at(-1);
|
||||
let pinnedTabsCount = gBrowser._numVisiblePinTabsWithoutCollapsed;
|
||||
|
||||
// Only if there are no normal tabs to drop after
|
||||
showIndicatorUnderNewTabButton = lastTab.hasAttribute("zen-empty-tab");
|
||||
showIndicatorUnderNewTabButton =
|
||||
lastTab.hasAttribute("zen-empty-tab");
|
||||
let useLastPinnd =
|
||||
(hoveringPeriphery ||
|
||||
(showIndicatorUnderNewTabButton &&
|
||||
@@ -1187,12 +1285,18 @@
|
||||
let possibleFolderElement = dropElement.parentElement;
|
||||
let isZenFolder = possibleFolderElement?.isZenFolder;
|
||||
let canHightlightGroup =
|
||||
gZenFolders.highlightGroupOnDragOver(possibleFolderElement, movingTabs) || !isZenFolder;
|
||||
gZenFolders.highlightGroupOnDragOver(
|
||||
possibleFolderElement,
|
||||
movingTabs
|
||||
) || !isZenFolder;
|
||||
let rect = window.windowUtils.getBoundsWithoutFlushing(dropElement);
|
||||
const overlapPercent = (event.clientY - rect.top) / rect.height;
|
||||
// We wan't to leave a small threshold (20% for example) so we can drag tabs below and above
|
||||
// a folder label without dragging into the folder.
|
||||
let threshold = Services.prefs.getIntPref("zen.tabs.folder-dragover-threshold-percent") / 100;
|
||||
let threshold =
|
||||
Services.prefs.getIntPref(
|
||||
"zen.tabs.folder-dragover-threshold-percent"
|
||||
) / 100;
|
||||
let dropIntoFolder =
|
||||
isZenFolder &&
|
||||
(overlapPercent < threshold ||
|
||||
@@ -1211,7 +1315,8 @@
|
||||
if (
|
||||
isTabGroupLabel(draggedTab) &&
|
||||
draggedTab.group?.isZenFolder &&
|
||||
(((isTab(dropElement) || dropElement.hasAttribute("split-view-group")) &&
|
||||
(((isTab(dropElement) ||
|
||||
dropElement.hasAttribute("split-view-group")) &&
|
||||
(!dropElement.pinned || dropElement.hasAttribute("zen-essential"))) ||
|
||||
showIndicatorUnderNewTabButton)
|
||||
) {
|
||||
@@ -1226,12 +1331,16 @@
|
||||
dropElement.hasAttribute("split-view-group")
|
||||
) {
|
||||
if (showIndicatorUnderNewTabButton) {
|
||||
rect = window.windowUtils.getBoundsWithoutFlushing(this.#dragShiftableItems.at(-1));
|
||||
rect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
this.#dragShiftableItems.at(-1)
|
||||
);
|
||||
}
|
||||
const indicator = gZenPinnedTabManager.dragIndicator;
|
||||
let top = 0;
|
||||
threshold =
|
||||
Services.prefs.getIntPref("browser.tabs.dragDrop.moveOverThresholdPercent") / 100;
|
||||
Services.prefs.getIntPref(
|
||||
"browser.tabs.dragDrop.moveOverThresholdPercent"
|
||||
) / 100;
|
||||
if (overlapPercent > threshold || showIndicatorUnderNewTabButton) {
|
||||
top = Math.round(rect.top + rect.height) + "px";
|
||||
dropBefore = false;
|
||||
@@ -1243,23 +1352,36 @@
|
||||
shouldPlayHapticFeedback = true;
|
||||
}
|
||||
indicator.setAttribute("orientation", "horizontal");
|
||||
indicator.style.setProperty("--indicator-left", rect.left + separation / 2 + "px");
|
||||
indicator.style.setProperty("--indicator-width", rect.width - separation + "px");
|
||||
indicator.style.setProperty(
|
||||
"--indicator-left",
|
||||
rect.left + separation / 2 + "px"
|
||||
);
|
||||
indicator.style.setProperty(
|
||||
"--indicator-width",
|
||||
rect.width - separation + "px"
|
||||
);
|
||||
indicator.style.top = top;
|
||||
indicator.style.removeProperty("left");
|
||||
this.#removeDragOverBackground();
|
||||
if (!isTab(dropElement) && dropElement?.parentElement?.isZenFolder) {
|
||||
dropElement = dropElement.parentElement;
|
||||
}
|
||||
} else if (dropElement.classList.contains("zen-drop-target") && canHightlightGroup) {
|
||||
} else if (
|
||||
dropElement.classList.contains("zen-drop-target") &&
|
||||
canHightlightGroup
|
||||
) {
|
||||
shouldPlayHapticFeedback =
|
||||
this.#applyDragOverBackground(dropElement) && !gZenPinnedTabManager._dragIndicator;
|
||||
this.#applyDragOverBackground(dropElement) &&
|
||||
!gZenPinnedTabManager._dragIndicator;
|
||||
gZenPinnedTabManager.removeTabContainersDragoverClass();
|
||||
dropElement = dropElement.parentElement?.labelElement || dropElement;
|
||||
if (dropElement.classList.contains("zen-current-workspace-indicator")) {
|
||||
dropElement =
|
||||
elementToMove(this._tabbrowserTabs.ariaFocusableItems.at(gBrowser._numZenEssentials)) ||
|
||||
dropElement;
|
||||
elementToMove(
|
||||
this._tabbrowserTabs.ariaFocusableItems.at(
|
||||
gBrowser._numZenEssentials
|
||||
)
|
||||
) || dropElement;
|
||||
dropBefore = true;
|
||||
}
|
||||
}
|
||||
@@ -1305,12 +1427,17 @@
|
||||
|
||||
if (!this._fakeEssentialTab) {
|
||||
const numEssentials = gBrowser._numZenEssentials;
|
||||
let pinnedTabs = this._tabbrowserTabs.ariaFocusableItems.slice(0, numEssentials);
|
||||
let pinnedTabs = this._tabbrowserTabs.ariaFocusableItems.slice(
|
||||
0,
|
||||
numEssentials
|
||||
);
|
||||
this._fakeEssentialTab = document.createXULElement("vbox");
|
||||
this._fakeEssentialTab.elementIndex = numEssentials;
|
||||
delete dragData.animDropElementIndex;
|
||||
if (!draggedTab.hasAttribute("zen-essential")) {
|
||||
event.target.closest(".zen-essentials-container").appendChild(this._fakeEssentialTab);
|
||||
event.target
|
||||
.closest(".zen-essentials-container")
|
||||
.appendChild(this._fakeEssentialTab);
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
pinnedTabs.push(this._fakeEssentialTab);
|
||||
this._fakeEssentialTab.getBoundingClientRect(); // Initialize layout
|
||||
@@ -1318,8 +1445,9 @@
|
||||
this.#makeDragImageEssential(event);
|
||||
let tabsPerRow = 0;
|
||||
let position = RTL_UI
|
||||
? window.windowUtils.getBoundsWithoutFlushing(this._tabbrowserTabs.pinnedTabsContainer)
|
||||
.right
|
||||
? window.windowUtils.getBoundsWithoutFlushing(
|
||||
this._tabbrowserTabs.pinnedTabsContainer
|
||||
).right
|
||||
: 0;
|
||||
for (let pinnedTab of pinnedTabs) {
|
||||
let tabPosition;
|
||||
@@ -1341,13 +1469,19 @@
|
||||
this.#maxTabsPerRow = tabsPerRow;
|
||||
}
|
||||
let usingFakeElement = !!this._fakeEssentialTab.parentElement;
|
||||
let elementMoving = usingFakeElement ? this._fakeEssentialTab : draggedTab;
|
||||
let elementMoving = usingFakeElement
|
||||
? this._fakeEssentialTab
|
||||
: draggedTab;
|
||||
if (usingFakeElement) {
|
||||
movingTabs = [this._fakeEssentialTab];
|
||||
}
|
||||
|
||||
let dragDataScreenX = usingFakeElement ? this._fakeEssentialTab.screenX : dragData.screenX;
|
||||
let dragDataScreenY = usingFakeElement ? this._fakeEssentialTab.screenY : dragData.screenY;
|
||||
let dragDataScreenX = usingFakeElement
|
||||
? this._fakeEssentialTab.screenX
|
||||
: dragData.screenX;
|
||||
let dragDataScreenY = usingFakeElement
|
||||
? this._fakeEssentialTab.screenY
|
||||
: dragData.screenY;
|
||||
|
||||
dragData.animLastScreenX ??= dragDataScreenX;
|
||||
dragData.animLastScreenY ??= dragDataScreenY;
|
||||
@@ -1355,11 +1489,17 @@
|
||||
let screenX = event.screenX;
|
||||
let screenY = event.screenY;
|
||||
|
||||
if (screenY == dragData.animLastScreenY && screenX == dragData.animLastScreenX) {
|
||||
if (
|
||||
screenY == dragData.animLastScreenY &&
|
||||
screenX == dragData.animLastScreenX
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tabs = this._tabbrowserTabs.visibleTabs.slice(0, gBrowser._numZenEssentials);
|
||||
let tabs = this._tabbrowserTabs.visibleTabs.slice(
|
||||
0,
|
||||
gBrowser._numZenEssentials
|
||||
);
|
||||
if (usingFakeElement) {
|
||||
tabs.push(this._fakeEssentialTab);
|
||||
}
|
||||
@@ -1369,7 +1509,8 @@
|
||||
dragData.animLastScreenY = screenY;
|
||||
dragData.animLastScreenX = screenX;
|
||||
|
||||
let { width: tabWidth, height: tabHeight } = elementMoving.getBoundingClientRect();
|
||||
let { width: tabWidth, height: tabHeight } =
|
||||
elementMoving.getBoundingClientRect();
|
||||
tabWidth += 4; // Add 6px to account for the gap
|
||||
tabHeight += 4;
|
||||
let shiftSizeX = tabWidth;
|
||||
@@ -1383,11 +1524,16 @@
|
||||
let lastTab = tabs.at(-1);
|
||||
if (RTL_UI) {
|
||||
firstTabInRow =
|
||||
tabs.length >= this.#maxTabsPerRow ? tabs[this.#maxTabsPerRow - 1] : lastTab;
|
||||
tabs.length >= this.#maxTabsPerRow
|
||||
? tabs[this.#maxTabsPerRow - 1]
|
||||
: lastTab;
|
||||
lastTabInRow = tabs[0];
|
||||
} else {
|
||||
firstTabInRow = tabs[0];
|
||||
lastTabInRow = tabs.length >= this.#maxTabsPerRow ? tabs[this.#maxTabsPerRow - 1] : lastTab;
|
||||
lastTabInRow =
|
||||
tabs.length >= this.#maxTabsPerRow
|
||||
? tabs[this.#maxTabsPerRow - 1]
|
||||
: lastTab;
|
||||
}
|
||||
let lastMovingTabScreenX = movingTabs.at(-1).screenX;
|
||||
let lastMovingTabScreenY = movingTabs.at(-1).screenY;
|
||||
@@ -1436,7 +1582,7 @@
|
||||
// * We're doing a binary search in order to reduce the amount of
|
||||
// tabs we need to check.
|
||||
|
||||
tabs = tabs.filter((t) => !movingTabs.includes(t) || t == elementMoving);
|
||||
tabs = tabs.filter(t => !movingTabs.includes(t) || t == elementMoving);
|
||||
let firstTabCenterX = firstMovingTabScreenX + translateX + tabWidth / 2;
|
||||
let lastTabCenterX = lastMovingTabScreenX + translateX + tabWidth / 2;
|
||||
let tabCenterX = directionX ? lastTabCenterX : firstTabCenterX;
|
||||
@@ -1447,25 +1593,37 @@
|
||||
let shiftNumber = this.#maxTabsPerRow - movingTabs.length;
|
||||
|
||||
let getTabShift = (tab, dropIndex) => {
|
||||
if (tab.elementIndex < elementMoving.elementIndex && tab.elementIndex >= dropIndex) {
|
||||
if (
|
||||
tab.elementIndex < elementMoving.elementIndex &&
|
||||
tab.elementIndex >= dropIndex
|
||||
) {
|
||||
// If tab is at the end of a row, shift back and down
|
||||
let tabRow = Math.ceil((tab.elementIndex + 1) / this.#maxTabsPerRow);
|
||||
let shiftedTabRow = Math.ceil(
|
||||
(tab.elementIndex + 1 + movingTabs.length) / this.#maxTabsPerRow
|
||||
);
|
||||
if (tab.elementIndex && tabRow != shiftedTabRow) {
|
||||
return [RTL_UI ? tabWidth * shiftNumber : -tabWidth * shiftNumber, shiftSizeY];
|
||||
return [
|
||||
RTL_UI ? tabWidth * shiftNumber : -tabWidth * shiftNumber,
|
||||
shiftSizeY,
|
||||
];
|
||||
}
|
||||
return [RTL_UI ? -shiftSizeX : shiftSizeX, 0];
|
||||
}
|
||||
if (tab.elementIndex > elementMoving.elementIndex && tab.elementIndex < dropIndex) {
|
||||
if (
|
||||
tab.elementIndex > elementMoving.elementIndex &&
|
||||
tab.elementIndex < dropIndex
|
||||
) {
|
||||
// If tab is not index 0 and at the start of a row, shift across and up
|
||||
let tabRow = Math.floor(tab.elementIndex / this.#maxTabsPerRow);
|
||||
let shiftedTabRow = Math.floor(
|
||||
(tab.elementIndex - movingTabs.length) / this.#maxTabsPerRow
|
||||
);
|
||||
if (tab.elementIndex && tabRow != shiftedTabRow) {
|
||||
return [RTL_UI ? -tabWidth * shiftNumber : tabWidth * shiftNumber, -shiftSizeY];
|
||||
return [
|
||||
RTL_UI ? -tabWidth * shiftNumber : tabWidth * shiftNumber,
|
||||
-shiftSizeY,
|
||||
];
|
||||
}
|
||||
return [RTL_UI ? shiftSizeX : -shiftSizeX, 0];
|
||||
}
|
||||
@@ -1475,7 +1633,8 @@
|
||||
let low = 0;
|
||||
let high = tabs.length - 1;
|
||||
let newIndex = -1;
|
||||
let oldIndex = dragData.animDropElementIndex ?? movingTabs[0].elementIndex;
|
||||
let oldIndex =
|
||||
dragData.animDropElementIndex ?? movingTabs[0].elementIndex;
|
||||
while (low <= high) {
|
||||
let mid = Math.floor((low + high) / 2);
|
||||
if (tabs[mid] == elementMoving && ++mid > high) {
|
||||
@@ -1489,9 +1648,13 @@
|
||||
low = mid + 1;
|
||||
} else if (screenY > tabCenterY) {
|
||||
high = mid - 1;
|
||||
} else if (RTL_UI ? screenX + tabWidth < tabCenterX : screenX > tabCenterX) {
|
||||
} else if (
|
||||
RTL_UI ? screenX + tabWidth < tabCenterX : screenX > tabCenterX
|
||||
) {
|
||||
high = mid - 1;
|
||||
} else if (RTL_UI ? screenX > tabCenterX : screenX + tabWidth < tabCenterX) {
|
||||
} else if (
|
||||
RTL_UI ? screenX > tabCenterX : screenX + tabWidth < tabCenterX
|
||||
) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
newIndex = tabs[mid].elementIndex;
|
||||
@@ -1523,7 +1686,8 @@
|
||||
for (let tab of tabs) {
|
||||
if (tab != draggedTab) {
|
||||
let [shiftX, shiftY] = getTabShift(tab, newIndex);
|
||||
tab.style.transform = shiftX || shiftY ? `translate(${shiftX}px, ${shiftY}px)` : "";
|
||||
tab.style.transform =
|
||||
shiftX || shiftY ? `translate(${shiftX}px, ${shiftY}px)` : "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1532,7 +1696,10 @@
|
||||
if (this._fakeEssentialTab) {
|
||||
this._fakeEssentialTab.remove();
|
||||
delete this._fakeEssentialTab;
|
||||
for (let tab of this._tabbrowserTabs.visibleTabs.slice(0, gBrowser._numZenEssentials)) {
|
||||
for (let tab of this._tabbrowserTabs.visibleTabs.slice(
|
||||
0,
|
||||
gBrowser._numZenEssentials
|
||||
)) {
|
||||
tab.style.transform = "";
|
||||
}
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
@@ -1551,8 +1718,13 @@
|
||||
tab.setAttribute("zen-essential", "true");
|
||||
tab.setAttribute("pinned", "true");
|
||||
tab.setAttribute("selected", "true");
|
||||
const draggedTabRect = window.windowUtils.getBoundsWithoutFlushing(this._fakeEssentialTab);
|
||||
tab.style.minWidth = tab.style.maxWidth = wrapper.style.width = draggedTabRect.width + "px";
|
||||
const draggedTabRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
this._fakeEssentialTab
|
||||
);
|
||||
tab.style.minWidth =
|
||||
tab.style.maxWidth =
|
||||
wrapper.style.width =
|
||||
draggedTabRect.width + "px";
|
||||
tab.style.minHeight =
|
||||
tab.style.maxHeight =
|
||||
wrapper.style.height =
|
||||
|
||||
@@ -22,4 +22,3 @@ interface nsIZenDragAndDrop : nsISupports {
|
||||
*/
|
||||
void onDragEnd();
|
||||
};
|
||||
|
||||
|
||||
@@ -10,26 +10,25 @@ namespace {
|
||||
|
||||
static constexpr auto kZenDefaultDragImageOpacity =
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
// For GTK, the default is 0.5 (DRAG_IMAGE_ALPHA_LEVEL) to match
|
||||
// the native behavior. Make sure its synced with the following variable:
|
||||
// https://searchfox.org/firefox-main/rev/14c08f0368ead8bfdddec62f43e0bb5c8fd61289/widget/gtk/nsDragService.cpp#75
|
||||
// For GTK, the default is 0.5 (DRAG_IMAGE_ALPHA_LEVEL) to match
|
||||
// the native behavior. Make sure its synced with the following variable:
|
||||
// https://searchfox.org/firefox-main/rev/14c08f0368ead8bfdddec62f43e0bb5c8fd61289/widget/gtk/nsDragService.cpp#75
|
||||
0.5f;
|
||||
#else
|
||||
// For other platforms, the default is whatever the value of DRAG_TRANSLUCENCY
|
||||
// is, defined in nsBaseDragService.h
|
||||
// For other platforms, the default is whatever the value of
|
||||
// DRAG_TRANSLUCENCY is, defined in nsBaseDragService.h
|
||||
DRAG_TRANSLUCENCY;
|
||||
#endif
|
||||
|
||||
} // namespace: <empty>
|
||||
} // namespace
|
||||
|
||||
// Use the macro to inject all of the definitions for nsISupports.
|
||||
NS_IMPL_ISUPPORTS(nsZenDragAndDrop, nsIZenDragAndDrop)
|
||||
|
||||
nsZenDragAndDrop::nsZenDragAndDrop() {
|
||||
(void)this->OnDragEnd();
|
||||
}
|
||||
nsZenDragAndDrop::nsZenDragAndDrop() { (void)this->OnDragEnd(); }
|
||||
|
||||
auto nsZenDragAndDrop::GetZenDragAndDropInstance() -> nsCOMPtr<nsZenDragAndDrop> {
|
||||
auto nsZenDragAndDrop::GetZenDragAndDropInstance()
|
||||
-> nsCOMPtr<nsZenDragAndDrop> {
|
||||
return do_GetService(ZEN_BOOSTS_BACKEND_CONTRACTID);
|
||||
}
|
||||
|
||||
@@ -45,4 +44,4 @@ nsZenDragAndDrop::OnDragEnd() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace: zen
|
||||
} // namespace zen
|
||||
|
||||
@@ -28,10 +28,11 @@ class nsZenDragAndDrop final : public nsIZenDragAndDrop {
|
||||
auto GetDragImageOpacity() const { return mDragImageOpacity; }
|
||||
|
||||
/**
|
||||
* @brief Get the singleton instance of nsZenDragAndDrop. There may be occasions
|
||||
* where it won't be available (e.g. on the content process), so this may return
|
||||
* nullptr.
|
||||
* @return nsZenDragAndDrop* The singleton instance, or nullptr if not available
|
||||
* @brief Get the singleton instance of nsZenDragAndDrop. There may be
|
||||
* occasions where it won't be available (e.g. on the content process), so
|
||||
* this may return nullptr.
|
||||
* @return nsZenDragAndDrop* The singleton instance, or nullptr if not
|
||||
* available
|
||||
*/
|
||||
static auto GetZenDragAndDropInstance() -> nsCOMPtr<nsZenDragAndDrop>;
|
||||
|
||||
@@ -40,6 +41,6 @@ class nsZenDragAndDrop final : public nsIZenDragAndDrop {
|
||||
float mDragImageOpacity{};
|
||||
};
|
||||
|
||||
} // namespace zen
|
||||
} // namespace zen
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
|
||||
const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
ZenLiveFoldersManager: "resource:///modules/zen/ZenLiveFoldersManager.sys.mjs",
|
||||
ZenLiveFoldersManager:
|
||||
"resource:///modules/zen/ZenLiveFoldersManager.sys.mjs",
|
||||
});
|
||||
|
||||
export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
@@ -77,7 +78,7 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
|
||||
this.labelElement.parentElement.setAttribute("context", "zenFolderActions");
|
||||
|
||||
this.labelElement.onRenameFinished = (newLabel) => {
|
||||
this.labelElement.onRenameFinished = newLabel => {
|
||||
this.name = newLabel.trim() || "Folder";
|
||||
const event = new CustomEvent("ZenFolderRenamed", {
|
||||
bubbles: true,
|
||||
@@ -127,7 +128,9 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
|
||||
get childActiveGroups() {
|
||||
if (this.tagName === "zen-workspace-collapsible-pins") {
|
||||
return Array.from(this.parentElement.querySelectorAll("zen-folder[has-active]"));
|
||||
return Array.from(
|
||||
this.parentElement.querySelectorAll("zen-folder[has-active]")
|
||||
);
|
||||
}
|
||||
return Array.from(this.querySelectorAll("zen-folder[has-active]"));
|
||||
}
|
||||
@@ -193,7 +196,7 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
|
||||
get allItems() {
|
||||
return [...this.groupContainer.children].filter(
|
||||
(child) =>
|
||||
child =>
|
||||
!(
|
||||
child.classList.contains("zen-tab-group-start") ||
|
||||
child.classList.contains("pinned-tabs-container-separator")
|
||||
@@ -227,7 +230,9 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
} else {
|
||||
const folders = new Map();
|
||||
for (let tab of this._activeTabs) {
|
||||
const group = tab?.group?.hasAttribute("split-view-group") ? tab?.group?.group : tab?.group;
|
||||
const group = tab?.group?.hasAttribute("split-view-group")
|
||||
? tab?.group?.group
|
||||
: tab?.group;
|
||||
if (!folders.has(group?.id)) {
|
||||
folders.set(group?.id, group?.activeGroups?.at(-1));
|
||||
}
|
||||
@@ -247,7 +252,10 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
}
|
||||
|
||||
get resetButton() {
|
||||
return this.labelElement.parentElement?.querySelector(".tab-reset-button") ?? null;
|
||||
return (
|
||||
this.labelElement.parentElement?.querySelector(".tab-reset-button") ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
unloadAllTabs(event) {
|
||||
@@ -280,8 +288,13 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
|
||||
addTabs(tabs) {
|
||||
super.addTabs(tabs);
|
||||
if (this.collapsed && !gZenFolders._sessionRestoring && this.isLiveFolder && tabs.length) {
|
||||
tabs.forEach((tab) => {
|
||||
if (
|
||||
this.collapsed &&
|
||||
!gZenFolders._sessionRestoring &&
|
||||
this.isLiveFolder &&
|
||||
tabs.length
|
||||
) {
|
||||
tabs.forEach(tab => {
|
||||
tab.setAttribute("folder-active", "true");
|
||||
});
|
||||
gZenFolders.animateCollapse(this);
|
||||
|
||||
@@ -36,7 +36,10 @@ function groupIsCollapsiblePins(group) {
|
||||
}
|
||||
|
||||
class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
#ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref("zen.folders.max-subfolders", 5);
|
||||
#ZEN_MAX_SUBFOLDERS = Services.prefs.getIntPref(
|
||||
"zen.folders.max-subfolders",
|
||||
5
|
||||
);
|
||||
|
||||
#popup = null;
|
||||
#popupTimer = null;
|
||||
@@ -69,10 +72,12 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
const contextMenuItemsToolbar = window.MozXULElement.parseXULToFragment(
|
||||
`<menuitem id="zen-context-menu-new-folder-toolbar" data-l10n-id="zen-toolbar-context-new-folder"/>`
|
||||
);
|
||||
document.getElementById("toolbar-context-openANewTab").after(contextMenuItemsToolbar);
|
||||
document
|
||||
.getElementById("toolbar-context-openANewTab")
|
||||
.after(contextMenuItemsToolbar);
|
||||
|
||||
const folderActionsMenu = document.getElementById("zenFolderActions");
|
||||
folderActionsMenu.addEventListener("popupshowing", (event) => {
|
||||
folderActionsMenu.addEventListener("popupshowing", event => {
|
||||
const target = event.explicitOriginalTarget;
|
||||
let folder;
|
||||
if (gBrowser.isTabGroupLabel(target)) {
|
||||
@@ -93,7 +98,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
this.#lastFolderContextMenu = folder;
|
||||
gZenLiveFoldersUI.buildContextMenu(folder);
|
||||
|
||||
const newSubfolderItem = document.getElementById("context_zenFolderNewSubfolder");
|
||||
const newSubfolderItem = document.getElementById(
|
||||
"context_zenFolderNewSubfolder"
|
||||
);
|
||||
newSubfolderItem.setAttribute(
|
||||
"disabled",
|
||||
folder.level >= this.#ZEN_MAX_SUBFOLDERS - 1 ? "true" : "false"
|
||||
@@ -105,7 +112,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
changeFolderSpace.innerHTML = "";
|
||||
for (const workspace of [...gZenWorkspaces.getWorkspaces()].reverse()) {
|
||||
const item = gZenWorkspaces.generateMenuItemForWorkspace(workspace);
|
||||
item.addEventListener("command", (event) => {
|
||||
item.addEventListener("command", event => {
|
||||
if (!this.#lastFolderContextMenu) {
|
||||
return;
|
||||
}
|
||||
@@ -120,7 +127,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
folderActionsMenu.addEventListener(
|
||||
"popuphidden",
|
||||
(event) => {
|
||||
event => {
|
||||
if (event.target === folderActionsMenu) {
|
||||
this.#lastFolderContextMenu = null;
|
||||
}
|
||||
@@ -128,7 +135,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
folderActionsMenu.addEventListener("command", (event) => {
|
||||
folderActionsMenu.addEventListener("command", event => {
|
||||
if (!this.#lastFolderContextMenu) {
|
||||
return;
|
||||
}
|
||||
@@ -198,12 +205,17 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
window.addEventListener("TabSelect", this);
|
||||
window.addEventListener("TabOpen", this);
|
||||
const onNewFolder = this.#onNewFolder.bind(this);
|
||||
document.getElementById("zen-context-menu-new-folder").addEventListener("command", onNewFolder);
|
||||
document
|
||||
.getElementById("zen-context-menu-new-folder")
|
||||
.addEventListener("command", onNewFolder);
|
||||
document
|
||||
.getElementById("zen-context-menu-new-folder-toolbar")
|
||||
.addEventListener("command", onNewFolder);
|
||||
SessionStore.promiseInitialized.then(() => {
|
||||
gBrowser.tabContainer.addEventListener("dragstart", this.cancelPopupTimer.bind(this));
|
||||
gBrowser.tabContainer.addEventListener(
|
||||
"dragstart",
|
||||
this.cancelPopupTimer.bind(this)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,7 +246,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
if (group.hasAttribute("split-view-group") && group.hasAttribute("zen-pinned-changed")) {
|
||||
if (
|
||||
group.hasAttribute("split-view-group") &&
|
||||
group.hasAttribute("zen-pinned-changed")
|
||||
) {
|
||||
// zen-pinned-changed remove it and set it to had-zen-pinned-changed to keep
|
||||
// track of the original pinned state
|
||||
group.removeAttribute("zen-pinned-changed");
|
||||
@@ -258,9 +273,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
const isActiveFolder = parentFolder?.activeGroups?.length > 0;
|
||||
const isSplitView = folder.hasAttribute("split-view-group");
|
||||
if (isActiveFolder && isSplitView) {
|
||||
parentFolder.activeTabs = [...new Set([...parentFolder.activeTabs, ...folder.tabs])].sort(
|
||||
(a, b) => a._tPos > b._tPos
|
||||
);
|
||||
parentFolder.activeTabs = [
|
||||
...new Set([...parentFolder.activeTabs, ...folder.tabs]),
|
||||
].sort((a, b) => a._tPos > b._tPos);
|
||||
}
|
||||
parentFolder.collapsed = isActiveFolder;
|
||||
}
|
||||
@@ -314,7 +329,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
async on_TabUngrouped(event) {
|
||||
const tab = event.detail;
|
||||
const group = event.target;
|
||||
if (group.hasAttribute("split-view-group") && tab.hasAttribute("had-zen-pinned-changed")) {
|
||||
if (
|
||||
group.hasAttribute("split-view-group") &&
|
||||
tab.hasAttribute("had-zen-pinned-changed")
|
||||
) {
|
||||
tab.setAttribute("zen-pinned-changed", true);
|
||||
tab.removeAttribute("had-zen-pinned-changed");
|
||||
}
|
||||
@@ -381,7 +399,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
#onNewFolder(event) {
|
||||
const isFromToolbar = event.target.id === "zen-context-menu-new-folder-toolbar";
|
||||
const isFromToolbar =
|
||||
event.target.id === "zen-context-menu-new-folder-toolbar";
|
||||
const contextMenu = event.target.parentElement;
|
||||
let tabs = TabContextMenu.contextTab?.multiselected
|
||||
? gBrowser.selectedTabs
|
||||
@@ -401,7 +420,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
// Prevent create folder inside Live Folder
|
||||
const thereIsOneLiveFolderTab = tabs?.some((tab) =>
|
||||
const thereIsOneLiveFolderTab = tabs?.some(tab =>
|
||||
tab.hasAttribute("zen-live-folder-item-id")
|
||||
);
|
||||
if (thereIsOneLiveFolderTab) {
|
||||
@@ -423,7 +442,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
async #convertFolderToSpace(folder) {
|
||||
const currentWorkspace = gZenWorkspaces.getActiveWorkspaceFromCache();
|
||||
let selectedTab = folder.tabs.find((tab) => tab.selected);
|
||||
let selectedTab = folder.tabs.find(tab => tab.selected);
|
||||
const icon = folder.icon?.querySelector("svg .icon image");
|
||||
|
||||
const newSpace = await gZenWorkspaces.createAndSaveWorkspace(
|
||||
@@ -432,20 +451,23 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
/* dontChange= */ false,
|
||||
currentWorkspace.containerTabId,
|
||||
{
|
||||
beforeChangeCallback: async (newWorkspace) => {
|
||||
await new Promise((resolve) => {
|
||||
beforeChangeCallback: async newWorkspace => {
|
||||
await new Promise(resolve => {
|
||||
requestAnimationFrame(async () => {
|
||||
const workspacePinnedContainer = gZenWorkspaces.workspaceElement(
|
||||
newWorkspace.uuid
|
||||
).pinnedTabsContainer;
|
||||
const tabs = folder.allItems.filter((tab) => !tab.hasAttribute("zen-empty-tab"));
|
||||
const tabs = folder.allItems.filter(
|
||||
tab => !tab.hasAttribute("zen-empty-tab")
|
||||
);
|
||||
workspacePinnedContainer.append(...tabs);
|
||||
await folder.delete();
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
if (selectedTab) {
|
||||
selectedTab.setAttribute("zen-workspace-id", newWorkspace.uuid);
|
||||
selectedTab.removeAttribute("folder-active");
|
||||
gZenWorkspaces.lastSelectedWorkspaceTabs[newWorkspace.uuid] = selectedTab;
|
||||
gZenWorkspaces.lastSelectedWorkspaceTabs[newWorkspace.uuid] =
|
||||
selectedTab;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
@@ -461,7 +483,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
tab.style.height = "";
|
||||
}
|
||||
gBrowser.TabStateFlusher.flush(tab.linkedBrowser);
|
||||
if (gZenWorkspaces.lastSelectedWorkspaceTabs[currentWorkspace.uuid] === tab) {
|
||||
if (
|
||||
gZenWorkspaces.lastSelectedWorkspaceTabs[currentWorkspace.uuid] === tab
|
||||
) {
|
||||
// This tab is no longer the last selected tab in the previous workspace because it's being moved to
|
||||
// the current workspace
|
||||
delete gZenWorkspaces.lastSelectedWorkspaceTabs[currentWorkspace.uuid];
|
||||
@@ -496,7 +520,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
folder.dispatchEvent(new CustomEvent("ZenFolderChangedWorkspace", { bubbles: true }));
|
||||
folder.dispatchEvent(
|
||||
new CustomEvent("ZenFolderChangedWorkspace", { bubbles: true })
|
||||
);
|
||||
|
||||
if (!hasDndSwitch) {
|
||||
gZenWorkspaces.changeWorkspaceWithID(workspaceId).then(() => {
|
||||
@@ -513,8 +539,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
createFolder(tabs = [], options = {}) {
|
||||
const filteredTabs = tabs
|
||||
.filter((tab) => !tab.hasAttribute("zen-essential"))
|
||||
.map((tab) => {
|
||||
.filter(tab => !tab.hasAttribute("zen-essential"))
|
||||
.map(tab => {
|
||||
gBrowser.pinTab(tab);
|
||||
if (tab?.group?.hasAttribute("split-view-group")) {
|
||||
tab = tab.group;
|
||||
@@ -526,9 +552,12 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
options.workspaceId
|
||||
)?.pinnedTabsContainer;
|
||||
const pinnedContainer =
|
||||
options.workspaceId && workspacePinned ? workspacePinned : gZenWorkspaces.pinnedTabsContainer;
|
||||
options.workspaceId && workspacePinned
|
||||
? workspacePinned
|
||||
: gZenWorkspaces.pinnedTabsContainer;
|
||||
const insertBefore =
|
||||
options.insertBefore || pinnedContainer.querySelector(".pinned-tabs-container-separator");
|
||||
options.insertBefore ||
|
||||
pinnedContainer.querySelector(".pinned-tabs-container-separator");
|
||||
const emptyTab = gBrowser.addTab("about:blank", {
|
||||
skipAnimation: true,
|
||||
pinned: true,
|
||||
@@ -557,7 +586,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
// deliberate user action indicating the tab has importance for the user.
|
||||
// Without this, it is not possible to save and close a tab group with
|
||||
// a short lifetime.
|
||||
folder.tabs.forEach((tab) => {
|
||||
folder.tabs.forEach(tab => {
|
||||
gBrowser.TabStateFlusher.flush(tab.linkedBrowser);
|
||||
});
|
||||
|
||||
@@ -572,7 +601,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
_createFolderNode(options = {}) {
|
||||
const folder = document.createXULElement("zen-folder", { is: "zen-folder" });
|
||||
const folder = document.createXULElement("zen-folder", {
|
||||
is: "zen-folder",
|
||||
});
|
||||
let id = options.id;
|
||||
if (!id) {
|
||||
// Note: If this changes, make sure to also update the
|
||||
@@ -587,14 +618,17 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
folder.color = "zen-workspace-color";
|
||||
folder.isLiveFolder = options.isLiveFolder;
|
||||
|
||||
folder.setAttribute("zen-workspace-id", options.workspaceId || gZenWorkspaces.activeWorkspace);
|
||||
folder.setAttribute(
|
||||
"zen-workspace-id",
|
||||
options.workspaceId || gZenWorkspaces.activeWorkspace
|
||||
);
|
||||
|
||||
// note: We set if the folder is collapsed some time after creation.
|
||||
// we do this to ensure marginBottom is set correctly in the case
|
||||
// that we want it to initially be collapsed.
|
||||
setTimeout(
|
||||
// eslint-disable-next-line no-shadow
|
||||
(folder) => {
|
||||
folder => {
|
||||
folder.collapsed = !!options.collapsed;
|
||||
},
|
||||
0,
|
||||
@@ -618,7 +652,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
gBrowser.pinTab(otherTab);
|
||||
}
|
||||
this._piningFolder = false;
|
||||
gBrowser.pinnedTabsContainer.insertBefore(group, gBrowser.pinnedTabsContainer.lastChild);
|
||||
gBrowser.pinnedTabsContainer.insertBefore(
|
||||
group,
|
||||
gBrowser.pinnedTabsContainer.lastChild
|
||||
);
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
return true;
|
||||
}
|
||||
@@ -649,13 +686,18 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
openTabsPopup(event) {
|
||||
event.stopPropagation();
|
||||
if (document.documentElement.getAttribute("zen-renaming-tab") || gURLBar.focused) {
|
||||
if (
|
||||
document.documentElement.getAttribute("zen-renaming-tab") ||
|
||||
gURLBar.focused
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeGroup = event.target.parentElement;
|
||||
if (
|
||||
activeGroup.tabs.filter((tab) => this.#shouldAppearOnTabSearch(tab, activeGroup)).length === 0
|
||||
activeGroup.tabs.filter(tab =>
|
||||
this.#shouldAppearOnTabSearch(tab, activeGroup)
|
||||
).length === 0
|
||||
) {
|
||||
// If the group has no tabs, we don't show the popup
|
||||
return;
|
||||
@@ -679,31 +721,38 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
foundTabs++;
|
||||
}
|
||||
}
|
||||
document.getElementById("zen-folder-tabs-search-no-results").hidden = foundTabs > 0;
|
||||
document.getElementById("zen-folder-tabs-search-no-results").hidden =
|
||||
foundTabs > 0;
|
||||
};
|
||||
search.addEventListener("input", onSearchInput);
|
||||
|
||||
const onKeyDown = (event) => {
|
||||
const onKeyDown = event => {
|
||||
// Arrow down and up to navigate through the list
|
||||
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
||||
event.preventDefault();
|
||||
const items = Array.from(tabsList.children).filter((item) => !item.hidden);
|
||||
const items = Array.from(tabsList.children).filter(
|
||||
item => !item.hidden
|
||||
);
|
||||
if (items.length === 0) {
|
||||
return;
|
||||
}
|
||||
let index = items.indexOf(tabsList.querySelector(".folders-tabs-list-item[selected]"));
|
||||
let index = items.indexOf(
|
||||
tabsList.querySelector(".folders-tabs-list-item[selected]")
|
||||
);
|
||||
if (event.key === "ArrowDown") {
|
||||
index = (index + 1) % items.length;
|
||||
} else if (event.key === "ArrowUp") {
|
||||
index = (index - 1 + items.length) % items.length;
|
||||
}
|
||||
items.forEach((item) => item.removeAttribute("selected"));
|
||||
items.forEach(item => item.removeAttribute("selected"));
|
||||
const targetItem = items[index];
|
||||
targetItem.setAttribute("selected", "true");
|
||||
targetItem.scrollIntoView({ block: "start", behavior: "smooth" });
|
||||
} else if (event.key === "Enter") {
|
||||
// Enter to select the currently highlighted item
|
||||
const highlightedItem = tabsList.querySelector(".folders-tabs-list-item[selected]");
|
||||
const highlightedItem = tabsList.querySelector(
|
||||
".folders-tabs-list-item[selected]"
|
||||
);
|
||||
if (highlightedItem) {
|
||||
highlightedItem.click();
|
||||
}
|
||||
@@ -714,7 +763,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
const target = event.target;
|
||||
target.setAttribute("open", true);
|
||||
|
||||
const handlePopupHidden = (event) => {
|
||||
const handlePopupHidden = event => {
|
||||
if (event.target !== this.#popup) {
|
||||
return;
|
||||
}
|
||||
@@ -733,14 +782,19 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
this.#popup.addEventListener("popuphidden", handlePopupHidden, { once: true });
|
||||
this.#popup.addEventListener("popuphidden", handlePopupHidden, {
|
||||
once: true,
|
||||
});
|
||||
this.#popup.openPopup(target, this.#searchPopupOptions);
|
||||
}
|
||||
|
||||
get #searchPopupOptions() {
|
||||
const isRightSide = gZenVerticalTabsManager._prefsRightSide;
|
||||
const position = isRightSide ? "topleft topright" : "topright topleft";
|
||||
let size = Math.min(this.#popup.querySelector("#zen-folder-tabs-list").children.length, 6);
|
||||
let size = Math.min(
|
||||
this.#popup.querySelector("#zen-folder-tabs-list").children.length,
|
||||
6
|
||||
);
|
||||
size *= 48;
|
||||
return {
|
||||
position,
|
||||
@@ -756,7 +810,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
// account for the visibility of the tab itself, it's just a literal
|
||||
// representation of the `hidden` attribute.
|
||||
const tabIsInActiveGroup = group.activeTabs.includes(tab);
|
||||
return !tabIsInActiveGroup && !(tab.hidden || tab.hasAttribute("zen-empty-tab"));
|
||||
return (
|
||||
!tabIsInActiveGroup && !(tab.hidden || tab.hasAttribute("zen-empty-tab"))
|
||||
);
|
||||
}
|
||||
|
||||
#populateTabsList(group) {
|
||||
@@ -786,7 +842,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
// We don't need to do anything if the URL is invalid. e.g. about:blank
|
||||
}
|
||||
let tabLabel = tab.label || "";
|
||||
let iconURL = gBrowser.getIcon(tab) || PlacesUtils.favicons.defaultFavicon.spec;
|
||||
let iconURL =
|
||||
gBrowser.getIcon(tab) || PlacesUtils.favicons.defaultFavicon.spec;
|
||||
|
||||
icon.src = iconURL;
|
||||
|
||||
@@ -809,7 +866,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
item.setAttribute("selected", "true");
|
||||
}
|
||||
|
||||
item.setAttribute("data-label", `${tabLabel.toLowerCase()} ${tabURL.toLowerCase()}`);
|
||||
item.setAttribute(
|
||||
"data-label",
|
||||
`${tabLabel.toLowerCase()} ${tabURL.toLowerCase()}`
|
||||
);
|
||||
|
||||
item.addEventListener("click", () => {
|
||||
gBrowser.selectedTab = tab;
|
||||
@@ -846,11 +906,17 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line complexity
|
||||
setFolderIndentation(tabs, groupElem = undefined, forCollapse = true, animate = true) {
|
||||
setFolderIndentation(
|
||||
tabs,
|
||||
groupElem = undefined,
|
||||
forCollapse = true,
|
||||
animate = true
|
||||
) {
|
||||
if (!gZenPinnedTabManager.expandedSidebarMode) {
|
||||
return;
|
||||
}
|
||||
const isSpaceCollapsed = gZenWorkspaces.activeWorkspaceElement?.hasCollapsedPinnedTabs;
|
||||
const isSpaceCollapsed =
|
||||
gZenWorkspaces.activeWorkspaceElement?.hasCollapsedPinnedTabs;
|
||||
|
||||
let tab = tabs[0];
|
||||
let isTab = false;
|
||||
@@ -863,7 +929,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
if (
|
||||
gBrowser.isTab(groupElem) &&
|
||||
(!(groupElem.hasAttribute("zen-empty-tab") && groupElem.group === tab.group) ||
|
||||
(!(
|
||||
groupElem.hasAttribute("zen-empty-tab") && groupElem.group === tab.group
|
||||
) ||
|
||||
groupElem?.hasAttribute("zen-empty-tab"))
|
||||
) {
|
||||
groupElem = groupElem.group;
|
||||
@@ -893,7 +961,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
for (const tabItem of tabs) {
|
||||
if (gBrowser.isTabGroupLabel(tabItem) || tabItem.group?.hasAttribute("split-view-group")) {
|
||||
if (
|
||||
gBrowser.isTabGroupLabel(tabItem) ||
|
||||
tabItem.group?.hasAttribute("split-view-group")
|
||||
) {
|
||||
tabItem.group.style.setProperty("--zen-folder-indent", `${spacing}px`);
|
||||
continue;
|
||||
}
|
||||
@@ -915,9 +986,11 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
onlySvgIcons: true,
|
||||
allowNone: Boolean(group.iconURL),
|
||||
closeOnSelect: false,
|
||||
onSelect: (icon) => {
|
||||
onSelect: icon => {
|
||||
this.setFolderUserIcon(group, icon);
|
||||
group.dispatchEvent(new CustomEvent("TabGroupUpdate", { bubbles: true }));
|
||||
group.dispatchEvent(
|
||||
new CustomEvent("TabGroupUpdate", { bubbles: true })
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -948,7 +1021,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
const labelContainer = group.querySelector(".tab-group-label-container");
|
||||
// Setup mouseenter/mouseleave events for the folder
|
||||
labelContainer.addEventListener("mouseenter", (event) => {
|
||||
labelContainer.addEventListener("mouseenter", event => {
|
||||
if (
|
||||
!group.collapsed ||
|
||||
!Services.prefs.getBoolPref("zen.folders.search.enabled") ||
|
||||
@@ -977,7 +1050,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
storeDataForSessionStore() {
|
||||
const folders = Array.from(gBrowser.tabContainer.querySelectorAll("zen-folder"));
|
||||
const folders = Array.from(
|
||||
gBrowser.tabContainer.querySelectorAll("zen-folder")
|
||||
);
|
||||
const splitGroups = Array.from(
|
||||
gBrowser.tabContainer.querySelectorAll("tab-group[split-view-group]")
|
||||
);
|
||||
@@ -1004,8 +1079,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
continue;
|
||||
}
|
||||
const emptyFolderTabs = folder.tabs
|
||||
.filter((tab) => tab.hasAttribute("zen-empty-tab"))
|
||||
.map((tab) => tab.getAttribute("id"));
|
||||
.filter(tab => tab.hasAttribute("zen-empty-tab"))
|
||||
.map(tab => tab.getAttribute("id"));
|
||||
|
||||
let prevSiblingInfo = null;
|
||||
const prevSibling = folder.previousElementSibling;
|
||||
@@ -1014,7 +1089,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
if (prevSibling) {
|
||||
if (gBrowser.isTabGroup(prevSibling)) {
|
||||
prevSiblingInfo = { type: "group", id: prevSibling.id };
|
||||
} else if (gBrowser.isTab(prevSibling) && prevSibling.hasAttribute("id")) {
|
||||
} else if (
|
||||
gBrowser.isTab(prevSibling) &&
|
||||
prevSibling.hasAttribute("id")
|
||||
) {
|
||||
prevSiblingInfo = { type: "tab", id: prevSibling.getAttribute("id") };
|
||||
} else {
|
||||
prevSiblingInfo = { type: "start", id: null };
|
||||
@@ -1061,8 +1139,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
tabFolderWorkingData.set(folderData.id, workingData);
|
||||
|
||||
const oldGroup = document.getElementById(folderData.id);
|
||||
folderData.emptyTabIds.forEach((id) => {
|
||||
oldGroup?.querySelector(`tab[id="${id}"]`)?.setAttribute("zen-empty-tab", true);
|
||||
folderData.emptyTabIds.forEach(id => {
|
||||
oldGroup
|
||||
?.querySelector(`tab[id="${id}"]`)
|
||||
?.setAttribute("zen-empty-tab", true);
|
||||
});
|
||||
if (gBrowser.isTabGroup(oldGroup)) {
|
||||
if (!folderData.splitViewGroup) {
|
||||
@@ -1097,7 +1177,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
}
|
||||
|
||||
for (const { node, containingTabsFragment } of tabFolderWorkingData.values()) {
|
||||
for (const {
|
||||
node,
|
||||
containingTabsFragment,
|
||||
} of tabFolderWorkingData.values()) {
|
||||
if (node) {
|
||||
node.appendChild(containingTabsFragment);
|
||||
}
|
||||
@@ -1111,7 +1194,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
switch (stateData?.prevSiblingInfo?.type) {
|
||||
case "tab":
|
||||
case "group": {
|
||||
const item = document.getElementById(stateData.prevSiblingInfo.id);
|
||||
const item = document.getElementById(
|
||||
stateData.prevSiblingInfo.id
|
||||
);
|
||||
if (item) {
|
||||
item.after(node);
|
||||
break;
|
||||
@@ -1124,7 +1209,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
default: {
|
||||
// Should insert after zen-empty-tab
|
||||
const start = parentWorkingData.node.groupStartElement.nextElementSibling;
|
||||
const start =
|
||||
parentWorkingData.node.groupStartElement.nextElementSibling;
|
||||
start.after(node);
|
||||
}
|
||||
}
|
||||
@@ -1140,9 +1226,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
setTimeout(() => {
|
||||
delete this._sessionRestoring;
|
||||
}, 0);
|
||||
delete this._sessionRestoring;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1163,10 +1247,11 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
if (
|
||||
folder?.isZenFolder &&
|
||||
(!folder.hasAttribute("split-view-group") || !folder.hasAttribute("selected")) &&
|
||||
(!folder.hasAttribute("split-view-group") ||
|
||||
!folder.hasAttribute("selected")) &&
|
||||
!(
|
||||
folder.level >= this.#ZEN_MAX_SUBFOLDERS &&
|
||||
movingTabs?.some((t) => gBrowser.isTabGroupLabel(t))
|
||||
movingTabs?.some(t => gBrowser.isTabGroupLabel(t))
|
||||
)
|
||||
) {
|
||||
if (folder.collapsed) {
|
||||
@@ -1191,8 +1276,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
#normalizeGroupItems(items) {
|
||||
return items
|
||||
.filter((item) => !item.hasAttribute("zen-empty-tab"))
|
||||
.map((item) => {
|
||||
.filter(item => !item.hasAttribute("zen-empty-tab"))
|
||||
.map(item => {
|
||||
if (gBrowser.isTabGroup(item)) {
|
||||
item = item.firstChild;
|
||||
} else if (gBrowser.isTabGroupLabel(item)) {
|
||||
@@ -1219,11 +1304,15 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
#collectGroupItems(group, opts = {}) {
|
||||
const { selectedTabs = [], splitViewIds = new Set(), activeFoldersIds = new Set() } = opts;
|
||||
const {
|
||||
selectedTabs = [],
|
||||
splitViewIds = new Set(),
|
||||
activeFoldersIds = new Set(),
|
||||
} = opts;
|
||||
const folders = new Map();
|
||||
return group.childGroupsAndTabs
|
||||
.filter((item) => !item.hasAttribute("zen-empty-tab"))
|
||||
.map((item) => {
|
||||
.filter(item => !item.hasAttribute("zen-empty-tab"))
|
||||
.map(item => {
|
||||
const isSplitView = item.group?.hasAttribute?.("split-view-group");
|
||||
const itemGroup = isSplitView ? item.group.group : item.group;
|
||||
if (!folders.has(itemGroup?.id)) {
|
||||
@@ -1257,7 +1346,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
#createAnimation(items, targetState, opts, callback = () => {}) {
|
||||
items = Array.isArray(items) ? items : [items];
|
||||
return items.map((item) =>
|
||||
return items.map(item =>
|
||||
gZenUIManager.motion.animate(item, targetState, opts).then(callback)
|
||||
);
|
||||
}
|
||||
@@ -1267,7 +1356,8 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
if (selectedTabs.length) {
|
||||
return heightShift;
|
||||
}
|
||||
heightShift += window.windowUtils.getBoundsWithoutFlushing(tabsContainer).height;
|
||||
heightShift +=
|
||||
window.windowUtils.getBoundsWithoutFlushing(tabsContainer).height;
|
||||
if (tabsContainer.separatorElement) {
|
||||
heightShift -= window.windowUtils.getBoundsWithoutFlushing(
|
||||
tabsContainer.separatorElement
|
||||
@@ -1278,7 +1368,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
get #folderAnimationDuration() {
|
||||
return this._sessionRestoring || this._dontAnimateFolder ? 0 : 0.12;
|
||||
return this._dontAnimateFolder ? 0 : 0.12;
|
||||
}
|
||||
|
||||
async animateCollapse(group) {
|
||||
@@ -1298,7 +1388,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
splitViewIds,
|
||||
activeFoldersIds,
|
||||
});
|
||||
const collapsedHeight = this.#calculateHeightShift(tabsContainer, selectedTabs);
|
||||
const collapsedHeight = this.#calculateHeightShift(
|
||||
tabsContainer,
|
||||
selectedTabs
|
||||
);
|
||||
|
||||
if (selectedTabs.length) {
|
||||
for (let i = 0; i < groupItems.length; i++) {
|
||||
@@ -1318,7 +1411,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
if (activeFolderId && activeFoldersIds.has(activeFolderId)) {
|
||||
// If item is tab-group-label-container we should hide it.
|
||||
// Other items between tab-group-labe-container and folder-active tab should be visible cuz they are hidden by margin-top
|
||||
if (item.parentElement.id !== activeFolderId && !item.hasAttribute("folder-active")) {
|
||||
if (
|
||||
item.parentElement.id !== activeFolderId &&
|
||||
!item.hasAttribute("folder-active")
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1331,7 +1427,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
group.setAttribute("has-active", "true");
|
||||
group.activeTabs = selectedTabs;
|
||||
|
||||
selectedTabs.forEach((tab) => {
|
||||
selectedTabs.forEach(tab => {
|
||||
this.setFolderIndentation([tab], group, /* for collapse = */ true);
|
||||
});
|
||||
}
|
||||
@@ -1348,7 +1444,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
...this.#createAnimation(
|
||||
groupStart,
|
||||
{
|
||||
marginTop: -(collapsedHeight + 4 * (selectedTabs.length === 0 ? 1 : 0)),
|
||||
marginTop: -(
|
||||
collapsedHeight +
|
||||
4 * (selectedTabs.length === 0 ? 1 : 0)
|
||||
),
|
||||
},
|
||||
{ duration, ease: "easeInOut" }
|
||||
)
|
||||
@@ -1440,7 +1539,11 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
let activeGroup = folders.get(tabGroup?.id);
|
||||
if (activeGroup) {
|
||||
this.setFolderIndentation([tab], activeGroup, /* for collapse = */ true);
|
||||
this.setFolderIndentation(
|
||||
[tab],
|
||||
activeGroup,
|
||||
/* for collapse = */ true
|
||||
);
|
||||
} else {
|
||||
// Since the folder is now expanded, we should remove active attribute
|
||||
// to the tab that was previously visible
|
||||
@@ -1538,7 +1641,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
async animateUnload(group, tabToUnload, ungroup = false) {
|
||||
const isSplitView = tabToUnload.group?.hasAttribute("split-view-group");
|
||||
if ((!group?.isZenFolder || !isSplitView) && !tabToUnload.hasAttribute("folder-active")) {
|
||||
if (
|
||||
(!group?.isZenFolder || !isSplitView) &&
|
||||
!tabToUnload.hasAttribute("folder-active")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const animations = [];
|
||||
@@ -1546,7 +1652,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
const activeGroups = group.activeGroups;
|
||||
for (const folder of activeGroups) {
|
||||
folder.activeTabs = folder.activeTabs.filter((tab) => tab !== tabToUnload);
|
||||
folder.activeTabs = folder.activeTabs.filter(tab => tab !== tabToUnload);
|
||||
|
||||
if (folder.activeTabs.length === 0) {
|
||||
lastTab = true;
|
||||
@@ -1563,7 +1669,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
// the correct container size in the DOM
|
||||
tabsContainer.offsetHeight;
|
||||
tabsContainer.setAttribute("hidden", true);
|
||||
const collapsedHeight = this.#calculateHeightShift(tabsContainer, []);
|
||||
const collapsedHeight = this.#calculateHeightShift(
|
||||
tabsContainer,
|
||||
[]
|
||||
);
|
||||
groupStart.style.marginTop = `${-(collapsedHeight + 4)}px`;
|
||||
};
|
||||
|
||||
@@ -1614,7 +1723,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
|
||||
// Await the tab unload animation first
|
||||
await Promise.all(tabUnloadAnimations);
|
||||
await Promise.all(animations.map((item) => (typeof item === "function" ? item() : item)));
|
||||
await Promise.all(
|
||||
animations.map(item => (typeof item === "function" ? item() : item))
|
||||
);
|
||||
this.#animationCount -= 1;
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
}
|
||||
@@ -1641,7 +1752,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
? tab.group.group
|
||||
: tab?.group;
|
||||
while (currentGroup) {
|
||||
const activeTabs = selectedTabs.filter((t) => currentGroup.tabs.includes(t));
|
||||
const activeTabs = selectedTabs.filter(t =>
|
||||
currentGroup.tabs.includes(t)
|
||||
);
|
||||
if (activeTabs.length) {
|
||||
if (currentGroup.collapsed) {
|
||||
if (currentGroup.hasAttribute("has-active")) {
|
||||
@@ -1696,7 +1809,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
for (let i = 0; i < groupItems.length; i++) {
|
||||
const { item, splitViewId } = groupItems[i];
|
||||
|
||||
itemsToShow.push(item);
|
||||
let itemVisible = item.visible;
|
||||
if (itemVisible) {
|
||||
itemsToShow.push(item);
|
||||
}
|
||||
|
||||
// Skip selected items
|
||||
if (selectedTabs.includes(item)) {
|
||||
@@ -1708,17 +1824,15 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!item.hasAttribute?.("folder-active")) {
|
||||
if (!itemsToHide.includes(item)) {
|
||||
itemsToHide.push(item);
|
||||
}
|
||||
if (!itemVisible && !itemsToHide.includes(item)) {
|
||||
itemsToHide.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: This is a hack to fix the animations not working properly
|
||||
this.styleCleanup(itemsToShow);
|
||||
itemsToHide.forEach((item) => {
|
||||
itemsToHide.forEach(item => {
|
||||
item.style.opacity = 0;
|
||||
item.style.height = 0;
|
||||
});
|
||||
@@ -1756,7 +1870,6 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
this.styleCleanup(itemsToHide);
|
||||
this.styleCleanup(selectedTabs);
|
||||
}
|
||||
|
||||
@@ -1766,7 +1879,9 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
const groupStart = group.groupStartElement;
|
||||
const tabsContainer = group.groupContainer;
|
||||
const heightContainer = expand ? 0 : this.#calculateHeightShift(tabsContainer, []);
|
||||
const heightContainer = expand
|
||||
? 0
|
||||
: this.#calculateHeightShift(tabsContainer, []);
|
||||
tabsContainer.style.overflow = "clip";
|
||||
|
||||
this.#createAnimation(
|
||||
@@ -1779,7 +1894,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
styleCleanup(items) {
|
||||
items.forEach((item) => {
|
||||
items.forEach(item => {
|
||||
item.style.removeProperty("opacity");
|
||||
item.style.removeProperty("height");
|
||||
});
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
content/browser/zen-components/ZenFolder.mjs (../../zen/folders/ZenFolder.mjs)
|
||||
content/browser/zen-components/ZenFolders.mjs (../../zen/folders/ZenFolders.mjs)
|
||||
content/browser/zen-styles/zen-folders.css (../../zen/folders/zen-folders.css)
|
||||
content/browser/zen-styles/zen-folders.css (../../zen/folders/zen-folders.css)
|
||||
|
||||
@@ -88,7 +88,6 @@ zen-folder {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
align-content: center;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
|
||||
@@ -266,8 +265,8 @@ zen-folder[collapsed] > .tab-group-container {
|
||||
}
|
||||
|
||||
#zen-folder-tabs-popup .zen-folder-tabs-list-search-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
margin: 10px 2px 10px 10px;
|
||||
-moz-context-properties: fill;
|
||||
fill: currentColor;
|
||||
@@ -275,8 +274,8 @@ zen-folder[collapsed] > .tab-group-container {
|
||||
}
|
||||
|
||||
.folders-tabs-list-item-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: var(--size-item-small);
|
||||
height: var(--size-item-small);
|
||||
flex-shrink: 0;
|
||||
margin-inline-end: 10px;
|
||||
margin-inline-start: 4px;
|
||||
|
||||
@@ -37,7 +37,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
ARC_HEIGHT_RATIO: 0.2, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
|
||||
});
|
||||
|
||||
#GLANCE_ANIMATION_DURATION = Services.prefs.getIntPref("zen.glance.animation-duration") / 1000;
|
||||
#GLANCE_ANIMATION_DURATION =
|
||||
Services.prefs.getIntPref("zen.glance.animation-duration") / 1000;
|
||||
|
||||
init() {
|
||||
this.#setupEventListeners();
|
||||
@@ -74,9 +75,13 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
menuitem.setAttribute("hidden", "true");
|
||||
menuitem.setAttribute("data-l10n-id", "zen-open-link-in-glance");
|
||||
|
||||
menuitem.addEventListener("command", () => this.openGlance({ url: gContextMenu.linkURL }));
|
||||
menuitem.addEventListener("command", () =>
|
||||
this.openGlance({ url: gContextMenu.linkURL })
|
||||
);
|
||||
|
||||
document.getElementById("context-sep-open").insertAdjacentElement("beforebegin", menuitem);
|
||||
document
|
||||
.getElementById("context-sep-open")
|
||||
.insertAdjacentElement("beforebegin", menuitem);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,7 +180,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
currentTab._selected = true;
|
||||
const newTab =
|
||||
existingTab ?? gBrowser.addTrustedTab(Services.io.newURI(url).spec, newTabOptions);
|
||||
existingTab ??
|
||||
gBrowser.addTrustedTab(Services.io.newURI(url).spec, newTabOptions);
|
||||
|
||||
this.#configureNewTab(newTab, currentTab, newUUID);
|
||||
this.#registerGlance(newTab, currentTab, newUUID);
|
||||
@@ -355,7 +361,11 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
this.#setAnimationState(true);
|
||||
const currentTab = ownerTab ?? gBrowser.selectedTab;
|
||||
const browserElement = this.#createBrowserElement(data.url, currentTab, existingTab);
|
||||
const browserElement = this.#createBrowserElement(
|
||||
data.url,
|
||||
currentTab,
|
||||
existingTab
|
||||
);
|
||||
|
||||
this.fillOverlay(browserElement);
|
||||
this.overlay.classList.add("zen-glance-overlay");
|
||||
@@ -386,7 +396,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
// until a better solution is found). If we do it inside the requestAnimationFrame,
|
||||
// we see flashing and if we do it directly, the animation does not play at all.
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve) => {
|
||||
return new Promise(async resolve => {
|
||||
// Recalculate location. When opening from pinned tabs,
|
||||
// view splitter doesn't catch if the tab is a glance tab or not.
|
||||
gZenViewSplitter.onLocationChange(browserElement);
|
||||
@@ -496,7 +506,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
const imageDataElement = this.#createGlancePreviewElement(data.elementData);
|
||||
this.browserWrapper.prepend(imageDataElement);
|
||||
this.#glances.get(this.#currentGlanceID).elementImageData = data.elementData;
|
||||
this.#glances.get(this.#currentGlanceID).elementImageData =
|
||||
data.elementData;
|
||||
|
||||
gZenUIManager.motion.animate(
|
||||
imageDataElement,
|
||||
@@ -518,7 +529,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @param {Browser} browserElement - The browser element
|
||||
*/
|
||||
#configureBrowserElement(browserElement) {
|
||||
const rect = window.windowUtils.getBoundsWithoutFlushing(this.browserWrapper.parentElement);
|
||||
const rect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
this.browserWrapper.parentElement
|
||||
);
|
||||
const minWidth = rect.width * 0.85;
|
||||
const minHeight = rect.height * 0.85;
|
||||
|
||||
@@ -574,7 +587,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.#animateParentBackground();
|
||||
gZenUIManager.motion
|
||||
.animate(this.browserWrapper, arcSequence, {
|
||||
duration: gZenUIManager.testingEnabled ? 0 : this.#GLANCE_ANIMATION_DURATION,
|
||||
duration: gZenUIManager.testingEnabled
|
||||
? 0
|
||||
: this.#GLANCE_ANIMATION_DURATION,
|
||||
ease: "easeInOut",
|
||||
})
|
||||
.then(() => {
|
||||
@@ -595,7 +610,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
// Calculate start and end positions based on direction
|
||||
let startPosition, endPosition;
|
||||
|
||||
const tabPanelsRect = window.windowUtils.getBoundsWithoutFlushing(gBrowser.tabpanels);
|
||||
const tabPanelsRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
gBrowser.tabpanels
|
||||
);
|
||||
|
||||
const widthPercent = 0.85;
|
||||
if (direction === "opening") {
|
||||
@@ -658,12 +675,17 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
// First, create the main animation steps
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
const progress = i / steps;
|
||||
const eased = direction === "opening" ? easeOutBack(progress) : easeOutCubic(progress);
|
||||
const eased =
|
||||
direction === "opening"
|
||||
? easeOutBack(progress)
|
||||
: easeOutCubic(progress);
|
||||
|
||||
// Calculate size interpolation
|
||||
const currentWidth = startPosition.width + (endPosition.width - startPosition.width) * eased;
|
||||
const currentWidth =
|
||||
startPosition.width + (endPosition.width - startPosition.width) * eased;
|
||||
const currentHeight =
|
||||
startPosition.height + (endPosition.height - startPosition.height) * eased;
|
||||
startPosition.height +
|
||||
(endPosition.height - startPosition.height) * eased;
|
||||
|
||||
// Calculate position on arc
|
||||
const distanceX = endPosition.x - startPosition.x;
|
||||
@@ -671,7 +693,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
const x = startPosition.x + distanceX * eased;
|
||||
const y =
|
||||
startPosition.y + distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
||||
startPosition.y +
|
||||
distanceY * eased +
|
||||
arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
||||
|
||||
sequence.top.push(`${y}px`);
|
||||
sequence.left.push(`${x}px`);
|
||||
@@ -707,13 +731,16 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
// Calculate available space for the arc
|
||||
const availableTopSpace = Math.min(startPosition.y, endPosition.y);
|
||||
const viewportHeight = window.innerHeight;
|
||||
const availableBottomSpace = viewportHeight - Math.max(startPosition.y, endPosition.y);
|
||||
const availableBottomSpace =
|
||||
viewportHeight - Math.max(startPosition.y, endPosition.y);
|
||||
|
||||
// Determine if we should arc downward or upward based on available space
|
||||
const shouldArcDownward = availableBottomSpace > availableTopSpace;
|
||||
|
||||
// Use the space in the direction we're arcing
|
||||
const availableSpace = shouldArcDownward ? availableBottomSpace : availableTopSpace;
|
||||
const availableSpace = shouldArcDownward
|
||||
? availableBottomSpace
|
||||
: availableTopSpace;
|
||||
|
||||
// Limit arc height to a percentage of the available space
|
||||
const arcHeight = Math.min(
|
||||
@@ -792,12 +819,17 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
return;
|
||||
}
|
||||
|
||||
const browserSidebarContainer = this.#currentParentTab?.linkedBrowser?.closest(
|
||||
".browserSidebarContainer"
|
||||
const browserSidebarContainer =
|
||||
this.#currentParentTab?.linkedBrowser?.closest(
|
||||
".browserSidebarContainer"
|
||||
);
|
||||
const sidebarButtons = this.browserWrapper.querySelector(
|
||||
".zen-glance-sidebar-container"
|
||||
);
|
||||
const sidebarButtons = this.browserWrapper.querySelector(".zen-glance-sidebar-container");
|
||||
|
||||
if (this.#handleConfirmationTimeout(onTabClose, hasFocused, sidebarButtons)) {
|
||||
if (
|
||||
this.#handleConfirmationTimeout(onTabClose, hasFocused, sidebarButtons)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -851,8 +883,15 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @returns {boolean} True if should return early
|
||||
*/
|
||||
#handleConfirmationTimeout(onTabClose, hasFocused, sidebarButtons) {
|
||||
if (onTabClose && hasFocused && !this.#confirmationTimeout && sidebarButtons) {
|
||||
const cancelButton = sidebarButtons.querySelector(".zen-glance-sidebar-close");
|
||||
if (
|
||||
onTabClose &&
|
||||
hasFocused &&
|
||||
!this.#confirmationTimeout &&
|
||||
sidebarButtons
|
||||
) {
|
||||
const cancelButton = sidebarButtons.querySelector(
|
||||
".zen-glance-sidebar-close"
|
||||
);
|
||||
cancelButton.setAttribute("waitconfirmation", true);
|
||||
this.#confirmationTimeout = setTimeout(() => {
|
||||
cancelButton.removeAttribute("waitconfirmation");
|
||||
@@ -871,7 +910,12 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @param {Element} sidebarButtons - The sidebar buttons
|
||||
* @param {string} setNewID - New glance ID to set
|
||||
*/
|
||||
#animateGlanceClosing(onTabClose, browserSidebarContainer, sidebarButtons, setNewID) {
|
||||
#animateGlanceClosing(
|
||||
onTabClose,
|
||||
browserSidebarContainer,
|
||||
sidebarButtons,
|
||||
setNewID
|
||||
) {
|
||||
if (this.closingGlance) {
|
||||
return;
|
||||
}
|
||||
@@ -976,14 +1020,19 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @returns {Promise} Promise that resolves when complete
|
||||
*/
|
||||
#executeClosingAnimation(setNewID, onTabClose) {
|
||||
return new Promise((resolve) => {
|
||||
const originalPosition = this.#glances.get(this.#currentGlanceID).originalPosition;
|
||||
const elementImageData = this.#glances.get(this.#currentGlanceID).elementImageData;
|
||||
return new Promise(resolve => {
|
||||
const originalPosition = this.#glances.get(
|
||||
this.#currentGlanceID
|
||||
).originalPosition;
|
||||
const elementImageData = this.#glances.get(
|
||||
this.#currentGlanceID
|
||||
).elementImageData;
|
||||
|
||||
this.#addElementPreview(elementImageData);
|
||||
|
||||
// Create curved closing animation sequence
|
||||
const closingData = this.#createClosingDataFromOriginalPosition(originalPosition);
|
||||
const closingData =
|
||||
this.#createClosingDataFromOriginalPosition(originalPosition);
|
||||
const arcSequence = this.#createGlanceArcSequence(closingData, "closing");
|
||||
|
||||
gZenUIManager.motion
|
||||
@@ -993,7 +1042,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
})
|
||||
.then(() => {
|
||||
// Remove element preview after closing animation
|
||||
const elementPreview = this.browserWrapper.querySelector(".zen-glance-element-preview");
|
||||
const elementPreview = this.browserWrapper.querySelector(
|
||||
".zen-glance-element-preview"
|
||||
);
|
||||
if (elementPreview) {
|
||||
elementPreview.remove();
|
||||
}
|
||||
@@ -1031,7 +1082,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
*/
|
||||
#addElementPreview(elementImageData) {
|
||||
if (elementImageData) {
|
||||
const imageDataElement = this.#createGlancePreviewElement(elementImageData);
|
||||
const imageDataElement =
|
||||
this.#createGlancePreviewElement(elementImageData);
|
||||
this.browserWrapper.prepend(imageDataElement);
|
||||
}
|
||||
}
|
||||
@@ -1081,7 +1133,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.overlay.classList.remove("zen-glance-overlay");
|
||||
gBrowser
|
||||
._getSwitcher()
|
||||
.setTabStateNoAction(lastCurrentTab, gBrowser.AsyncTabSwitcher.STATE_UNLOADED);
|
||||
.setTabStateNoAction(
|
||||
lastCurrentTab,
|
||||
gBrowser.AsyncTabSwitcher.STATE_UNLOADED
|
||||
);
|
||||
|
||||
if (!this.#currentParentTab.selected) {
|
||||
this.#currentParentTab._visuallySelected = false;
|
||||
@@ -1107,7 +1162,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
this.#ignoreClose = true;
|
||||
lastCurrentTab.dispatchEvent(new Event("GlanceClose", { bubbles: true }));
|
||||
gBrowser.removeTab(lastCurrentTab, { animate: true, skipPermitUnload: true });
|
||||
gBrowser.removeTab(lastCurrentTab, {
|
||||
animate: true,
|
||||
skipPermitUnload: true,
|
||||
});
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
}
|
||||
|
||||
@@ -1192,7 +1250,12 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.#removeParentBackground(parentHasBrowser, browserContainer);
|
||||
|
||||
if (!justAnimateParent && this.overlay) {
|
||||
this.#resetGlanceStates(closeCurrentTab, closeParentTab, parentHasBrowser, browserContainer);
|
||||
this.#resetGlanceStates(
|
||||
closeCurrentTab,
|
||||
closeParentTab,
|
||||
parentHasBrowser,
|
||||
browserContainer
|
||||
);
|
||||
}
|
||||
|
||||
if (clearID) {
|
||||
@@ -1220,8 +1283,16 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @param {boolean} parentHasBrowser - Whether parent has browser
|
||||
* @param {Element} browserContainer - The browser container
|
||||
*/
|
||||
#resetGlanceStates(closeCurrentTab, closeParentTab, parentHasBrowser, browserContainer) {
|
||||
if (parentHasBrowser && !this.#currentParentTab.hasAttribute("split-view")) {
|
||||
#resetGlanceStates(
|
||||
closeCurrentTab,
|
||||
closeParentTab,
|
||||
parentHasBrowser,
|
||||
browserContainer
|
||||
) {
|
||||
if (
|
||||
parentHasBrowser &&
|
||||
!this.#currentParentTab.hasAttribute("split-view")
|
||||
) {
|
||||
if (closeParentTab) {
|
||||
browserContainer.classList.remove("deck-selected");
|
||||
}
|
||||
@@ -1258,7 +1329,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.quickOpenGlance();
|
||||
if (prevTab && prevTab.linkedBrowser) {
|
||||
prevTab.linkedBrowser.docShellIsActive = false;
|
||||
prevTab.linkedBrowser.closest(".browserSidebarContainer").classList.remove("deck-selected");
|
||||
prevTab.linkedBrowser
|
||||
.closest(".browserSidebarContainer")
|
||||
.classList.remove("deck-selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,7 +1357,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.#currentGlanceID && this.#currentGlanceID !== tab.getAttribute("glance-id")) {
|
||||
if (
|
||||
this.#currentGlanceID &&
|
||||
this.#currentGlanceID !== tab.getAttribute("glance-id")
|
||||
) {
|
||||
this.quickCloseGlance();
|
||||
}
|
||||
|
||||
@@ -1375,7 +1451,11 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @returns {boolean} True if valid
|
||||
*/
|
||||
#isValidGlanceUrl(urlSpec) {
|
||||
return urlSpec.startsWith("http") || urlSpec.startsWith("https") || urlSpec.startsWith("file");
|
||||
return (
|
||||
urlSpec.startsWith("http") ||
|
||||
urlSpec.startsWith("https") ||
|
||||
urlSpec.startsWith("file")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1465,10 +1545,14 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.#handleZenFolderPinning();
|
||||
gBrowser.moveTabAfter(this.#currentTab, this.#currentParentTab);
|
||||
|
||||
const browserRect = window.windowUtils.getBoundsWithoutFlushing(this.browserWrapper);
|
||||
const browserRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
this.browserWrapper
|
||||
);
|
||||
this.#prepareTabForFullOpen();
|
||||
|
||||
const sidebarButtons = this.browserWrapper.querySelector(".zen-glance-sidebar-container");
|
||||
const sidebarButtons = this.browserWrapper.querySelector(
|
||||
".zen-glance-sidebar-container"
|
||||
);
|
||||
if (sidebarButtons) {
|
||||
sidebarButtons.remove();
|
||||
}
|
||||
@@ -1493,7 +1577,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
*/
|
||||
#handleZenFolderPinning() {
|
||||
const isZenFolder = this.#currentParentTab?.group?.isZenFolder;
|
||||
if (Services.prefs.getBoolPref("zen.folders.owned-tabs-in-folder") && isZenFolder) {
|
||||
if (
|
||||
Services.prefs.getBoolPref("zen.folders.owned-tabs-in-folder") &&
|
||||
isZenFolder
|
||||
) {
|
||||
gBrowser.pinTab(this.#currentTab);
|
||||
}
|
||||
}
|
||||
@@ -1551,7 +1638,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @param {Event} event - The bookmark click event
|
||||
*/
|
||||
openGlanceForBookmark(event) {
|
||||
const activationMethod = Services.prefs.getStringPref("zen.glance.activation-method", "ctrl");
|
||||
const activationMethod = Services.prefs.getStringPref(
|
||||
"zen.glance.activation-method",
|
||||
"ctrl"
|
||||
);
|
||||
|
||||
if (!this.#isActivationKeyPressed(event, activationMethod)) {
|
||||
return;
|
||||
@@ -1590,7 +1680,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
*/
|
||||
#createGlanceDataFromBookmark(event) {
|
||||
const rect = window.windowUtils.getBoundsWithoutFlushing(event.target);
|
||||
const tabPanelRect = window.windowUtils.getBoundsWithoutFlushing(gBrowser.tabpanels);
|
||||
const tabPanelRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
gBrowser.tabpanels
|
||||
);
|
||||
// the bookmark is most likely outisde the tabpanel, so we need to give a negative number
|
||||
// so it can be corrected later
|
||||
// eslint-disable-next-line no-shadow
|
||||
@@ -1631,7 +1723,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
gZenViewSplitter.splitTabs([currentTab, currentParentTab], "vsep", 1);
|
||||
|
||||
const browserContainer = currentTab.linkedBrowser?.closest(".browserSidebarContainer");
|
||||
const browserContainer = currentTab.linkedBrowser?.closest(
|
||||
".browserSidebarContainer"
|
||||
);
|
||||
if (!gReduceMotion && browserContainer) {
|
||||
gZenViewSplitter.animateBrowserDrop(browserContainer);
|
||||
}
|
||||
@@ -1644,7 +1738,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
*/
|
||||
#handleZenFolderPinningForSplit(parentTab) {
|
||||
const isZenFolder = parentTab?.group?.isZenFolder;
|
||||
if (Services.prefs.getBoolPref("zen.folders.owned-tabs-in-folder") && isZenFolder) {
|
||||
if (
|
||||
Services.prefs.getBoolPref("zen.folders.owned-tabs-in-folder") &&
|
||||
isZenFolder
|
||||
) {
|
||||
gBrowser.pinTab(this.#currentTab);
|
||||
}
|
||||
}
|
||||
@@ -1657,7 +1754,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
*/
|
||||
getTabOrGlanceParent(tab) {
|
||||
if (tab?.hasAttribute("glance-id") && this.#glances) {
|
||||
const parentTab = this.#glances.get(tab.getAttribute("glance-id"))?.parentTab;
|
||||
const parentTab = this.#glances.get(
|
||||
tab.getAttribute("glance-id")
|
||||
)?.parentTab;
|
||||
if (parentTab) {
|
||||
return parentTab;
|
||||
}
|
||||
@@ -1702,7 +1801,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
if (currentGlanceID && oldGlanceID) {
|
||||
return (
|
||||
currentGlanceID === oldGlanceID && oldPanel.classList.contains("zen-glance-background")
|
||||
currentGlanceID === oldGlanceID &&
|
||||
oldPanel.classList.contains("zen-glance-background")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1752,7 +1852,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @param {Tab} parentTab - Parent tab
|
||||
*/
|
||||
#openGlanceForSearch(currentTab, parentTab) {
|
||||
const browserRect = window.windowUtils.getBoundsWithoutFlushing(gBrowser.tabbox);
|
||||
const browserRect = window.windowUtils.getBoundsWithoutFlushing(
|
||||
gBrowser.tabbox
|
||||
);
|
||||
const clickPosition = gZenUIManager._lastClickPosition || {
|
||||
clientX: browserRect.width / 2,
|
||||
clientY: browserRect.height / 2,
|
||||
|
||||
@@ -17,7 +17,9 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
}
|
||||
|
||||
async #initActivationMethod() {
|
||||
this.#activationMethod = await this.sendQuery("ZenGlance:GetActivationMethod");
|
||||
this.#activationMethod = await this.sendQuery(
|
||||
"ZenGlance:GetActivationMethod"
|
||||
);
|
||||
}
|
||||
|
||||
#ensureOnlyKeyModifiers(event) {
|
||||
@@ -114,7 +116,9 @@ export class ZenGlanceChild extends JSWindowActorChild {
|
||||
return;
|
||||
}
|
||||
this.sendAsyncMessage("ZenGlance:CloseGlance", {
|
||||
hasFocused: this.contentWindow.document.activeElement !== this.contentWindow.document.body,
|
||||
hasFocused:
|
||||
this.contentWindow.document.activeElement !==
|
||||
this.contentWindow.document.body,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ export class ZenGlanceParent extends JSWindowActorParent {
|
||||
async receiveMessage(message) {
|
||||
switch (message.name) {
|
||||
case "ZenGlance:GetActivationMethod": {
|
||||
return Services.prefs.getStringPref("zen.glance.activation-method", "ctrl");
|
||||
return Services.prefs.getStringPref(
|
||||
"zen.glance.activation-method",
|
||||
"ctrl"
|
||||
);
|
||||
}
|
||||
case "ZenGlance:OpenGlance": {
|
||||
this.openGlance(this.browsingContext.topChromeWindow, message.data);
|
||||
@@ -23,11 +26,14 @@ export class ZenGlanceParent extends JSWindowActorParent {
|
||||
onTabClose: true,
|
||||
...message.data,
|
||||
};
|
||||
this.browsingContext.topChromeWindow.gZenGlanceManager.closeGlance(params);
|
||||
this.browsingContext.topChromeWindow.gZenGlanceManager.closeGlance(
|
||||
params
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "ZenGlance:RecordLinkClickData": {
|
||||
this.browsingContext.topChromeWindow.gZenGlanceManager.lastLinkClickData = message.data;
|
||||
this.browsingContext.topChromeWindow.gZenGlanceManager.lastLinkClickData =
|
||||
message.data;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
content/browser/zen-components/ZenGlanceManager.mjs (../../zen/glance/ZenGlanceManager.mjs)
|
||||
content/browser/zen-styles/zen-glance.css (../../zen/glance/zen-glance.css)
|
||||
content/browser/zen-styles/zen-glance.css (../../zen/glance/zen-glance.css)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
export function openGlanceOnTab(window, callback, close = true) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve) => {
|
||||
return new Promise(async resolve => {
|
||||
window.gZenGlanceManager
|
||||
.openGlance({
|
||||
url: "https://example.com",
|
||||
@@ -13,7 +13,7 @@ export function openGlanceOnTab(window, callback, close = true) {
|
||||
width: 0,
|
||||
height: 0,
|
||||
})
|
||||
.then(async (glanceTab) => {
|
||||
.then(async glanceTab => {
|
||||
await callback(glanceTab);
|
||||
if (close) {
|
||||
window.gZenGlanceManager
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
}
|
||||
|
||||
& toolbarbutton {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: var(--size-item-large);
|
||||
height: var(--size-item-large);
|
||||
background: color-mix(in srgb, light-dark(rgb(24, 24, 24), rgb(231, 231, 231)) 96%, var(--zen-primary-color));
|
||||
transition:
|
||||
background 0.05s ease,
|
||||
@@ -65,7 +65,7 @@
|
||||
width: fit-content;
|
||||
& label {
|
||||
display: block;
|
||||
max-width: 0px;
|
||||
max-width: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at https://mozilla.org/MPL/2.0/. -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="192" height="192">
|
||||
<path d="M0 0 C46.53 0 93.06 0 141 0 C140.31337286 6.17964422 139.55249061 11.27288504 137.70605469 17.05029297 C137.47297387 17.80257864 137.23989305 18.55486431 136.99974918 19.32994652 C136.23144234 21.80315256 135.45168558 24.27258703 134.671875 26.7421875 C134.12437759 28.49738282 133.57765617 30.25282037 133.03166199 32.00848389 C131.87637142 35.71831589 130.71622139 39.42657597 129.55197144 43.13360596 C127.74764855 48.8788063 125.95370897 54.62720979 124.16235352 60.37646484 C123.86778165 61.32180147 123.57320978 62.2671381 123.26971149 63.24112129 C122.67820023 65.13942545 122.08671887 67.03773892 121.49526787 68.93606186 C120.61596105 71.75702774 119.73559404 74.57766091 118.85499573 77.39822388 C113.93371601 93.16794093 109.12231506 108.96839561 104.39160156 124.79638672 C104.15798416 125.57612854 103.92436676 126.35587036 103.68367004 127.15924072 C103.08515835 129.15844483 102.48956633 131.15852242 101.89428711 133.15869141 C101 136 101 136 100 138 C53.47 138 6.94 138 -41 138 C-40.30154873 133.1108411 -39.57595592 129.15411541 -38.15258789 124.53222656 C-37.57916405 122.65642914 -37.57916405 122.65642914 -36.99415588 120.74273682 C-36.57039663 119.37534329 -36.14656076 118.0079735 -35.72265625 116.640625 C-35.27348999 115.1778587 -34.82480765 113.71494372 -34.37657166 112.25189209 C-33.18301778 108.36047716 -31.98331296 104.47098593 -30.78216553 100.58190918 C-29.63602455 96.86810525 -28.49491032 93.15276556 -27.35351562 89.4375 C-24.23585848 79.29161092 -21.11791678 69.14580929 -18 59 C-12.06 39.53 -6.12 20.06 0 0 Z " fill="#C00002" transform="translate(51,54)"/>
|
||||
<path d="M0 0 C18.3328319 -0.77792059 36.66127963 -1.35606988 55.00715542 -1.70980167 C63.53040721 -1.87858134 72.04320263 -2.10845198 80.55981445 -2.48950195 C142.46067644 -5.20608208 142.46067644 -5.20608208 159.53827381 9.52021503 C166.76889916 16.3955246 173.28323862 24.18336817 178 33 C178 34.32 178 35.64 178 37 C159.57187597 37.07007601 141.14378652 37.12298126 122.71555805 37.15543652 C114.15904092 37.17090649 105.60260658 37.19199848 97.04614258 37.22631836 C89.58846853 37.25621675 82.13085443 37.27557406 74.67312211 37.28226548 C70.72416302 37.28617701 66.77537545 37.29537225 62.82647133 37.31719017 C59.10909816 37.33756234 55.39196707 37.34383237 51.67454338 37.33932304 C49.66086617 37.34054104 47.64721527 37.35667936 45.63360596 37.3732605 C44.43192276 37.36913651 43.23023956 37.36501251 41.99214172 37.36076355 C40.42831993 37.36491162 40.42831993 37.36491162 38.83290577 37.36914349 C32.93264951 36.60030705 29.62184448 32.77709579 25.875 28.5 C19.58131594 21.47164064 12.89888852 14.86095567 6.14794922 8.2734375 C5.35146973 7.48839844 4.55499023 6.70335937 3.734375 5.89453125 C3.01475586 5.19175049 2.29513672 4.48896973 1.55371094 3.76489258 C0 2 0 2 0 0 Z " fill="#C00002" transform="translate(14,0)"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.6 KiB |
@@ -111,16 +111,15 @@ const defaultKeyboardGroups = {
|
||||
"zen-bidi-switch-direction-shortcut",
|
||||
"zen-screenshot-shortcut",
|
||||
],
|
||||
devTools: [
|
||||
/*Filled automatically*/
|
||||
],
|
||||
devTools: [/*Filled automatically*/],
|
||||
};
|
||||
|
||||
const fixedL10nIds = {
|
||||
cmd_findPrevious: "zen-search-find-again-shortcut-prev",
|
||||
"Browser:ReloadSkipCache": "zen-nav-reload-shortcut-skip-cache",
|
||||
cmd_close: "zen-close-tab-shortcut",
|
||||
"History:RestoreLastClosedTabOrWindowOrSession": "zen-restore-last-closed-tab-shortcut",
|
||||
"History:RestoreLastClosedTabOrWindowOrSession":
|
||||
"zen-restore-last-closed-tab-shortcut",
|
||||
};
|
||||
|
||||
const ZEN_MAIN_KEYSET_ID = "mainKeyset";
|
||||
@@ -191,7 +190,13 @@ export class nsKeyShortcutModifiers {
|
||||
}
|
||||
|
||||
// used to avoid any future changes to the object
|
||||
static fromObject({ ctrl = false, alt = false, shift = false, meta = false, accel = false }) {
|
||||
static fromObject({
|
||||
ctrl = false,
|
||||
alt = false,
|
||||
shift = false,
|
||||
meta = false,
|
||||
accel = false,
|
||||
}) {
|
||||
return new nsKeyShortcutModifiers(ctrl, alt, shift, meta, accel);
|
||||
}
|
||||
|
||||
@@ -270,7 +275,9 @@ export class nsKeyShortcutModifiers {
|
||||
}
|
||||
|
||||
areAnyActive() {
|
||||
return this.#control || this.#alt || this.#shift || this.#meta || this.#accel;
|
||||
return (
|
||||
this.#control || this.#alt || this.#shift || this.#meta || this.#accel
|
||||
);
|
||||
}
|
||||
|
||||
get control() {
|
||||
@@ -385,7 +392,9 @@ class KeyShortcut {
|
||||
KeyShortcut.sanitizeL10nId(key.getAttribute("data-l10n-id")),
|
||||
key.getAttribute("id")
|
||||
),
|
||||
nsKeyShortcutModifiers.parseFromXHTMLAttribute(key.getAttribute("modifiers")),
|
||||
nsKeyShortcutModifiers.parseFromXHTMLAttribute(
|
||||
key.getAttribute("modifiers")
|
||||
),
|
||||
key.getAttribute("command"),
|
||||
key.getAttribute("data-l10n-id"),
|
||||
key.getAttribute("disabled") == "true",
|
||||
@@ -589,7 +598,11 @@ class KeyShortcut {
|
||||
}
|
||||
|
||||
isUserEditable() {
|
||||
if (!this.#id || this.#internal || (this.#group == FIREFOX_SHORTCUTS_GROUP && this.#disabled)) {
|
||||
if (
|
||||
!this.#id ||
|
||||
this.#internal ||
|
||||
(this.#group == FIREFOX_SHORTCUTS_GROUP && this.#disabled)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -653,10 +666,14 @@ class nsZenKeyboardShortcutsLoader {
|
||||
let keySet = document.getElementById(ZEN_MAIN_KEYSET_ID);
|
||||
let newShortcutList = [];
|
||||
|
||||
const correctDefaultShortcut = (shortcut) => {
|
||||
const correctDefaultShortcut = shortcut => {
|
||||
if (shortcut.getID() === "key_savePage") {
|
||||
shortcut.setModifiers(
|
||||
nsKeyShortcutModifiers.fromObject({ accel: true, alt: true, shift: true })
|
||||
nsKeyShortcutModifiers.fromObject({
|
||||
accel: true,
|
||||
alt: true,
|
||||
shift: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -801,7 +818,10 @@ class nsZenKeyboardShortcutsLoader {
|
||||
}
|
||||
let parsed = KeyShortcut.parseFromXHTML(key, { group: "devTools" });
|
||||
// Move "inspector" shortcut to use "L" key instead of "I"
|
||||
if (parsed.getID() == "key_inspector" || parsed.getID() == "key_inspectorMac") {
|
||||
if (
|
||||
parsed.getID() == "key_inspector" ||
|
||||
parsed.getID() == "key_inspectorMac"
|
||||
) {
|
||||
parsed.setNewBinding("L");
|
||||
}
|
||||
newShortcutList.push(parsed);
|
||||
@@ -869,7 +889,7 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
fillDefaultIfNotPresent(data) {
|
||||
for (let shortcut of nsZenKeyboardShortcutsLoader.zenGetDefaultShortcuts()) {
|
||||
// If it has an ID and we dont find it in the data, we add it
|
||||
if (shortcut.getID() && !data.find((s) => s.getID() == shortcut.getID())) {
|
||||
if (shortcut.getID() && !data.find(s => s.getID() == shortcut.getID())) {
|
||||
data.push(shortcut);
|
||||
}
|
||||
}
|
||||
@@ -919,7 +939,8 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
// detection for internal keys was not working properly, so every internal
|
||||
// shortcut was being saved as a user-editable shortcut.
|
||||
// This migration will fix this issue.
|
||||
const defaultShortcuts = nsZenKeyboardShortcutsLoader.zenGetDefaultShortcuts();
|
||||
const defaultShortcuts =
|
||||
nsZenKeyboardShortcutsLoader.zenGetDefaultShortcuts();
|
||||
// Get the default shortcut, compare the id and set the internal flag if needed
|
||||
for (let shortcut of data) {
|
||||
for (let defaultShortcut of defaultShortcuts) {
|
||||
@@ -933,7 +954,7 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
// Migrate from 3 to 4
|
||||
// In this new version, we are just removing the 'zen-toggle-sidebar' shortcut
|
||||
// since it's not used anymore.
|
||||
data = data.filter((shortcut) => shortcut.getID() != "zen-toggle-sidebar");
|
||||
data = data.filter(shortcut => shortcut.getID() != "zen-toggle-sidebar");
|
||||
}
|
||||
if (version < 5) {
|
||||
// Migrate from 4 to 5
|
||||
@@ -968,11 +989,14 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
if (version < 7) {
|
||||
// Migrate from 6 to 7
|
||||
// In this new version, we add the devtools shortcuts
|
||||
const listener = (event) => {
|
||||
const listener = event => {
|
||||
event.stopPropagation();
|
||||
|
||||
const devToolsShortcuts = nsZenKeyboardShortcutsLoader.zenGetDefaultDevToolsShortcuts();
|
||||
gZenKeyboardShortcutsManager.updatedDefaultDevtoolsShortcuts(devToolsShortcuts);
|
||||
const devToolsShortcuts =
|
||||
nsZenKeyboardShortcutsLoader.zenGetDefaultDevToolsShortcuts();
|
||||
gZenKeyboardShortcutsManager.updatedDefaultDevtoolsShortcuts(
|
||||
devToolsShortcuts
|
||||
);
|
||||
|
||||
window.removeEventListener("zen-devtools-keyset-added", listener);
|
||||
};
|
||||
@@ -991,7 +1015,11 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
"C",
|
||||
"",
|
||||
ZEN_OTHER_SHORTCUTS_GROUP,
|
||||
nsKeyShortcutModifiers.fromObject({ accel: true, shift: true, alt: true }),
|
||||
nsKeyShortcutModifiers.fromObject({
|
||||
accel: true,
|
||||
shift: true,
|
||||
alt: true,
|
||||
}),
|
||||
"cmd_zenCopyCurrentURLMarkdown",
|
||||
"zen-text-action-copy-url-markdown-shortcut"
|
||||
)
|
||||
@@ -1001,7 +1029,9 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
// Migrate from version 8 to 9
|
||||
// Due to security concerns, replace "code:" actions with corresponding <command> IDs
|
||||
// we also remove 'zen-toggle-web-panel' since it's not used anymore
|
||||
data = data.filter((shortcut) => shortcut.getID() != "zen-toggle-web-panel");
|
||||
data = data.filter(
|
||||
shortcut => shortcut.getID() != "zen-toggle-web-panel"
|
||||
);
|
||||
for (let shortcut of data) {
|
||||
if (shortcut.getAction()?.startsWith("code:")) {
|
||||
const id = shortcut.getID();
|
||||
@@ -1084,7 +1114,11 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
// - Remove the built-in "Open File" keybinding; menu item remains available
|
||||
// - Remove default "Bookmark All Tabs" keybinding (Ctrl+Shift+D) to avoid conflict
|
||||
// - Remove "Stop" keybinding to avoid conflict with Firefox's built-in binding
|
||||
const shouldBeEmptyShortcuts = ["openFileKb", "bookmarkAllTabsKb", "key_stop"];
|
||||
const shouldBeEmptyShortcuts = [
|
||||
"openFileKb",
|
||||
"bookmarkAllTabsKb",
|
||||
"key_stop",
|
||||
];
|
||||
for (let shortcut of data) {
|
||||
if (shouldBeEmptyShortcuts.includes(shortcut.getID?.())) {
|
||||
shortcut.shouldBeEmpty = true;
|
||||
@@ -1092,7 +1126,9 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
}
|
||||
|
||||
// Also remove zen-compact-mode-show-toolbar
|
||||
data = data.filter((shortcut) => shortcut.getID() != "zen-compact-mode-show-toolbar");
|
||||
data = data.filter(
|
||||
shortcut => shortcut.getID() != "zen-compact-mode-show-toolbar"
|
||||
);
|
||||
}
|
||||
|
||||
if (version < 13) {
|
||||
@@ -1130,7 +1166,10 @@ class nsZenKeyboardShortcutsVersioner {
|
||||
let emptySplitFound = false,
|
||||
undoCloseWindowFound = false;
|
||||
for (let shortcut of data) {
|
||||
if (shortcut.getID() == "zen-new-empty-split-view" && AppConstants.platform == "macosx") {
|
||||
if (
|
||||
shortcut.getID() == "zen-new-empty-split-view" &&
|
||||
AppConstants.platform == "macosx"
|
||||
) {
|
||||
if (shortcut.getKeyName() == "+") {
|
||||
shortcut.setNewBinding("*");
|
||||
}
|
||||
@@ -1179,7 +1218,10 @@ window.gZenKeyboardShortcutsManager = {
|
||||
"zen.keyboard.shortcuts.disable-mainkeyset-clear",
|
||||
false
|
||||
);
|
||||
window.addEventListener("zen-devtools-keyset-added", this._hasAddedDevtoolShortcuts.bind(this));
|
||||
window.addEventListener(
|
||||
"zen-devtools-keyset-added",
|
||||
this._hasAddedDevtoolShortcuts.bind(this)
|
||||
);
|
||||
|
||||
this.init();
|
||||
},
|
||||
@@ -1188,11 +1230,14 @@ window.gZenKeyboardShortcutsManager = {
|
||||
if (this.inBrowserView) {
|
||||
const loadedShortcuts = await this._loadSaved();
|
||||
|
||||
this._currentShortcutList = this.versioner.fixedKeyboardShortcuts(loadedShortcuts);
|
||||
this._currentShortcutList =
|
||||
this.versioner.fixedKeyboardShortcuts(loadedShortcuts);
|
||||
this._applyShortcuts();
|
||||
|
||||
await this._saveShortcuts();
|
||||
window.dispatchEvent(new Event("ZenKeyboardShortcutsReady", { bubbles: true }));
|
||||
window.dispatchEvent(
|
||||
new Event("ZenKeyboardShortcutsReady", { bubbles: true })
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1210,12 +1255,16 @@ window.gZenKeyboardShortcutsManager = {
|
||||
try {
|
||||
return KeyShortcut.parseFromSaved(data);
|
||||
} catch (e) {
|
||||
console.error("Zen CKS: Error parsing saved shortcuts. Resetting to defaults...", e);
|
||||
console.error(
|
||||
"Zen CKS: Error parsing saved shortcuts. Resetting to defaults...",
|
||||
e
|
||||
);
|
||||
gNotificationBox.appendNotification(
|
||||
"zen-shortcuts-corrupted",
|
||||
{
|
||||
label: { "l10n-id": "zen-shortcuts-corrupted" },
|
||||
image: "chrome://browser/skin/notification-icons/persistent-storage-blocked.svg",
|
||||
image:
|
||||
"chrome://browser/skin/notification-icons/persistent-storage-blocked.svg",
|
||||
priority: gNotificationBox.PRIORITY_WARNING_HIGH,
|
||||
},
|
||||
[]
|
||||
@@ -1325,12 +1374,17 @@ window.gZenKeyboardShortcutsManager = {
|
||||
if (!browser.gZenKeyboardShortcutsManager?._hasToLoadDevtools) {
|
||||
return;
|
||||
}
|
||||
let devtoolsKeyset = browser.gZenKeyboardShortcutsManager.getZenDevtoolsKeyset(browser);
|
||||
let devtoolsKeyset =
|
||||
browser.gZenKeyboardShortcutsManager.getZenDevtoolsKeyset(browser);
|
||||
for (let key of this._currentShortcutList) {
|
||||
if (key.getGroup() != "devTools") {
|
||||
continue;
|
||||
}
|
||||
if (nsZenKeyboardShortcutsLoader.IGNORED_DEVTOOLS_SHORTCUTS.includes(key.getID())) {
|
||||
if (
|
||||
nsZenKeyboardShortcutsLoader.IGNORED_DEVTOOLS_SHORTCUTS.includes(
|
||||
key.getID()
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const originalKey = browser.document.getElementById(key.getID());
|
||||
@@ -1345,7 +1399,9 @@ window.gZenKeyboardShortcutsManager = {
|
||||
}
|
||||
}
|
||||
|
||||
const originalDevKeyset = browser.document.getElementById(ZEN_DEVTOOLS_KEYSET_ID);
|
||||
const originalDevKeyset = browser.document.getElementById(
|
||||
ZEN_DEVTOOLS_KEYSET_ID
|
||||
);
|
||||
originalDevKeyset.after(devtoolsKeyset);
|
||||
},
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
NetUtil: "resource://gre/modules/NetUtil.sys.mjs",
|
||||
DeferredTask: "resource://gre/modules/DeferredTask.sys.mjs",
|
||||
NetworkHelper: "resource://devtools/shared/network-observer/NetworkHelper.sys.mjs",
|
||||
NetworkHelper:
|
||||
"resource://devtools/shared/network-observer/NetworkHelper.sys.mjs",
|
||||
});
|
||||
|
||||
export class nsZenLiveFolderProvider {
|
||||
@@ -135,7 +136,10 @@ export class nsZenLiveFolderProvider {
|
||||
userContextId = space.containerTabId || 0;
|
||||
}
|
||||
}
|
||||
const principal = Services.scriptSecurityManager.createContentPrincipal(uri, { userContextId });
|
||||
const principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
uri,
|
||||
{ userContextId }
|
||||
);
|
||||
|
||||
const channel = lazy.NetUtil.newChannel({
|
||||
uri,
|
||||
@@ -146,7 +150,8 @@ export class nsZenLiveFolderProvider {
|
||||
contentPolicyType: Ci.nsIContentPolicy.TYPE_SAVEAS_DOWNLOAD,
|
||||
loadingPrincipal: principal,
|
||||
securityFlags:
|
||||
Ci.nsILoadInfo.SEC_REQUIRE_CORS_INHERITS_SEC_CONTEXT | Ci.nsILoadInfo.SEC_COOKIES_INCLUDE,
|
||||
Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL |
|
||||
Ci.nsILoadInfo.SEC_COOKIES_INCLUDE,
|
||||
triggeringPrincipal: principal,
|
||||
}).QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
@@ -168,7 +173,7 @@ export class nsZenLiveFolderProvider {
|
||||
byteChunks.push(lazy.NetUtil.readInputStream(stream, count));
|
||||
}
|
||||
},
|
||||
onStartRequest: (request) => {
|
||||
onStartRequest: request => {
|
||||
const http = request.QueryInterface(Ci.nsIHttpChannel);
|
||||
|
||||
try {
|
||||
@@ -181,7 +186,10 @@ export class nsZenLiveFolderProvider {
|
||||
contentType = http.getResponseHeader("content-type");
|
||||
} catch (ex) {}
|
||||
|
||||
if (contentType && !lazy.NetworkHelper.isTextMimeType(contentType.split(";")[0].trim())) {
|
||||
if (
|
||||
contentType &&
|
||||
!lazy.NetworkHelper.isTextMimeType(contentType.split(";")[0].trim())
|
||||
) {
|
||||
request.cancel(Cr.NS_ERROR_FILE_UNKNOWN_TYPE);
|
||||
}
|
||||
|
||||
@@ -214,7 +222,9 @@ export class nsZenLiveFolderProvider {
|
||||
|
||||
let effectiveCharset = "utf-8";
|
||||
|
||||
const mimeType = contentType ? contentType.split(";")[0].trim().toLowerCase() : "";
|
||||
const mimeType = contentType
|
||||
? contentType.split(";")[0].trim().toLowerCase()
|
||||
: "";
|
||||
if (mimeType === "text/html") {
|
||||
effectiveCharset = this.sniffCharset(bytes, headerCharset);
|
||||
} else if (headerCharset) {
|
||||
@@ -251,7 +261,12 @@ export class nsZenLiveFolderProvider {
|
||||
*/
|
||||
sniffCharset(bytes, headerCharset = "") {
|
||||
// 1. BOM detection (highest priority)
|
||||
if (bytes.length >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) {
|
||||
if (
|
||||
bytes.length >= 3 &&
|
||||
bytes[0] === 0xef &&
|
||||
bytes[1] === 0xbb &&
|
||||
bytes[2] === 0xbf
|
||||
) {
|
||||
return "utf-8";
|
||||
}
|
||||
if (bytes.length >= 2) {
|
||||
@@ -268,7 +283,9 @@ export class nsZenLiveFolderProvider {
|
||||
// is more likely to be correct.
|
||||
try {
|
||||
const headLen = Math.min(bytes.length, 8192);
|
||||
const head = new TextDecoder("windows-1252").decode(bytes.subarray(0, headLen));
|
||||
const head = new TextDecoder("windows-1252").decode(
|
||||
bytes.subarray(0, headLen)
|
||||
);
|
||||
|
||||
const metaCharsetRegex = /<meta\s+charset\s*=\s*["']?([a-z0-9_-]+)/i;
|
||||
let match = head.match(metaCharsetRegex);
|
||||
|
||||
@@ -51,7 +51,9 @@ class nsZenLiveFoldersManager {
|
||||
}
|
||||
|
||||
for (const provider of providers) {
|
||||
const module = ChromeUtils.importESModule(provider.path, { global: "current" });
|
||||
const module = ChromeUtils.importESModule(provider.path, {
|
||||
global: "current",
|
||||
});
|
||||
const ProviderClass = module[provider.module];
|
||||
this.registry.set(ProviderClass.type, ProviderClass);
|
||||
}
|
||||
@@ -114,7 +116,8 @@ class nsZenLiveFoldersManager {
|
||||
#onTabDismiss(event) {
|
||||
const itemIdAttr = "zen-live-folder-item-id";
|
||||
const itemId =
|
||||
event.target.getAttribute(itemIdAttr) || event.detail?.getAttribute?.(itemIdAttr);
|
||||
event.target.getAttribute(itemIdAttr) ||
|
||||
event.detail?.getAttribute?.(itemIdAttr);
|
||||
|
||||
if (itemId) {
|
||||
if (event.type === "TabUngrouped") {
|
||||
@@ -139,7 +142,9 @@ class nsZenLiveFoldersManager {
|
||||
|
||||
#onActionButtonClick(event) {
|
||||
const liveFolderId = event.target.getAttribute("live-folder-action");
|
||||
this.getFolder(liveFolderId)?.onActionButtonClick(event.target.getAttribute("data-l10n-id"));
|
||||
this.getFolder(liveFolderId)?.onActionButtonClick(
|
||||
event.target.getAttribute("data-l10n-id")
|
||||
);
|
||||
}
|
||||
|
||||
#onTabGroupRemoved(event) {
|
||||
@@ -317,7 +322,9 @@ class nsZenLiveFoldersManager {
|
||||
|
||||
// Remove the dismissed items associated with the folder from the set
|
||||
this.dismissedItems = new Set(
|
||||
Array.from(this.dismissedItems).filter((itemId) => !itemId.startsWith(prefix))
|
||||
Array.from(this.dismissedItems).filter(
|
||||
itemId => !itemId.startsWith(prefix)
|
||||
)
|
||||
);
|
||||
|
||||
if (deleteFolder) {
|
||||
@@ -351,7 +358,9 @@ class nsZenLiveFoldersManager {
|
||||
}
|
||||
|
||||
// itemid -> id:itemid
|
||||
const itemIds = new Set(items.map((item) => this.#makeCompositeId(liveFolder.id, item.id)));
|
||||
const itemIds = new Set(
|
||||
items.map(item => this.#makeCompositeId(liveFolder.id, item.id))
|
||||
);
|
||||
|
||||
const outdatedTabs = [];
|
||||
const existingItemIds = new Set();
|
||||
@@ -377,27 +386,45 @@ class nsZenLiveFoldersManager {
|
||||
|
||||
// Remove the dismissed items that are no longer in the given list
|
||||
for (const dismissedItemId of this.dismissedItems) {
|
||||
if (dismissedItemId.startsWith(`${liveFolder.id}:`) && !itemIds.has(dismissedItemId)) {
|
||||
if (
|
||||
dismissedItemId.startsWith(`${liveFolder.id}:`) &&
|
||||
!itemIds.has(dismissedItemId)
|
||||
) {
|
||||
this.dismissedItems.delete(dismissedItemId);
|
||||
}
|
||||
}
|
||||
|
||||
let userContextId = 0;
|
||||
let space = folder.ownerGlobal.gZenWorkspaces.getWorkspaceFromId(
|
||||
folder.getAttribute("zen-workspace-id")
|
||||
);
|
||||
if (space) {
|
||||
userContextId = space.containerTabId || 0;
|
||||
}
|
||||
|
||||
// Only add the items that are not already in the folder and was not dismissed by the user
|
||||
const newItems = items
|
||||
.filter((item) => {
|
||||
.filter(item => {
|
||||
const compositeId = this.#makeCompositeId(liveFolder.id, item.id);
|
||||
return !existingItemIds.has(compositeId) && !this.dismissedItems.has(compositeId);
|
||||
return (
|
||||
!existingItemIds.has(compositeId) &&
|
||||
!this.dismissedItems.has(compositeId)
|
||||
);
|
||||
})
|
||||
.map((item) => {
|
||||
.map(item => {
|
||||
const tab = this.window.gBrowser.addTrustedTab(item.url, {
|
||||
createLazyBrowser: true,
|
||||
inBackground: true,
|
||||
skipAnimation: true,
|
||||
noInitialLabel: true,
|
||||
lazyTabTitle: item.title,
|
||||
userContextId,
|
||||
});
|
||||
// createLazyBrowser can't be pinned by default
|
||||
this.window.gBrowser.pinTab(tab);
|
||||
if (userContextId) {
|
||||
tab.setAttribute("zenDefaultUserContextId", "true");
|
||||
}
|
||||
if (item.icon) {
|
||||
this.window.gBrowser.setIcon(tab, item.icon);
|
||||
if (tab.linkedBrowser) {
|
||||
@@ -406,7 +433,10 @@ class nsZenLiveFoldersManager {
|
||||
});
|
||||
}
|
||||
}
|
||||
tab.setAttribute("zen-live-folder-item-id", this.#makeCompositeId(liveFolder.id, item.id));
|
||||
tab.setAttribute(
|
||||
"zen-live-folder-item-id",
|
||||
this.#makeCompositeId(liveFolder.id, item.id)
|
||||
);
|
||||
if (item.subtitle) {
|
||||
tab.setAttribute("zen-show-sublabel", item.subtitle);
|
||||
const tabLabel = tab.querySelector(".zen-tab-sublabel");
|
||||
@@ -459,7 +489,10 @@ class nsZenLiveFoldersManager {
|
||||
if (!this.window) {
|
||||
return null;
|
||||
}
|
||||
const folder = lazy.ZenWindowSync.getItemFromWindow(this.window, liveFolder.id);
|
||||
const folder = lazy.ZenWindowSync.getItemFromWindow(
|
||||
this.window,
|
||||
liveFolder.id
|
||||
);
|
||||
if (folder?.isZenFolder) {
|
||||
return folder;
|
||||
}
|
||||
@@ -504,7 +537,7 @@ class nsZenLiveFoldersManager {
|
||||
let data = [];
|
||||
for (let [id, liveFolder] of this.liveFolders) {
|
||||
const prefix = `${id}:`;
|
||||
const dismissedItems = Array.from(this.dismissedItems).filter((itemId) =>
|
||||
const dismissedItems = Array.from(this.dismissedItems).filter(itemId =>
|
||||
itemId.startsWith(prefix)
|
||||
);
|
||||
|
||||
@@ -556,7 +589,7 @@ class nsZenLiveFoldersManager {
|
||||
continue;
|
||||
}
|
||||
|
||||
const folder = folders.find((x) => x.id === entry.id);
|
||||
const folder = folders.find(x => x.id === entry.id);
|
||||
if (!folder) {
|
||||
// No point restore if the live folder can't find its folder
|
||||
continue;
|
||||
@@ -573,7 +606,7 @@ class nsZenLiveFoldersManager {
|
||||
liveFolder.tabsState = entry.tabsState || [];
|
||||
liveFolder.state.lastErrorId = entry.data.state.lastErrorId;
|
||||
if (entry.dismissedItems && Array.isArray(entry.dismissedItems)) {
|
||||
entry.dismissedItems.forEach((id) => this.dismissedItems.add(id));
|
||||
entry.dismissedItems.forEach(id => this.dismissedItems.add(id));
|
||||
}
|
||||
|
||||
liveFolder.start();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user