From 9c11e19db8fb543b071acc7aa8740c72c7f53451 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 31 Jan 2025 18:40:50 +0100 Subject: [PATCH 01/62] Update macOS signing process to use production environment and improve profile handling --- .github/workflows/macos-universal-release-build.yml | 2 +- configs/macos/mozconfig | 10 ---------- src/tools/signing/macos/mach_commands-py.patch | 11 +++++++---- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/.github/workflows/macos-universal-release-build.yml b/.github/workflows/macos-universal-release-build.yml index 69a380992..cbabcb77d 100644 --- a/.github/workflows/macos-universal-release-build.yml +++ b/.github/workflows/macos-universal-release-build.yml @@ -191,7 +191,7 @@ jobs: run: | cd engine # TODO: Change it to "production" once we figure out the issue with the webauth - ./mach macos-sign -v -r -c "release" -e "production-without-restricted" -a "./obj-x86_64-apple-darwin/dist/${{ env.APP_NAME }}.app" --rcodesign-p12-file zenCert.p12 --rcodesign-p12-password-file zenpCertPassword.passwd + ./mach macos-sign -v -r -c "release" -e "production" -a "./obj-x86_64-apple-darwin/dist/${{ env.APP_NAME }}.app" --rcodesign-p12-file zenCert.p12 --rcodesign-p12-password-file zenpCertPassword.passwd - name: Create DMG run: | diff --git a/configs/macos/mozconfig b/configs/macos/mozconfig index 34ee5c6a5..1cc417ced 100644 --- a/configs/macos/mozconfig +++ b/configs/macos/mozconfig @@ -8,17 +8,7 @@ export MOZ_MACBUNDLE_NAME="Zen Browser.app" # override LTO settings # TODO: Dont -export MOZ_LTO=cross,thin -ac_add_options --enable-lto=cross,thin -if test "$ZEN_RELEASE"; then - if test "$ZEN_GA_DISABLE_PGO"; then - export ZEN_DUMMY=1 - else - export MOZ_PGO=1 - ac_add_options MOZ_PGO=1 - fi -fi if test "$SURFER_COMPAT" = "x86_64"; then ac_add_options --target=x86_64-apple-darwin diff --git a/src/tools/signing/macos/mach_commands-py.patch b/src/tools/signing/macos/mach_commands-py.patch index c292d3be4..c61833a08 100644 --- a/src/tools/signing/macos/mach_commands-py.patch +++ b/src/tools/signing/macos/mach_commands-py.patch @@ -1,5 +1,5 @@ diff --git a/tools/signing/macos/mach_commands.py b/tools/signing/macos/mach_commands.py -index a513ad723805459c194d27b42dac68e9babba468..be74acbfe16a4eb389bc7d0ba32820b82fe2819c 100644 +index a513ad723805459c194d27b42dac68e9babba468..3a08bb0987f9d6cf01c05f8ebb56efa91a5b9d0e 100644 --- a/tools/signing/macos/mach_commands.py +++ b/tools/signing/macos/mach_commands.py @@ -37,7 +37,6 @@ from mozbuild.base import MachCommandConditions as conditions @@ -10,15 +10,18 @@ index a513ad723805459c194d27b42dac68e9babba468..be74acbfe16a4eb389bc7d0ba32820b8 ) @CommandArgument( "-v", -@@ -342,6 +341,7 @@ def macos_sign( +@@ -342,6 +341,10 @@ def macos_sign( cs_reset_cmd = ["find", app, "-exec", "codesign", "--remove-signature", "{}", ";"] run(command_context, cs_reset_cmd, capture_output=not verbose_arg) -+ run(command_context, ["mv", "./embedded.provisionprofile", os.path.join(app, "Contents")], capture_output=not verbose_arg) ++ originProfile = os.path.join(os.curdir, "embedded.provisionprofile") ++ endProfile = os.path.join(app, "Contents", "embedded.provisionprofile") ++ print(f"ZEN: Moving {originProfile} to {endProfile}") ++ os.rename(originProfile, endProfile) if use_rcodesign_arg is True: sign_with_rcodesign( command_context, -@@ -567,7 +567,7 @@ def sign_with_rcodesign( +@@ -567,7 +570,7 @@ def sign_with_rcodesign( # input path and its options are specified as standard arguments. ctx.log(logging.INFO, "macos-sign", {}, "Signing with rcodesign") From 8afb8ee204d85b940e02d4a3f236599ea7743435 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 14 Mar 2025 18:29:22 +0100 Subject: [PATCH 02/62] update @zen-browser/surfer dependency to version 1.10.5 and refine media controls styling --- package-lock.json | 8 +-- package.json | 2 +- .../base/content/zen-media-player.inc.xhtml | 14 +--- .../content/zen-styles/zen-media-controls.css | 68 ++++++------------- .../zen-components/ZenMediaController.mjs | 13 ---- src/browser/themes/shared/zen-icons/icons.css | 6 +- .../shared/zen-icons/lin/media-next.svg | 2 +- .../shared/zen-icons/lin/media-previous.svg | 2 +- 8 files changed, 29 insertions(+), 86 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae338762c..8dbd35d31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@zen-browser/surfer": "^1.10.4" + "@zen-browser/surfer": "^1.10.5" }, "devDependencies": { "husky": "^9.1.7", @@ -288,9 +288,9 @@ "license": "MIT" }, "node_modules/@zen-browser/surfer": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.10.4.tgz", - "integrity": "sha512-xDXJYgbJTfNpM+LsJDJ81VCotwIBY3CItrD7Y1hPqf84Ino/sTqy/QuHQCVqZU3StewAvVuV68MWnaiY9ytlMA==", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@zen-browser/surfer/-/surfer-1.10.5.tgz", + "integrity": "sha512-jpGArye02C6M65qy0b5kZWzDBO5sh/BY6k2otC1keAjICm9lxELsh5ELRz0tVQ6kwrBUC3yE4uP8jzUgQdCuCg==", "dependencies": { "@resvg/resvg-js": "^1.4.0", "async-icns": "^1.0.2", diff --git a/package.json b/package.json index af630a45e..3c3a548ac 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "homepage": "https://github.com/zen-browser/core#readme", "dependencies": { - "@zen-browser/surfer": "^1.10.4" + "@zen-browser/surfer": "^1.10.5" }, "devDependencies": { "husky": "^9.1.7", diff --git a/src/browser/base/content/zen-media-player.inc.xhtml b/src/browser/base/content/zen-media-player.inc.xhtml index 8295bf40a..a60b65c47 100644 --- a/src/browser/base/content/zen-media-player.inc.xhtml +++ b/src/browser/base/content/zen-media-player.inc.xhtml @@ -5,30 +5,18 @@ hidden="true"> - - - - - - - - - - - image'); - this.mediaServiceTitle = document.querySelector('#zen-media-service-title'); this.mediaProgressBar = document.querySelector('#zen-media-progress-bar'); this.mediaCurrentTime = document.querySelector('#zen-media-current-time'); this.mediaDuration = document.querySelector('#zen-media-duration'); @@ -106,15 +102,6 @@ class ZenMediaController { this.mediaControlBar.classList.add('playing'); } - // Have it displayed as e.g. youtube.com - let host = this._currentBrowser._originalURI.displayHost; - if (host.startsWith('www.')) host = host.slice(4); - // note: we might have subdomains, so we need to split the host - const [service, ...tld] = host.split('.'); - this.mediaServiceTitle.querySelector('.service').textContent = service; - this.mediaServiceTitle.querySelector('.tld').textContent = '.' + tld.join('.'); - - this.mediaServiceIcon.src = this._currentBrowser.mIconURL; this.mediaFocusButton.style.listStyleImage = `url(${this._currentBrowser.mIconURL})`; this.mediaTitle.textContent = metadata.title || ''; diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index 5a2baba6a..b6a47e67d 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -1179,8 +1179,6 @@ menupopup > menuitem:is([type='checkbox']) .menu-iconic-left { list-style-image: url('close.svg') !important; } -#zen-media-controls-toolbar:hover { - #zen-media-focus-button { - list-style-image: url('screen.svg') !important; - } +#zen-media-focus-button:hover { + list-style-image: url('screen.svg') !important; } diff --git a/src/browser/themes/shared/zen-icons/lin/media-next.svg b/src/browser/themes/shared/zen-icons/lin/media-next.svg index 0bf9db593..81bb40717 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-next.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-next.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-previous.svg b/src/browser/themes/shared/zen-icons/lin/media-previous.svg index 1175b9c3f..118f55f3e 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-previous.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-previous.svg @@ -1 +1 @@ - + From 0da5653fef000d1156418edc9662dde354fd2e7d Mon Sep 17 00:00:00 2001 From: UnownPlain <38232575+UnownPlain@users.noreply.github.com> Date: Fri, 14 Mar 2025 19:08:11 +0000 Subject: [PATCH 03/62] Fix files paths in release notes generation --- .../workflows/src/generate_release_notes.sh | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/.github/workflows/src/generate_release_notes.sh b/.github/workflows/src/generate_release_notes.sh index 21758086d..ac4e4c55e 100644 --- a/.github/workflows/src/generate_release_notes.sh +++ b/.github/workflows/src/generate_release_notes.sh @@ -67,33 +67,38 @@ cat << EOF >> "release_notes.md" EOF generate_checksum() { - local file=$1 - if [ -f "$file" ]; then - echo "Generating checksum for $file" - sha256sum "$file" | awk '{print $1 " " $2}' >> "release_notes.md" - else - echo "Warning: $file not found, skipping checksum" + local pattern=$1 + echo "Generating checksum for $pattern" + sha256sum $pattern 2> /dev/null | awk '{sub(".*/", "", $2); print $1 " " $2}' >> "release_notes.md" + if [ ${PIPESTATUS[0]} -ne 0 ]; then + echo "Warning: No files found matching $pattern, skipping checksum." fi } files=( - "./zen.source.tar.zst" - "./zen.linux-x86_64.tar.xz" - "./zen.linux-aarch64.tar.xz" - "./zen-x86_64.AppImage" - "./zen-x86_64.AppImage.zsync" - "./zen-aarch64.AppImage" - "./zen-aarch64.AppImage.zsync" + "./zen.source.tar.zst/*" + "./zen.linux-x86_64.tar.xz/*" + "./zen.linux-aarch64.tar.xz/*" + "./zen-x86_64.AppImage/*" + "./zen-x86_64.AppImage.zsync/*" + "./zen-aarch64.AppImage/*" + "./zen-aarch64.AppImage.zsync/*" "./.github/workflows/object/windows-x64-signed-x86_64/zen.win-x86_64.zip" + "./zen.win-x86_64.zip/*" "./.github/workflows/object/windows-x64-signed-arm64/zen.win-arm64.zip" - "./linux.mar" - "./linux-aarch64.mar" + "./zen.win-arm64.zip/*" + "./linux.mar/*" + "./linux-aarch64.mar/*" "./.github/workflows/object/windows-x64-signed-x86_64/windows.mar" + "./windows.mar/*" "./.github/workflows/object/windows-x64-signed-arm64/windows-arm64.mar" - "./macos.mar" + "./windows-arm64.mar/*" + "./macos.mar/*" "./.github/workflows/object/windows-x64-signed-x86_64/zen.installer.exe" + "./zen.installer.exe/*" "./.github/workflows/object/windows-x64-signed-arm64/zen.installer-arm64.exe" - "./zen.macos-universal.dmg" + "./zen.installer-arm64.exe/*" + "./zen.macos-universal.dmg/*" ) for file in "${files[@]}"; do From f6f561841c8b7a60ca50905043ae846292f755d8 Mon Sep 17 00:00:00 2001 From: Pham Minh Triet <92496972+Nanome203@users.noreply.github.com> Date: Sat, 15 Mar 2025 02:37:06 +0700 Subject: [PATCH 04/62] make installation guide on other linux distros less confusing Signed-off-by: Pham Minh Triet <92496972+Nanome203@users.noreply.github.com> --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 537d574ee..74d0b8778 100644 --- a/README.md +++ b/README.md @@ -96,16 +96,18 @@ brew install --cask zen-browser yay -S zen-browser-bin ``` -##### Other Linux distributions (AppImage with automated system integration) +##### Other Linux distributions (Tarball or AppImage) -- `native` tarball install: - `bash <(curl -s https://updates.zen-browser.app/install.sh)` - -- `zsync` is required for the Update feature of the script below +- `Tarball` install: +```sh +bash <(curl -s https://updates.zen-browser.app/install.sh)` +``` +- `AppImage` install: ```sh bash <(curl https://updates.zen-browser.app/appimage.sh) ``` +> AppImage install requires `zsync` for the Update feature - Again, if you don't see your OS listed above, that's because we already have it in our [downloads page](https://zen-browser.app/download)! 🔄 From 481976a35371f018b730627e91d9818005b4c99a Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 14 Mar 2025 20:54:19 +0100 Subject: [PATCH 05/62] refactor media controls styling and improve workspace tab switching logic --- .../content/zen-styles/zen-media-controls.css | 39 +++++++------------ .../base/zen-components/ZenWorkspaces.mjs | 9 +++-- .../tabbrowser/content/tabbrowser-js.patch | 11 +++++- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index 83a2d6802..98eb009b2 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -1,5 +1,5 @@ #zen-media-controls-toolbar { - --progress-height: 5px; + --progress-height: 4px; --button-spacing: 2px; display: flex; @@ -50,8 +50,8 @@ &::-moz-range-thumb { background: var(--zen-primary-color); border: none; - width: 14px; - height: 14px; + width: calc(var(--progress-height) * 2.5); + height:calc(var(--progress-height) * 2.5); border-radius: 50%; cursor: pointer; } @@ -84,7 +84,7 @@ top: -50%; left: 50%; transform: translateX(-50%); - z-index: -1; + z-index: 0; pointer-events: none; } @@ -93,21 +93,7 @@ transition: opacity 0.2s ease, transform 0.2s ease; - - @container (max-width: 185px) { - width: 0; - height: 0; - opacity: 0; - padding: 0; - margin-right: -10%; - transform: translateX(-20px); - transition: margin 0.15s ease-in-out; - } - - @container (min-width: 185px) { - opacity: 1; - transform: translateX(0); - } + position: relative; } toolbaritem { @@ -119,7 +105,7 @@ bottom: 0; padding: 4px; border-radius: var(--border-radius-medium); - background: light-dark(rgb(255, 255, 255), rgb(11, 11, 11)) !important; + background: light-dark(rgb(255, 255, 255), rgb(7, 7, 7)) !important; width: 100%; box-shadow: 0 0 10px rgba(0, 0, 0, 0.05); } @@ -127,13 +113,13 @@ .show-on-hover { max-height: 0; opacity: 0; - transform: translateY(5px); + transform: translateY(10px); padding: 0 6px; transition: - max-height 0.15s ease-in-out, - opacity 0.15s ease-in-out, - transform 0.1s ease-in-out, - padding 0.1s ease-in-out; + max-height 0.2s ease-out, + opacity 0.2s ease-out, + transform 0.2s ease-out, + padding 0.2s ease-out; } #zen-media-current-time, @@ -190,11 +176,13 @@ } #zen-media-info-vbox { + transition-delay: 0.01s; & label { width: 100%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; + min-height: 16px; } } @@ -210,6 +198,7 @@ flex-grow: 1; height: 1.1rem; align-items: center; + padding-top: 0px; } #zen-media-controls-hbox { diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 03c18e9aa..e70833a60 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -2373,9 +2373,12 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { async switchIfNeeded(browser, i) { const tab = gBrowser.getTabForBrowser(browser); - const workspaceId = tab.getAttribute('zen-workspace-id'); - if (!tab.hasAttribute('zen-essential') && workspaceId !== this.activeWorkspace) { - await this.changeWorkspace({ uuid: workspaceId }); + await this.switchTabIfNeeded(tab); + } + + async switchTabIfNeeded(tab) { + if (!tab.hasAttribute('zen-essential') && tab.getAttribute('zen-workspace-id') !== this.activeWorkspace) { + await this.changeWorkspace({ uuid: tab.getAttribute('zen-workspace-id') }); } gBrowser.selectedTab = tab; } diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index d288a20db..00517a651 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..cd3ad53dbe399383178d0eff459ad72079b02024 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991bacb7b545 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -578,6 +578,15 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..cd3ad53dbe399383178d0eff459ad720 if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } +@@ -6513,7 +6661,7 @@ + // preventDefault(). It will still raise the window if appropriate. + break; + } +- this.selectedTab = tab; ++ ZenWorkspaces.switchTabIfNeeded(tab); + window.focus(); + aEvent.preventDefault(); + break; @@ -7415,6 +7563,7 @@ aWebProgress.isTopLevel ) { From 89243d03cddee58cdb9a7169bdf27f55740c242b Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 14 Mar 2025 23:06:18 +0100 Subject: [PATCH 06/62] refactor media controls event handling and improve styling --- .../content/zen-styles/zen-media-controls.css | 8 ++-- .../zen-components/ZenMediaController.mjs | 48 ++++++++++++------- src/browser/base/zen-components/moz.build | 7 +++ 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index 98eb009b2..93a4c9167 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -51,7 +51,7 @@ background: var(--zen-primary-color); border: none; width: calc(var(--progress-height) * 2.5); - height:calc(var(--progress-height) * 2.5); + height: calc(var(--progress-height) * 2.5); border-radius: 50%; cursor: pointer; } @@ -66,10 +66,11 @@ .show-on-hover { max-height: 50px; padding: 2px 6px; - padding-top: 4px; + padding-top: 6px; margin-bottom: 0; opacity: 1; transform: translateY(0); + pointer-events: auto; } } @@ -115,6 +116,7 @@ opacity: 0; transform: translateY(10px); padding: 0 6px; + pointer-events: none; transition: max-height 0.2s ease-out, opacity 0.2s ease-out, @@ -198,7 +200,7 @@ flex-grow: 1; height: 1.1rem; align-items: center; - padding-top: 0px; + padding-top: 0px !important; } #zen-media-controls-hbox { diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 9f4c6938b..3b43e7a5f 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -24,6 +24,12 @@ class ZenMediaController { this.mediaFocusButton = document.querySelector('#zen-media-focus-button'); this.mediaProgressBarContainer = document.querySelector('#zen-media-progress-hbox'); + this.onPositionstateChange = this._onPositionstateChange.bind(this); + this.onPlaybackstateChange = this._onPlaybackstateChange.bind(this); + this.onSupportedKeysChange = this._onSupportedKeysChange.bind(this); + this.onMetadataChange = this._onMetadataChange.bind(this); + this.onDeactivated = this._onDeactivated.bind(this); + window.addEventListener('TabSelect', (event) => { if (this._currentBrowser) { if (event.target.linkedBrowser.browserId === this._currentBrowser.browserId) { @@ -71,11 +77,11 @@ class ZenMediaController { deinitMediaController(mediaController) { if (!mediaController) return; - mediaController.onpositionstatechange = null; - mediaController.onplaybackstatechange = null; - mediaController.onsupportedkeyschange = null; - mediaController.onmetadatachange = null; - mediaController.ondeactivated = null; + mediaController.removeEventListener('positionstatechange', this.onPositionstateChange); + mediaController.removeEventListener('playbackstatechange', this.onPlaybackstateChange); + mediaController.removeEventListener('supportedkeyschange', this.onSupportedKeysChange); + mediaController.removeEventListener('metadatachange', this.onMetadataChange); + mediaController.removeEventListener('deactivated', this.onDeactivated); this._currentMediaController = null; this._currentBrowser = null; @@ -85,11 +91,17 @@ class ZenMediaController { this._mediaUpdateInterval = null; } - this.mediaControlBar.setAttribute('hidden', 'true'); + gZenUIManager.motion + .animate(this.mediaControlBar, { + opacity: [1, 0], + y: [0, 10], + }) + .then(() => { + this.mediaControlBar.setAttribute('hidden', 'true'); + gZenUIManager.updateTabsToolbar(); + }); this.mediaControlBar.removeAttribute('muted'); this.mediaControlBar.classList.remove('playing'); - - gZenUIManager.updateTabsToolbar(); } /** @@ -133,11 +145,11 @@ class ZenMediaController { this._currentBrowser = browser; } - mediaController.onpositionstatechange = this.onPositionstateChange.bind(this); - mediaController.onplaybackstatechange = this.onPlaybackstateChange.bind(this); - mediaController.onsupportedkeyschange = this.onSupportedKeysChange.bind(this); - mediaController.onmetadatachange = this.onMetadataChange.bind(this); - mediaController.ondeactivated = this.onDeactivated.bind(this); + mediaController.addEventListener('positionstatechange', this.onPositionstateChange); + mediaController.addEventListener('playbackstatechange', this.onPlaybackstateChange); + mediaController.addEventListener('supportedkeyschange', this.onSupportedKeysChange); + mediaController.addEventListener('metadatachange', this.onMetadataChange); + mediaController.addEventListener('deactivated', this.onDeactivated); const metadata = mediaController.getMetadata(); const positionState = mediaController.getPositionState(); @@ -148,7 +160,7 @@ class ZenMediaController { /** * @param {Event} event - The deactivation event. */ - onDeactivated(event) { + _onDeactivated(event) { if (event.target === this._currentMediaController) { this.deinitMediaController(event.target); } @@ -158,7 +170,7 @@ class ZenMediaController { * Updates playback state and UI based on changes. * @param {Event} event - The playback state change event. */ - onPlaybackstateChange(event) { + _onPlaybackstateChange(event) { this.mediaControlBar.classList.toggle('playing', event.target.isPlaying); } @@ -166,7 +178,7 @@ class ZenMediaController { * Updates supported keys in the UI. * @param {Event} event - The supported keys change event. */ - onSupportedKeysChange(event) { + _onSupportedKeysChange(event) { for (const key of this.supportedKeys) { const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`); button.disabled = !event.target.supportedKeys.includes(key); @@ -177,7 +189,7 @@ class ZenMediaController { * Updates position state and UI when the media position changes. * @param {Event} event - The position state change event. */ - onPositionstateChange(event) { + _onPositionstateChange(event) { if (event.target !== this._currentMediaController) return; this._currentPosition = event.position; @@ -242,7 +254,7 @@ class ZenMediaController { * Updates metadata in the UI. * @param {Event} event - The metadata change event. */ - onMetadataChange(event) { + _onMetadataChange(event) { const metadata = event.target.getMetadata(); this.mediaTitle.textContent = metadata.title || ''; this.mediaArtist.textContent = metadata.artist || ''; diff --git a/src/browser/base/zen-components/moz.build b/src/browser/base/zen-components/moz.build index cf1ec0a2d..a42e79f65 100644 --- a/src/browser/base/zen-components/moz.build +++ b/src/browser/base/zen-components/moz.build @@ -2,3 +2,10 @@ BROWSER_CHROME_MANIFESTS += [ "tests/browser.toml", ] + +FINAL_TARGET_FILES.actors += [ + "actors/ZenGlanceChild.sys.mjs", + "actors/ZenGlanceParent.sys.mjs", + "actors/ZenThemeMarketplaceChild.sys.mjs", + "actors/ZenThemeMarketplaceParent.sys.mjs", +] From d1098af7f0e132e942955e2c8fbbc995150e2976 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 14 Mar 2025 23:21:41 +0100 Subject: [PATCH 07/62] update installation instructions in README and refine CSS margins for compact mode --- README.md | 3 +++ src/browser/base/content/zen-styles/zen-compact-mode.css | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 74d0b8778..6d6e54745 100644 --- a/README.md +++ b/README.md @@ -99,14 +99,17 @@ yay -S zen-browser-bin ##### Other Linux distributions (Tarball or AppImage) - `Tarball` install: + ```sh bash <(curl -s https://updates.zen-browser.app/install.sh)` ``` + - `AppImage` install: ```sh bash <(curl https://updates.zen-browser.app/appimage.sh) ``` + > AppImage install requires `zsync` for the Update feature - Again, if you don't see your OS listed above, that's because we already have it in our [downloads page](https://zen-browser.app/download)! 🔄 diff --git a/src/browser/base/content/zen-styles/zen-compact-mode.css b/src/browser/base/content/zen-styles/zen-compact-mode.css index 3fede326d..7a1e14a72 100644 --- a/src/browser/base/content/zen-styles/zen-compact-mode.css +++ b/src/browser/base/content/zen-styles/zen-compact-mode.css @@ -16,10 +16,12 @@ #zen-tabbox-wrapper { /* Remove extra 1px of margine we have to add to the tabbox */ margin-left: 0 !important; + margin-right: 0 !important; } #zen-appcontent-wrapper { margin-left: var(--zen-element-separation) !important; + margin-right: var(--zen-element-separation) !important; & #tabbrowser-tabbox { margin-left: 0 !important; @@ -92,7 +94,7 @@ & .browserSidebarContainer { margin-left: 0 !important; - margin-right: var(--zen-element-separation) !important; + margin-right: 0 !important; } } From 8ea7b497ffaab4f413f7e01a9fd1bb59d0065a69 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sat, 15 Mar 2025 14:47:10 +0700 Subject: [PATCH 08/62] Fix media control progress bar jumping to 50% --- .../zen-components/ZenMediaController.mjs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 3b43e7a5f..34f27b1c3 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -209,25 +209,25 @@ class ZenMediaController { if (this._currentDuration >= 900_000) return this.mediaProgressBarContainer.setAttribute('hidden', 'true'); else this.mediaProgressBarContainer.removeAttribute('hidden'); + if (!this._currentDuration) return; + this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition); this.mediaDuration.textContent = this.formatSecondsToTime(this._currentDuration); this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100; - if (this._currentMediaController?.isPlaying) { - this._mediaUpdateInterval = setInterval(() => { - if (this._currentMediaController?.isPlaying) { - this._currentPosition += 1; - if (this._currentPosition > this._currentDuration) { - this._currentPosition = this._currentDuration; - } - this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition); - this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100; - } else { - clearInterval(this._mediaUpdateInterval); - this._mediaUpdateInterval = null; + this._mediaUpdateInterval = setInterval(() => { + if (this._currentMediaController?.isPlaying) { + this._currentPosition += 1; + if (this._currentPosition > this._currentDuration) { + this._currentPosition = this._currentDuration; } - }, 1000); - } + this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition); + this.mediaProgressBar.value = (this._currentPosition / this._currentDuration) * 100; + } else { + clearInterval(this._mediaUpdateInterval); + this._mediaUpdateInterval = null; + } + }, 1000); } /** From de14e8e935a7ec9a895ae17410ec2700a452cb83 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sat, 15 Mar 2025 16:11:35 +0700 Subject: [PATCH 09/62] Check if controller is active before activating --- src/browser/base/zen-components/ZenMediaController.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 34f27b1c3..890821800 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -138,7 +138,7 @@ class ZenMediaController { activateMediaControls(mediaController, browser) { this.updateMuteState(); - if (this._currentBrowser?.browserId === browser.browserId) return; + if (!mediaController.isActive || this._currentBrowser?.browserId === browser.browserId) return; else { this.deinitMediaController(this._currentMediaController); this._currentMediaController = mediaController; From e780eee207f76c8f1530e73ed7f04372163e1a2f Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 15 Mar 2025 10:24:44 +0100 Subject: [PATCH 10/62] refactor media controls animations and styles; add marquee effect for media title --- .../content/zen-images/note-indicator.svg | 16 +++---- .../content/zen-styles/zen-animations.css | 13 ++++++ .../content/zen-styles/zen-media-controls.css | 44 +++++++++---------- .../zen-components/ZenMediaController.mjs | 29 ++++++++---- 4 files changed, 63 insertions(+), 39 deletions(-) diff --git a/src/browser/base/content/zen-images/note-indicator.svg b/src/browser/base/content/zen-images/note-indicator.svg index 3e0a64c1f..053d78cb3 100644 --- a/src/browser/base/content/zen-images/note-indicator.svg +++ b/src/browser/base/content/zen-images/note-indicator.svg @@ -1,13 +1,13 @@ - + - + - + - + - + - + Date: Sat, 15 Mar 2025 13:40:09 +0100 Subject: [PATCH 12/62] refactor media controls layout and styles; improve visibility and responsiveness --- .../base/content/zen-media-player.inc.xhtml | 24 ++-- .../content/zen-styles/zen-media-controls.css | 48 ++++++-- .../zen-components/ZenMediaController.mjs | 4 +- .../base/zen-components/ZenWorkspaces.mjs | 25 ++-- .../tabbrowser/content/tabbrowser-js.patch | 112 ++++++++++-------- .../tabbrowser/content/tabs-js.patch | 87 ++++++-------- .../shared/zen-icons/lin/media-mute.svg | 2 +- .../shared/zen-icons/lin/media-unmute.svg | 2 +- 8 files changed, 169 insertions(+), 135 deletions(-) diff --git a/src/browser/base/content/zen-media-player.inc.xhtml b/src/browser/base/content/zen-media-player.inc.xhtml index a60b65c47..e2bc804d5 100644 --- a/src/browser/base/content/zen-media-player.inc.xhtml +++ b/src/browser/base/content/zen-media-player.inc.xhtml @@ -5,18 +5,20 @@ hidden="true"> - - - + + + + + + + + + + - - - - - = 900_000) return this.mediaProgressBarContainer.setAttribute('hidden', 'true'); - else this.mediaProgressBarContainer.removeAttribute('hidden'); + if (this._currentDuration >= 900_000) return this.mediaControlBar.setAttribute('media-position-hidden', 'true'); + else this.mediaControlBar.removeAttribute('media-position-hidden'); this.mediaCurrentTime.textContent = this.formatSecondsToTime(this._currentPosition); this.mediaDuration.textContent = this.formatSecondsToTime(this._currentDuration); diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index e70833a60..5af8f2bc7 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -36,10 +36,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { this._resolveInitialized = resolve; }); - promiseEmptyTabInitialized = new Promise((resolve) => { - this._resolveEmptyTabInitialized = resolve; - }); - workspaceIndicatorXUL = ` @@ -621,11 +617,15 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if (Services.prefs.getBoolPref('zen.workspaces.disable_empty_state_for_testing', false)) { return; } + if (this._initialTab) { + this.moveTabToWorkspace(this._initialTab, this.activeWorkspace); + gBrowser.selectedTab = this._initialTab; + gBrowser.moveTabTo(this._initialTab, 0, { forceStandaloneTab: true }); + this._initialTab._possiblyEmpty = false; + this._initialTab = null; + } const currentTab = gBrowser.selectedTab; let showed = false; - await this.promiseEmptyTabInitialized; - this._resolveEmptyTabInitialized = null; - this.promiseEmptyTabInitialized = null; if (currentTab.pinned) { this.selectEmptyTab(); try { @@ -640,8 +640,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if ( (currentTab.isEmpty && (currentTab.getAttribute('image') === gPageIcons[currentTabURL] || !currentTab.hasAttribute('image'))) || - currentTab.hasAttribute('zen-empty-tab') || - (currentTab._possibleEmptyTab && currentTab.isEmpty) + currentTab._possiblyEmpty ) { this.selectEmptyTab(); this._removedByStartupPage = true; @@ -654,6 +653,14 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { } } + handleInitialTab(tab, isEmpty) { + if (isEmpty) { + tab._possiblyEmpty = true; + } else { + this._initialTab = tab; + } + } + initIndicatorContextMenu(indicator) { const th = (event) => { event.preventDefault(); diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 00517a651..9faa921ef 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991bacb7b545 100644 +index 628aa6596627c85efe361fc1ece8fd58f7ee653e..06a4aae50ebe8a42d08d4689d8e80a63af1fa8a3 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -412,11 +412,50 @@ @@ -55,7 +55,15 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } return i; } -@@ -811,12 +850,13 @@ +@@ -546,6 +585,7 @@ + this.tabpanels.appendChild(panel); + + let tab = this.tabs[0]; ++ ZenWorkspaces.handleInitialTab(tab, (!remoteType || remoteType === E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE) && !Services.prefs.getBoolPref('zen.workspaces.disable_empty_state_for_testing', false)); + tab.linkedPanel = uniqueId; + this._selectedTab = tab; + this._selectedBrowser = browser; +@@ -811,12 +851,13 @@ } this.showTab(aTab); @@ -73,7 +81,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b this.moveTabTo(aTab, this.pinnedTabCount, { forceStandaloneTab: true }); } aTab.setAttribute("pinned", "true"); -@@ -830,12 +870,15 @@ +@@ -830,12 +871,15 @@ } if (this.tabContainer.verticalMode) { @@ -90,7 +98,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b }); } else { this.moveTabTo(aTab, this.pinnedTabCount - 1, { -@@ -1018,6 +1061,8 @@ +@@ -1018,6 +1062,8 @@ let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"]; @@ -99,7 +107,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if ( aIconURL && !aLoadingPrincipal && -@@ -1028,6 +1073,9 @@ +@@ -1028,6 +1074,9 @@ ); return; } @@ -109,7 +117,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b let browser = this.getBrowserForTab(aTab); browser.mIconURL = aIconURL; -@@ -1273,6 +1321,7 @@ +@@ -1273,6 +1322,7 @@ if (!this._previewMode) { newTab.recordTimeFromUnloadToReload(); newTab.updateLastAccessed(); @@ -117,7 +125,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b oldTab.updateLastAccessed(); // if this is the foreground window, update the last-seen timestamps. if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) { -@@ -1425,6 +1474,9 @@ +@@ -1425,6 +1475,9 @@ } let activeEl = document.activeElement; @@ -127,7 +135,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b // If focus is on the old tab, move it to the new tab. if (activeEl == oldTab) { newTab.focus(); -@@ -1748,7 +1800,7 @@ +@@ -1748,7 +1801,7 @@ } _setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) { @@ -136,7 +144,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b return false; } -@@ -1851,7 +1903,7 @@ +@@ -1851,7 +1904,7 @@ newIndex = this.selectedTab._tPos + 1; } @@ -145,7 +153,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b let browser; if (targetTab) { browser = this.getBrowserForTab(targetTab); -@@ -2108,6 +2160,7 @@ +@@ -2108,6 +2161,7 @@ uriIsAboutBlank, userContextId, skipLoad, @@ -153,7 +161,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } = {}) { let b = document.createXULElement("browser"); // Use the JSM global to create the permanentKey, so that if the -@@ -2181,8 +2234,7 @@ +@@ -2181,8 +2235,7 @@ // we use a different attribute name for this? b.setAttribute("name", name); } @@ -163,7 +171,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b b.setAttribute("transparent", "true"); } -@@ -2347,7 +2399,7 @@ +@@ -2347,7 +2400,7 @@ let panel = this.getPanel(browser); let uniqueId = this._generateUniquePanelID(); @@ -172,7 +180,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b aTab.linkedPanel = uniqueId; // Inject the into the DOM if necessary. -@@ -2406,8 +2458,8 @@ +@@ -2406,8 +2459,8 @@ // If we transitioned from one browser to two browsers, we need to set // hasSiblings=false on both the existing browser and the new browser. if (this.tabs.length == 2) { @@ -183,7 +191,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } else { aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1; } -@@ -2629,6 +2681,7 @@ +@@ -2629,6 +2682,7 @@ schemelessInput, hasValidUserGestureActivation = false, textDirectiveUserActivation = false, @@ -191,7 +199,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } = {} ) { // all callers of addTab that pass a params object need to pass -@@ -2639,6 +2692,12 @@ +@@ -2639,6 +2693,12 @@ ); } @@ -204,7 +212,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (!UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.start("browser.tabs.opening", "initting", window); } -@@ -2702,6 +2761,15 @@ +@@ -2702,6 +2762,15 @@ noInitialLabel, skipBackgroundNotify, }); @@ -220,7 +228,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (insertTab) { // insert the tab into the tab container in the correct position this._insertTabAtIndex(t, { -@@ -2726,6 +2794,7 @@ +@@ -2726,6 +2795,7 @@ initialBrowsingContextGroupId, openWindowInfo, skipLoad, @@ -228,7 +236,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b })); if (focusUrlBar) { -@@ -2845,6 +2914,9 @@ +@@ -2845,6 +2915,9 @@ } } @@ -238,7 +246,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b // Additionally send pinned tab events if (pinned) { this._notifyPinnedStatus(t); -@@ -2904,6 +2976,7 @@ +@@ -2904,6 +2977,7 @@ label = "", insertBefore = null, showCreateUI = false, @@ -246,7 +254,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } = {} ) { if (!tabs?.length) { -@@ -2918,7 +2991,12 @@ +@@ -2918,7 +2992,12 @@ id = `${Date.now()}-${Math.round(Math.random() * 100)}`; } let group = this._createTabGroup(id, color, false, label); @@ -260,7 +268,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b group, insertBefore?.group ?? insertBefore ); -@@ -3126,6 +3204,7 @@ +@@ -3126,6 +3205,7 @@ initialBrowsingContextGroupId, openWindowInfo, skipLoad, @@ -268,7 +276,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } ) { // If we don't have a preferred remote type, and we have a remote -@@ -3189,6 +3268,7 @@ +@@ -3189,6 +3269,7 @@ openWindowInfo, name, skipLoad, @@ -276,7 +284,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b }); } -@@ -3367,6 +3447,27 @@ +@@ -3367,6 +3448,27 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -304,7 +312,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3380,6 +3481,7 @@ +@@ -3380,6 +3482,7 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -312,7 +320,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3415,7 +3517,27 @@ +@@ -3415,7 +3518,27 @@ skipLoad: true, preferredRemoteType, }); @@ -341,7 +349,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (select) { tabToSelect = tab; } -@@ -3428,8 +3550,8 @@ +@@ -3428,8 +3551,8 @@ // inserted in the DOM. If the tab is not yet in the DOM, // just insert it in the right place from the start. if (!tab.parentNode) { @@ -352,17 +360,17 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b tab.toggleAttribute("pinned", true); this.tabContainer._invalidateCachedTabs(); // Then ensure all the tab open/pinning information is sent. -@@ -3504,6 +3626,9 @@ +@@ -3504,6 +3627,9 @@ this.selectedTab = tabToSelect; this.removeTab(leftoverTab); } + else { -+ this.selectedTab._possibleEmptyTab = true; // Not needed, but just in case. ++ this.selectedTab._possiblyEmpty = this.selectedTab.isEmpty; // Not needed, but just in case. + } if (tabs.length > 1 || !tabs[0].selected) { this._updateTabsAfterInsert(); -@@ -3693,7 +3818,7 @@ +@@ -3693,7 +3819,7 @@ // Ensure we have an index if one was not provided. if (typeof index != "number") { // Move the new tab after another tab if needed, to the end otherwise. @@ -371,7 +379,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if ( !bulkOrderedOpen && ((openerTab && -@@ -3736,18 +3861,18 @@ +@@ -3736,18 +3862,18 @@ // Ensure index is within bounds. if (tab.pinned) { @@ -394,7 +402,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (tabAfter && tabAfter.group == tabGroup) { // Place at the front of, or between tabs in, the same tab group this.tabContainer.insertBefore(tab, tabAfter); -@@ -4059,6 +4184,9 @@ +@@ -4059,6 +4185,9 @@ return; } @@ -404,7 +412,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b this.removeTabs(selectedTabs); } -@@ -4391,6 +4519,7 @@ +@@ -4391,6 +4520,7 @@ skipSessionStore, } = {} ) { @@ -412,7 +420,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (UserInteraction.running("browser.tabs.opening", window)) { UserInteraction.finish("browser.tabs.opening", window); } -@@ -4407,6 +4536,12 @@ +@@ -4407,6 +4537,12 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -425,7 +433,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4421,7 +4556,9 @@ +@@ -4421,7 +4557,9 @@ // frame created for it (for example, by updating the visually selected // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -436,7 +444,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -4435,7 +4572,6 @@ +@@ -4435,7 +4573,6 @@ TelemetryStopwatch.cancel("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); return; } @@ -444,7 +452,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b let lockTabSizing = !this.tabContainer.verticalMode && !aTab.pinned && -@@ -4574,14 +4710,14 @@ +@@ -4574,14 +4711,14 @@ !!this.tabsInCollapsedTabGroups.length; if ( aTab.visible && @@ -461,7 +469,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (closeWindow) { // We've already called beforeunload on all the relevant tabs if we get here, -@@ -4605,6 +4741,7 @@ +@@ -4605,6 +4742,7 @@ newTab = true; } @@ -469,7 +477,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b aTab._endRemoveArgs = [closeWindow, newTab]; // swapBrowsersAndCloseOther will take care of closing the window without animation. -@@ -4645,9 +4782,7 @@ +@@ -4645,9 +4783,7 @@ aTab._mouseleave(); if (newTab) { @@ -480,7 +488,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } else { TabBarVisibility.update(); } -@@ -4776,6 +4911,8 @@ +@@ -4776,6 +4912,8 @@ this.tabs[i]._tPos = i; } @@ -489,7 +497,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (!this._windowIsClosing) { if (wasPinned) { this.tabContainer._positionPinnedTabs(); -@@ -4994,7 +5131,7 @@ +@@ -4994,7 +5132,7 @@ !excludeTabs.has(aTab.owner) && Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") ) { @@ -498,7 +506,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } // Try to find a remaining tab that comes after the given tab -@@ -5016,7 +5153,7 @@ +@@ -5016,7 +5154,7 @@ } if (tab) { @@ -507,7 +515,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } // If no qualifying visible tab was found, see if there is a tab in -@@ -5434,10 +5571,10 @@ +@@ -5434,10 +5572,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); } @@ -520,7 +528,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -5675,7 +5812,7 @@ +@@ -5675,7 +5813,7 @@ // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -529,7 +537,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b } else { aIndex = Math.max(aIndex, this.pinnedTabCount); } -@@ -5685,10 +5822,17 @@ +@@ -5685,10 +5823,17 @@ this._handleTabMove(aTab, () => { let neighbor = this.tabs[aIndex]; @@ -549,7 +557,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b neighbor.after(aTab); } else { this.tabContainer.insertBefore(aTab, neighbor); -@@ -5697,7 +5841,7 @@ +@@ -5697,7 +5842,7 @@ } moveTabToGroup(aTab, aGroup) { @@ -558,7 +566,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b return; } if (aTab.group && aTab.group.id === aGroup.id) { -@@ -5721,6 +5865,10 @@ +@@ -5721,6 +5866,10 @@ moveActionCallback(); @@ -569,7 +577,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b // Clear tabs cache after moving nodes because the order of tabs may have // changed. this.tabContainer._invalidateCachedTabs(); -@@ -5771,7 +5919,7 @@ +@@ -5771,7 +5920,7 @@ createLazyBrowser, }; @@ -578,7 +586,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b if (aIndex < numPinned || (aTab.pinned && aIndex == numPinned)) { params.pinned = true; } -@@ -6513,7 +6661,7 @@ +@@ -6513,7 +6662,7 @@ // preventDefault(). It will still raise the window if appropriate. break; } @@ -587,7 +595,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b window.focus(); aEvent.preventDefault(); break; -@@ -7415,6 +7563,7 @@ +@@ -7415,6 +7564,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -595,7 +603,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; } -@@ -8381,7 +8530,7 @@ var TabContextMenu = { +@@ -8381,7 +8531,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext; @@ -604,7 +612,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b // Move Tab items let contextMoveTabOptions = document.getElementById( "context_moveTabOptions" -@@ -8414,7 +8563,7 @@ var TabContextMenu = { +@@ -8414,7 +8564,7 @@ var TabContextMenu = { let contextMoveTabToStart = document.getElementById("context_moveToStart"); let isFirstTab = tabsToMove[0] == visibleTabs[0] || @@ -613,7 +621,7 @@ index 628aa6596627c85efe361fc1ece8fd58f7ee653e..f8a96152feea39b55c9b9cd14dff991b contextMoveTabToStart.disabled = isFirstTab && allSelectedTabsAdjacent; document.getElementById("context_openTabInWindow").disabled = -@@ -8647,6 +8796,7 @@ var TabContextMenu = { +@@ -8647,6 +8797,7 @@ var TabContextMenu = { if (this.contextTab.multiselected) { gBrowser.removeMultiSelectedTabs(); } else { diff --git a/src/browser/components/tabbrowser/content/tabs-js.patch b/src/browser/components/tabbrowser/content/tabs-js.patch index ec4e9822e..5c93bcbc1 100644 --- a/src/browser/components/tabbrowser/content/tabs-js.patch +++ b/src/browser/components/tabbrowser/content/tabs-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js -index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a84f01452 100644 +index fa96568d366fd3608f9bd583fa793150bd815c8b..1c940a3b162919256ca73fa867c5c261a3395e25 100644 --- a/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js @@ -94,7 +94,7 @@ @@ -11,16 +11,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } return true; }; -@@ -135,6 +135,8 @@ - this.previewPanel = null; - - this.allTabs[0].label = this.emptyTabTitle; -+ this.allTabs[0]._possibleEmptyTab = true; -+ ZenWorkspaces._resolveEmptyTabInitialized(); - - // Hide the secondary text for locales where it is unsupported due to size constraints. - const language = Services.locale.appLocaleAsBCP47; -@@ -339,7 +341,7 @@ +@@ -339,7 +339,7 @@ // and we're not hitting the scroll buttons. if ( event.button != 0 || @@ -29,7 +20,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a event.composedTarget.localName == "toolbarbutton" ) { return; -@@ -388,6 +390,7 @@ +@@ -388,6 +388,7 @@ // Reset the "ignored click" flag target._ignoredCloseButtonClicks = false; } @@ -37,7 +28,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } /* Protects from close-tab-button errant doubleclick: -@@ -683,7 +686,7 @@ +@@ -683,7 +684,7 @@ if (this.#isContainerVerticalPinnedExpanded(tab)) { // In expanded vertical mode, the max number of pinned tabs per row is dynamic // Set this before adjusting dragged tab's position @@ -46,7 +37,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a let tabsPerRow = 0; let position = 0; for (let pinnedTab of pinnedTabs) { -@@ -883,6 +886,10 @@ +@@ -883,6 +884,10 @@ } let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0); @@ -57,7 +48,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if ( (effects == "move" || effects == "copy") && this == draggedTab.container && -@@ -996,6 +1003,18 @@ +@@ -996,6 +1001,18 @@ this._tabDropIndicator.hidden = true; event.stopPropagation(); @@ -76,7 +67,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (draggedTab && dropEffect == "copy") { // copy the dropped tab (wherever it's from) let newIndex = this._getDropIndex(event); -@@ -1034,10 +1053,11 @@ +@@ -1034,10 +1051,11 @@ } } else { let pinned = draggedTab.pinned; @@ -92,7 +83,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a ); let size = this.verticalMode ? "height" : "width"; let screenAxis = this.verticalMode ? "screenY" : "screenX"; -@@ -1114,7 +1134,7 @@ +@@ -1114,7 +1132,7 @@ let postTransitionCleanup = () => { tab.removeAttribute("tabdrop-samewindow"); @@ -101,7 +92,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (dropIndex !== false) { gBrowser.moveTabTo(tab, dropIndex); if (!directionForward) { -@@ -1122,7 +1142,7 @@ +@@ -1122,7 +1140,7 @@ } } }; @@ -110,7 +101,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -1249,7 +1269,7 @@ +@@ -1249,7 +1267,7 @@ return; } } @@ -119,7 +110,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a gBrowser.loadTabs(urls, { inBackground, replace, -@@ -1279,13 +1299,23 @@ +@@ -1279,13 +1297,23 @@ return; } @@ -145,7 +136,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a ) { delete draggedTab._dragData; return; -@@ -1517,7 +1547,7 @@ +@@ -1517,7 +1545,7 @@ } get newTabButton() { @@ -154,7 +145,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } get verticalMode() { -@@ -1537,28 +1567,40 @@ +@@ -1537,28 +1565,40 @@ if (this.#allTabs) { return this.#allTabs; } @@ -203,7 +194,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a return children.filter(node => node.tagName == "tab-group"); } -@@ -1579,7 +1621,7 @@ +@@ -1579,7 +1619,7 @@ */ get visibleTabs() { if (!this.#visibleTabs) { @@ -212,7 +203,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } return this.#visibleTabs; } -@@ -1613,10 +1655,8 @@ +@@ -1613,10 +1653,8 @@ return this.#focusableItems; } @@ -225,7 +216,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a let focusableItems = []; for (let child of children) { -@@ -1632,6 +1672,7 @@ +@@ -1632,6 +1670,7 @@ } this.#focusableItems = [ @@ -233,7 +224,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a ...verticalPinnedTabsContainer.children, ...focusableItems, ]; -@@ -1642,6 +1683,7 @@ +@@ -1642,6 +1681,7 @@ _invalidateCachedTabs() { this.#allTabs = null; this._invalidateCachedVisibleTabs(); @@ -241,7 +232,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } _invalidateCachedVisibleTabs() { -@@ -1656,8 +1698,8 @@ +@@ -1656,8 +1696,8 @@ #isContainerVerticalPinnedExpanded(tab) { return ( this.verticalMode && @@ -252,7 +243,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a ); } -@@ -1672,7 +1714,7 @@ +@@ -1672,7 +1712,7 @@ if (node == null) { // We have a container for non-tab elements at the end of the scrollbox. @@ -261,7 +252,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } node.before(tab); -@@ -1772,7 +1814,7 @@ +@@ -1772,7 +1812,7 @@ // There are separate "new tab" buttons for horizontal tabs toolbar, vertical tabs and // for when the tab strip is overflowed (which is shared by vertical and horizontal tabs); // Attach the long click popup to all of them. @@ -270,7 +261,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a const newTab2 = this.newTabButton; const newTabVertical = document.getElementById( "vertical-tabs-newtab-button" -@@ -1855,7 +1897,7 @@ +@@ -1855,7 +1895,7 @@ let rect = ele => { return window.windowUtils.getBoundsWithoutFlushing(ele); }; @@ -279,7 +270,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (tab && rect(tab).width <= this._tabClipWidth) { this.setAttribute("closebuttons", "activetab"); } else { -@@ -1867,10 +1909,12 @@ +@@ -1867,10 +1907,12 @@ _handleTabSelect(aInstant) { let selectedTab = this.selectedItem; @@ -292,7 +283,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a selectedTab._notselectedsinceload = false; } -@@ -1882,7 +1926,7 @@ +@@ -1882,7 +1924,7 @@ return; } @@ -301,7 +292,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (!tabs.length) { return; } -@@ -1918,7 +1962,7 @@ +@@ -1918,7 +1960,7 @@ if (isEndTab && !this._hasTabTempMaxWidth) { return; } @@ -310,7 +301,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a // Force tabs to stay the same width, unless we're closing the last tab, // which case we need to let them expand just enough so that the overall // tabbar width is the same. -@@ -1933,7 +1977,7 @@ +@@ -1933,7 +1975,7 @@ let tabsToReset = []; for (let i = numPinned; i < tabs.length; i++) { let tab = tabs[i]; @@ -319,7 +310,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (!isEndTab) { // keep tabs the same width tab.style.transition = "none"; -@@ -1999,16 +2043,15 @@ +@@ -1999,16 +2041,15 @@ // Move pinned tabs to another container when the tabstrip is toggled to vertical // and when session restore code calls _positionPinnedTabs; update styling whenever // the number of pinned tabs changes. @@ -342,7 +333,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } } -@@ -2016,9 +2059,7 @@ +@@ -2016,9 +2057,7 @@ } _resetVerticalPinnedTabs() { @@ -353,7 +344,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (!verticalTabsContainer.children.length) { return; -@@ -2031,8 +2072,8 @@ +@@ -2031,8 +2070,8 @@ } _positionPinnedTabs() { @@ -364,7 +355,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a let absPositionHorizontalTabs = this.overflowing && tabs.length > numPinned && numPinned > 0; -@@ -2041,7 +2082,7 @@ +@@ -2041,7 +2080,7 @@ if (this.verticalMode) { this._updateVerticalPinnedTabs(); @@ -373,7 +364,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a let layoutData = this._pinnedTabsLayoutCache; let uiDensity = document.documentElement.getAttribute("uidensity"); if (!layoutData || layoutData.uiDensity != uiDensity) { -@@ -2113,7 +2154,7 @@ +@@ -2113,7 +2152,7 @@ return; } @@ -382,7 +373,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a let directionX = screenX > dragData.animLastScreenX; let directionY = screenY > dragData.animLastScreenY; -@@ -2121,7 +2162,7 @@ +@@ -2121,7 +2160,7 @@ dragData.animLastScreenX = screenX; let { width: tabWidth, height: tabHeight } = @@ -391,7 +382,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a let shiftSizeX = tabWidth * movingTabs.length; let shiftSizeY = tabHeight; dragData.tabWidth = tabWidth; -@@ -2296,10 +2337,11 @@ +@@ -2296,10 +2335,11 @@ } let pinned = draggedTab.pinned; @@ -407,7 +398,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a ); if (this.#rtlMode) { -@@ -2348,7 +2390,11 @@ +@@ -2348,7 +2388,11 @@ translate = Math.min(Math.max(translate, firstBound), lastBound); for (let tab of movingTabs) { @@ -420,7 +411,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } dragData.translatePos = translate; -@@ -2484,12 +2530,16 @@ +@@ -2484,12 +2528,16 @@ // Shift background tabs to leave a gap where the dragged tab // would currently be dropped. for (let tab of tabs) { @@ -438,7 +429,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a if (tab.group?.tabs[0] == tab) { tab.group.style.setProperty( "--tabgroup-dragover-transform", -@@ -2541,8 +2591,9 @@ +@@ -2541,8 +2589,9 @@ ); } @@ -450,7 +441,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a return; } -@@ -2553,6 +2604,7 @@ +@@ -2553,6 +2602,7 @@ tab.style.transform = ""; if (tab.group) { tab.group.style.removeProperty("--tabgroup-dragover-transform"); @@ -458,7 +449,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } tab.removeAttribute("dragover-createGroup"); } -@@ -2604,7 +2656,7 @@ +@@ -2604,7 +2654,7 @@ movingTab._moveTogetherSelectedTabsData.newIndex = movingTabNewIndex; movingTab._moveTogetherSelectedTabsData.animate = false; }; @@ -467,7 +458,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a postTransitionCleanup(); } else { let onTransitionEnd = transitionendEvent => { -@@ -2707,9 +2759,9 @@ +@@ -2707,9 +2757,9 @@ function newIndex(aTab, index) { // Don't allow mixing pinned and unpinned tabs. if (aTab.pinned) { @@ -479,7 +470,7 @@ index fa96568d366fd3608f9bd583fa793150bd815c8b..89a3d8d63a045433f15fae37c8f5df2a } } -@@ -2793,7 +2845,7 @@ +@@ -2793,7 +2843,7 @@ } _notifyBackgroundTab(aTab) { diff --git a/src/browser/themes/shared/zen-icons/lin/media-mute.svg b/src/browser/themes/shared/zen-icons/lin/media-mute.svg index e98cb1e7e..45d1e0887 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-mute.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-mute.svg @@ -1 +1 @@ - + diff --git a/src/browser/themes/shared/zen-icons/lin/media-unmute.svg b/src/browser/themes/shared/zen-icons/lin/media-unmute.svg index 304ce827f..0d7642634 100644 --- a/src/browser/themes/shared/zen-icons/lin/media-unmute.svg +++ b/src/browser/themes/shared/zen-icons/lin/media-unmute.svg @@ -1 +1 @@ - + From ee275bf950bd2449c50fc580ea1f6af85e2a918b Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 15 Mar 2025 13:40:32 +0100 Subject: [PATCH 13/62] fix(css): correct transition timing syntax in media controls styles --- .../base/content/zen-styles/zen-media-controls.css | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index 12263449f..d3294e518 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -86,7 +86,7 @@ transform: translateX(-50%); z-index: 0; pointer-events: none; - transition: opacity .8s ease; + transition: opacity 0.8s ease; opacity: 1; } @@ -196,9 +196,9 @@ background: linear-gradient(to right, var(--zen-media-control-bg) 0%, transparent 100%); pointer-events: none; top: 6px; - left: -2px; - height: calc(100% - 6px); - z-index: 1; + left: -2px; + height: calc(100% - 6px); + z-index: 1; } & label { From 963fb3ca3cf75e0e38d3d00aba5b8f37cebbb1ca Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 15 Mar 2025 15:39:36 +0100 Subject: [PATCH 14/62] fix(xhtml): correct data-l10n-id for zen-glance sidebar close button --- l10n | 2 +- src/browser/base/content/zen-glance.inc.xhtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n b/l10n index 1db9cb464..0bc81a3d4 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit 1db9cb464e03cd75c910920360c8389516c9a4fd +Subproject commit 0bc81a3d4fc7f2fdcd99b7a2168db0c4f19bdaa9 diff --git a/src/browser/base/content/zen-glance.inc.xhtml b/src/browser/base/content/zen-glance.inc.xhtml index 286a32b11..51891d19c 100644 --- a/src/browser/base/content/zen-glance.inc.xhtml +++ b/src/browser/base/content/zen-glance.inc.xhtml @@ -1,4 +1,4 @@ From ce2e68ee324ba32dc43387150fa4c135d866eca7 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 15 Mar 2025 18:59:28 +0100 Subject: [PATCH 15/62] fix(ui): update URL bar layout and adjust media controls padding --- src/browser/base/content/ZenUIManager.mjs | 6 +++++- src/browser/base/content/zen-styles/zen-media-controls.css | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 185fe8cc3..e1866c2a7 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -65,6 +65,7 @@ var gZenUIManager = { tabs.style.removeProperty('flex'); tabs.style.maxHeight = height + 'px'; gZenVerticalTabsManager.actualWindowButtons.removeAttribute('zen-has-hover'); + gURLBar.updateLayoutBreakout(); }, get tabsWrapper() { @@ -361,7 +362,7 @@ var gZenVerticalTabsManager = { marginBottom: isLastTab() ? [] : [transform, '0px'], }, { - duration: 0.2, + duration: 0.12, easing: 'ease-out', } ) @@ -373,6 +374,9 @@ var gZenVerticalTabsManager = { gZenUIManager.motion .animate(aTab.querySelector('.tab-content'), { filter: ['blur(1px)', 'blur(0px)'], + }, { + duration: 0.12, + easing: 'ease-out', }) .then(() => { aTab.querySelector('.tab-stack').style.removeProperty('filter'); diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index d3294e518..c804deef4 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -110,7 +110,7 @@ position: absolute; left: 0; bottom: 0; - padding: 5px; + padding: 4px 6px; border-radius: var(--border-radius-medium); background: var(--zen-media-control-bg) !important; width: 100%; From b6477b17d8f8c47e72d7a33bbc7364eeafcd43f6 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sat, 15 Mar 2025 19:36:13 +0100 Subject: [PATCH 16/62] fix(build): disable LTO temporarily and enable PGO based on release settings refactor(ui): remove unnecessary DOMContentLoaded listener from toolbar registration fix(ui): trigger window resize event on closing watermark to recalculate layout refactor(ui): improve animation structure for tab content in vertical tabs manager --- configs/macos/mozconfig | 12 ++++++- .../base/content/ZenCustomizableUI.sys.mjs | 7 ---- src/browser/base/content/ZenStartup.mjs | 1 + src/browser/base/content/ZenUIManager.mjs | 16 +++++---- .../CustomizableUI-sys-mjs.patch | 14 ++++---- .../urlbar/UrlbarInput-sys-mjs.patch | 33 ++++++++++++------- 6 files changed, 51 insertions(+), 32 deletions(-) diff --git a/configs/macos/mozconfig b/configs/macos/mozconfig index 1cc417ced..9c1f488f3 100644 --- a/configs/macos/mozconfig +++ b/configs/macos/mozconfig @@ -7,8 +7,18 @@ export MOZ_MACBUNDLE_ID=${appId} export MOZ_MACBUNDLE_NAME="Zen Browser.app" # override LTO settings -# TODO: Dont +# TODO: Dont use LTO for now, it's causing a lot of issues +export MOZ_LTO=cross,thin +ac_add_options --enable-lto=cross,thin +if test "$ZEN_RELEASE"; then + if test "$ZEN_GA_DISABLE_PGO"; then + export ZEN_DUMMY=1 + else + export MOZ_PGO=1 + ac_add_options MOZ_PGO=1 + fi +fi if test "$SURFER_COMPAT" = "x86_64"; then ac_add_options --target=x86_64-apple-darwin diff --git a/src/browser/base/content/ZenCustomizableUI.sys.mjs b/src/browser/base/content/ZenCustomizableUI.sys.mjs index abd8112dc..a29692253 100644 --- a/src/browser/base/content/ZenCustomizableUI.sys.mjs +++ b/src/browser/base/content/ZenCustomizableUI.sys.mjs @@ -125,12 +125,5 @@ export var ZenCustomizableUI = new (class { registerToolbarNodes(window) { window.CustomizableUI.registerToolbarNode(window.document.getElementById('zen-sidebar-top-buttons')); window.CustomizableUI.registerToolbarNode(window.document.getElementById('zen-sidebar-bottom-buttons')); - window.addEventListener( - 'DOMContentLoaded', - () => { - this._dispatchResizeEvent(window); - }, - { once: true } - ); } })(); diff --git a/src/browser/base/content/ZenStartup.mjs b/src/browser/base/content/ZenStartup.mjs index 4de69a3d5..662afbd55 100644 --- a/src/browser/base/content/ZenStartup.mjs +++ b/src/browser/base/content/ZenStartup.mjs @@ -58,6 +58,7 @@ closeWatermark() { document.documentElement.removeAttribute('zen-before-loaded'); + window.dispatchEvent(new window.Event('resize')); // To recalculate the layout if (Services.prefs.getBoolPref('zen.watermark.enabled', false)) { gZenUIManager.motion .animate( diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index e1866c2a7..5a3089c5b 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -372,12 +372,16 @@ var gZenVerticalTabsManager = { aTab.style.removeProperty('opacity'); }); gZenUIManager.motion - .animate(aTab.querySelector('.tab-content'), { - filter: ['blur(1px)', 'blur(0px)'], - }, { - duration: 0.12, - easing: 'ease-out', - }) + .animate( + aTab.querySelector('.tab-content'), + { + filter: ['blur(1px)', 'blur(0px)'], + }, + { + duration: 0.12, + easing: 'ease-out', + } + ) .then(() => { aTab.querySelector('.tab-stack').style.removeProperty('filter'); }); diff --git a/src/browser/components/customizableui/CustomizableUI-sys-mjs.patch b/src/browser/components/customizableui/CustomizableUI-sys-mjs.patch index 35657acbd..20662d9f1 100644 --- a/src/browser/components/customizableui/CustomizableUI-sys-mjs.patch +++ b/src/browser/components/customizableui/CustomizableUI-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs -index e6b9b7dcfab179e7552c146eb1551b45ad042266..d9d838a7a51f67b52b69f419024cc3174ae5260b 100644 +index 8eab0f9181c19c68a0a2daf0f819b3ae82ed92bc..092107b377ec4f7bc9ae86c817cded349732ffc6 100644 --- a/browser/components/customizableui/CustomizableUI.sys.mjs +++ b/browser/components/customizableui/CustomizableUI.sys.mjs @@ -13,6 +13,7 @@ ChromeUtils.defineESModuleGetters(lazy, { @@ -116,7 +116,7 @@ index e6b9b7dcfab179e7552c146eb1551b45ad042266..d9d838a7a51f67b52b69f419024cc317 win.setToolbarVisibility( areaNode, typeof defaultCollapsed == "string" -@@ -4658,6 +4656,7 @@ export var CustomizableUI = { +@@ -4857,6 +4855,7 @@ export var CustomizableUI = { unregisterArea(aName, aDestroyPlacements) { CustomizableUIInternal.unregisterArea(aName, aDestroyPlacements); }, @@ -124,7 +124,7 @@ index e6b9b7dcfab179e7552c146eb1551b45ad042266..d9d838a7a51f67b52b69f419024cc317 /** * Add a widget to an area. * If the area to which you try to add is not known to CustomizableUI, -@@ -6483,11 +6482,11 @@ class OverflowableToolbar { +@@ -6840,11 +6839,11 @@ class OverflowableToolbar { parseFloat(style.paddingLeft) - parseFloat(style.paddingRight) - toolbarChildrenWidth; @@ -134,11 +134,11 @@ index e6b9b7dcfab179e7552c146eb1551b45ad042266..d9d838a7a51f67b52b69f419024cc317 this.#target == this.#toolbar ? toolbarChildrenWidth - : sumChildrenInlineSize(this.#target); -+ : sumChildrenInlineSize(this.#target, win.gZenVerticalTabsManager._topButtonsSeparatorElement); ++ : sumChildrenInlineSize((win.gZenVerticalTabsManager._hasSetSingleToolbar && this.#target.id == 'nav-bar-customization-target') ? win.document.getElementById("zen-sidebar-top-buttons-customization-target") : this.#target, win.gZenVerticalTabsManager._topButtonsSeparatorElement); }); lazy.log.debug( -@@ -6497,7 +6496,8 @@ class OverflowableToolbar { +@@ -6854,7 +6853,8 @@ class OverflowableToolbar { // If the target has min-width: 0, their children might actually overflow // it, so check for both cases explicitly. let targetContentWidth = Math.max(targetWidth, targetChildrenWidth); @@ -148,7 +148,7 @@ index e6b9b7dcfab179e7552c146eb1551b45ad042266..d9d838a7a51f67b52b69f419024cc317 return { isOverflowing, targetContentWidth, totalAvailWidth }; } -@@ -6591,7 +6591,7 @@ class OverflowableToolbar { +@@ -6948,7 +6948,7 @@ class OverflowableToolbar { } } if (!inserted) { @@ -157,7 +157,7 @@ index e6b9b7dcfab179e7552c146eb1551b45ad042266..d9d838a7a51f67b52b69f419024cc317 } child.removeAttribute("cui-anchorid"); child.removeAttribute("overflowedItem"); -@@ -6753,6 +6753,9 @@ class OverflowableToolbar { +@@ -7110,6 +7110,9 @@ class OverflowableToolbar { * @param {MouseEvent} aEvent the click event. */ #onClickDefaultListButton(aEvent) { diff --git a/src/browser/components/urlbar/UrlbarInput-sys-mjs.patch b/src/browser/components/urlbar/UrlbarInput-sys-mjs.patch index f6f9a9537..ced98537b 100644 --- a/src/browser/components/urlbar/UrlbarInput-sys-mjs.patch +++ b/src/browser/components/urlbar/UrlbarInput-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/urlbar/UrlbarInput.sys.mjs b/browser/components/urlbar/UrlbarInput.sys.mjs -index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb0bee29ea 100644 +index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..79b9161544633d319d7e550dd95334b62e85eed4 100644 --- a/browser/components/urlbar/UrlbarInput.sys.mjs +++ b/browser/components/urlbar/UrlbarInput.sys.mjs @@ -67,6 +67,13 @@ XPCOMUtils.defineLazyPreferenceGetter( @@ -52,7 +52,18 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb } /** -@@ -1098,7 +1116,11 @@ export class UrlbarInput { +@@ -943,6 +961,10 @@ export class UrlbarInput { + // Nullify search mode before setURI so it won't try to restore it. + this.searchMode = null; + this.setURI(null, true, false, true); ++ if (this.hasAttribute("zen-floating-urlbar")) { ++ this.window.gBrowser.selectedBrowser.focus(); ++ return; ++ } + if (this.value && this.focused) { + this.select(); + } +@@ -1098,7 +1120,11 @@ export class UrlbarInput { } if (!this.#providesSearchMode(result)) { @@ -65,7 +76,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb } this.controller.recordSelectedResult(event, result); -@@ -2157,6 +2179,11 @@ export class UrlbarInput { +@@ -2157,6 +2183,11 @@ export class UrlbarInput { this.setAttribute("breakout-extend", "true"); @@ -77,7 +88,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb // Enable the animation only after the first extend call to ensure it // doesn't run when opening a new window. if (!this.hasAttribute("breakout-extend-animate")) { -@@ -2176,6 +2203,11 @@ export class UrlbarInput { +@@ -2176,6 +2207,11 @@ export class UrlbarInput { return; } @@ -89,7 +100,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb this.removeAttribute("breakout-extend"); this.#updateTextboxPosition(); } -@@ -2998,7 +3030,7 @@ export class UrlbarInput { +@@ -2998,7 +3034,7 @@ export class UrlbarInput { */ _trimValue(val) { let trimmedValue = lazy.UrlbarPrefs.get("trimURLs") @@ -98,7 +109,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb : val; // Only trim value if the directionality doesn't change to RTL and we're not // showing a strikeout https protocol. -@@ -3365,7 +3397,7 @@ export class UrlbarInput { +@@ -3365,7 +3401,7 @@ export class UrlbarInput { } else { where = lazy.BrowserUtils.whereToOpenLink(event, false, false); } @@ -107,7 +118,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb if (where == "current") { where = "tab"; } else if (where == "tab") { -@@ -3380,6 +3412,9 @@ export class UrlbarInput { +@@ -3380,6 +3416,9 @@ export class UrlbarInput { ) { where = "current"; } @@ -117,7 +128,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb return where; } -@@ -3921,6 +3956,11 @@ export class UrlbarInput { +@@ -3921,6 +3960,11 @@ export class UrlbarInput { } _on_click(event) { @@ -129,7 +140,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb if ( event.target == this.inputField || event.target == this._inputContainer || -@@ -3992,7 +4032,7 @@ export class UrlbarInput { +@@ -3992,7 +4036,7 @@ export class UrlbarInput { } } @@ -138,7 +149,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb this.view.autoOpen({ event }); } else { if (this._untrimOnFocusAfterKeydown) { -@@ -4032,9 +4072,12 @@ export class UrlbarInput { +@@ -4032,9 +4076,12 @@ export class UrlbarInput { } _on_mousedown(event) { @@ -152,7 +163,7 @@ index 02c328f0d0724b0cf95c820fe49a43e94a97b3c2..30387bf4f128fdc1d687ee4f6c5a51eb if ( event.target != this.inputField && -@@ -4044,8 +4087,8 @@ export class UrlbarInput { +@@ -4044,8 +4091,8 @@ export class UrlbarInput { break; } From ac85bdfd3ef8e6a2b65f6d8bb6aff6335521c043 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 16 Mar 2025 00:51:18 +0100 Subject: [PATCH 17/62] fix(styles): adjust right positioning for split view in tab browser (closes https://github.com/zen-browser/desktop/issues/6451) --- .../base/content/zen-styles/zen-decks.css | 4 ++++ .../base/zen-components/ZenViewSplitter.mjs | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-decks.css b/src/browser/base/content/zen-styles/zen-decks.css index c63b945c8..8b39b2a47 100644 --- a/src/browser/base/content/zen-styles/zen-decks.css +++ b/src/browser/base/content/zen-styles/zen-decks.css @@ -278,6 +278,10 @@ &[side='right'] { right: 0; + + &[has-split-view='true'] { + right: var(--zen-element-separation); + } } &::after { diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index 789bcdb38..f9a0734fd 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -49,9 +49,13 @@ class SplitNode extends SplitLeafNode { return this._children; } - addChild(child) { + addChild(child, prepend = true) { child.parent = this; - this._children.unshift(child); + if (prepend) { + this._children.unshift(child); + } else { + this._children.push(child); + } } } @@ -231,6 +235,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); this.fakeBrowser.setAttribute('flex', '1'); this.fakeBrowser.id = 'zen-split-view-fake-browser'; + if (oldTab.splitView) { + this.fakeBrowser.setAttribute('has-split-view', 'true'); + } gBrowser.tabbox.appendChild(this.fakeBrowser); this.fakeBrowser.style.setProperty('--zen-split-view-fake-icon', `url(${draggedTab.getAttribute('image')})`); draggedTab._visuallySelected = true; @@ -988,10 +995,10 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { this.activateSplitView(splitData); } - addTabToSplit(tab, splitNode) { + addTabToSplit(tab, splitNode, prepend = true) { const reduce = splitNode.children.length / (splitNode.children.length + 1); splitNode.children.forEach((c) => (c.sizeInParent *= reduce)); - splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100)); + splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100), prepend); } /** @@ -1599,7 +1606,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { if (parentNode.direction !== splitDirection) { this.splitIntoNode(droppedOnSplitNode, new SplitLeafNode(draggedTab, 50), hoverSide, 0.5); } else { - this.addTabToSplit(draggedTab, parentNode); + this.addTabToSplit(draggedTab, parentNode, /* prepend = */ hoverSide === 'left' || hoverSide === 'top'); } } else { this.addTabToSplit(draggedTab, group.layoutTree); From a69876325a91661eb21e1e17631cdf8e1fa4f2af Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 16 Mar 2025 01:06:55 +0100 Subject: [PATCH 18/62] fix(styles): add default icon for broken tab images in vertical tabs --- .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 049c88ab7..7ffe0b312 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -267,6 +267,14 @@ scale: var(--zen-active-tab-scale); } + & .tab-icon-image { + &:not([src]), + &:-moz-broken { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3C/svg%3E") !important; + background: color-mix(in srgb, var(--zen-primary-color) 70%, transparent 30%); + } + } + max-width: unset; padding: 0 !important; From 364ad230fdf661c49e6558f227f7f4c97588dd18 Mon Sep 17 00:00:00 2001 From: pewpewnor <125549982+pewpewnor@users.noreply.github.com> Date: Sun, 16 Mar 2025 13:50:58 +0700 Subject: [PATCH 19/62] Fix bash install command in documentation on how to install for Linux using tarball Signed-off-by: pewpewnor <125549982+pewpewnor@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d6e54745..e38fb038e 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ yay -S zen-browser-bin - `Tarball` install: ```sh -bash <(curl -s https://updates.zen-browser.app/install.sh)` +bash <(curl -s https://updates.zen-browser.app/install.sh) ``` - `AppImage` install: From 0af85f8c03a22e6cc1bff1bdc0754f62c4bb3bae Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sun, 16 Mar 2025 21:04:08 +0700 Subject: [PATCH 20/62] New features for media control --- .../base/content/zen-media-player.inc.xhtml | 18 +- .../content/zen-styles/zen-media-controls.css | 26 ++ .../zen-components/ZenMediaController.mjs | 297 ++++++++++++++---- src/browser/themes/shared/zen-icons/icons.css | 8 + .../PictureInPicture-sys-mjs.patch | 12 +- 5 files changed, 286 insertions(+), 75 deletions(-) diff --git a/src/browser/base/content/zen-media-player.inc.xhtml b/src/browser/base/content/zen-media-player.inc.xhtml index e2bc804d5..20e42d254 100644 --- a/src/browser/base/content/zen-media-player.inc.xhtml +++ b/src/browser/base/content/zen-media-player.inc.xhtml @@ -6,10 +6,20 @@ - - - - + + + + + + + + + + { - if (this._currentBrowser) { - if (event.target.linkedBrowser.browserId === this._currentBrowser.browserId) { - gZenUIManager.motion - .animate( - this.mediaControlBar, - { - opacity: [1, 0], - y: [0, 10], - }, - { - duration: 0.1, - } - ) - .then(() => { - this.mediaControlBar.setAttribute('hidden', 'true'); - }); - } else if (this.mediaControlBar.hasAttribute('hidden')) { - this.mediaControlBar.removeAttribute('hidden'); - window.requestAnimationFrame(() => { - this.mediaControlBar.style.height = - this.mediaControlBar.querySelector('toolbaritem').getBoundingClientRect().height + 'px'; - this.mediaControlBar.style.opacity = 0; - gZenUIManager.motion.animate( - this.mediaControlBar, - { - opacity: [0, 1], - y: [10, 0], - }, - {} - ); - }); - } + const linkedBrowser = event.target.linkedBrowser; + this.switchController(); - gZenUIManager.updateTabsToolbar(); + if (this._currentBrowser) { + if (linkedBrowser.browserId === this._currentBrowser.browserId) { + if (this._tabTimeout) { + clearTimeout(this._tabTimeout); + this._tabTimeout = null; + } + + this.hideMediaControls(); + } else { + this._tabTimeout = setTimeout(() => { + if (!this.mediaControlBar.hasAttribute('pip')) this.showMediaControls(); + else this._tabTimeout = null; + }, 500); + } } }); window.addEventListener('TabClose', (event) => { - if (this._currentBrowser) { - if (event.target.linkedBrowser.browserId === this._currentBrowser.browserId) { - this.deinitMediaController(this._currentMediaController); - } - } + const linkedBrowser = event.target.linkedBrowser; + this.deinitMediaController( + linkedBrowser.browsingContext.mediaController, + true, + linkedBrowser.browserId === this._currentBrowser?.browserId, + true + ); }); window.addEventListener('DOMAudioPlaybackStarted', (event) => { @@ -87,24 +78,46 @@ class ZenMediaController { * Deinitializes a media controller, removing all event listeners and resetting state. * @param {Object} mediaController - The media controller to deinitialize. */ - deinitMediaController(mediaController) { + async deinitMediaController(mediaController, shouldForget = true, shouldOverride = true, shouldHide = true) { if (!mediaController) return; - mediaController.removeEventListener('positionstatechange', this.onPositionstateChange); - mediaController.removeEventListener('playbackstatechange', this.onPlaybackstateChange); - mediaController.removeEventListener('supportedkeyschange', this.onSupportedKeysChange); - mediaController.removeEventListener('metadatachange', this.onMetadataChange); - mediaController.removeEventListener('deactivated', this.onDeactivated); + const retrievedMediaController = this.mediaControllersMap.get(mediaController.id); - this._currentMediaController = null; - this._currentBrowser = null; - - if (this._mediaUpdateInterval) { - clearInterval(this._mediaUpdateInterval); - this._mediaUpdateInterval = null; + if (this.tabObserver && shouldOverride) { + this.tabObserver.disconnect(); + this.tabObserver = null; } - gZenUIManager.motion + if (shouldForget) { + mediaController.removeEventListener('positionstatechange', this.onPositionstateChange); + mediaController.removeEventListener('playbackstatechange', this.onPlaybackstateChange); + mediaController.removeEventListener('supportedkeyschange', this.onSupportedKeysChange); + mediaController.removeEventListener('metadatachange', this.onMetadataChange); + mediaController.removeEventListener('deactivated', this.onDeactivated); + + this.mediaControllersMap.delete(mediaController.id); + this.pipEligibilityMap.delete(retrievedMediaController.browser.browserId); + } + + if (shouldOverride) { + this._currentMediaController = null; + this._currentBrowser = null; + + if (this._mediaUpdateInterval) { + clearInterval(this._mediaUpdateInterval); + this._mediaUpdateInterval = null; + } + + if (shouldHide) await this.hideMediaControls(); + this.mediaControlBar.removeAttribute('muted'); + this.mediaControlBar.classList.remove('playing'); + } + } + + hideMediaControls() { + if (this.mediaControlBar.hasAttribute('hidden')) return; + + return gZenUIManager.motion .animate( this.mediaControlBar, { @@ -119,8 +132,67 @@ class ZenMediaController { this.mediaControlBar.setAttribute('hidden', 'true'); gZenUIManager.updateTabsToolbar(); }); - this.mediaControlBar.removeAttribute('muted'); - this.mediaControlBar.classList.remove('playing'); + } + + showMediaControls() { + const tab = gBrowser.getTabForBrowser(this._currentBrowser); + if (tab.hasAttribute('pictureinpicture')) return this.hideMediaControls(); + + if (!this.mediaControlBar.hasAttribute('hidden')) return; + this.updatePipButton(); + + this.mediaControlBar.removeAttribute('hidden'); + window.requestAnimationFrame(() => { + this.mediaControlBar.style.height = + this.mediaControlBar.querySelector('toolbaritem').getBoundingClientRect().height + 'px'; + this.mediaControlBar.style.opacity = 0; + gZenUIManager.updateTabsToolbar(); + gZenUIManager.motion.animate( + this.mediaControlBar, + { + opacity: [0, 1], + y: [10, 0], + }, + {} + ); + }); + } + + setupMediaController(mediaController, browser) { + this._currentMediaController = mediaController; + this._currentBrowser = browser; + + this.updatePipButton(); + + this.tabObserver = new MutationObserver((entries) => { + for (const entry of entries) { + if (entry.target.hasAttribute('pictureinpicture')) { + this.hideMediaControls(); + this.mediaControlBar.setAttribute('pip', ''); + } else { + const { selectedBrowser } = gBrowser; + if (selectedBrowser.browserId !== this._currentBrowser.browserId) { + this.showMediaControls(); + } + + this.mediaControlBar.removeAttribute('pip'); + } + } + }); + + this.tabObserver.observe(gBrowser.getTabForBrowser(browser), { + attributes: true, + attributeFilter: ['pictureinpicture'], + }); + + const positionState = mediaController.getPositionState(); + this.mediaControllersMap.set(mediaController.id, { + controller: mediaController, + browser, + position: positionState.position, + duration: positionState.duration, + lastUpdated: Date.now(), + }); } /** @@ -128,12 +200,15 @@ class ZenMediaController { * @param {Object} metadata - The media metadata (title, artist, etc.). * @param {Object} positionState - The position state (position, duration). */ - setupMediaControl(metadata, positionState) { - if (!this.mediaControlBar.classList.contains('playing')) { + setupMediaControlUI(metadata, positionState) { + this.updatePipButton(); + + if (!this.mediaControlBar.classList.contains('playing') && this._currentMediaController.isPlaying) { this.mediaControlBar.classList.add('playing'); } - this.mediaFocusButton.style.listStyleImage = `url(${this._currentBrowser.mIconURL})`; + const iconURL = this._currentBrowser.mIconURL || `page-icon:${this._currentBrowser.currentURI.spec}`; + this.mediaFocusButton.style.listStyleImage = `url(${iconURL})`; this.mediaTitle.textContent = metadata.title || ''; this.mediaArtist.textContent = metadata.artist || ''; @@ -158,10 +233,21 @@ class ZenMediaController { this.updateMuteState(); if (!mediaController.isActive || this._currentBrowser?.browserId === browser.browserId) return; + + const metadata = mediaController.getMetadata(); + const positionState = mediaController.getPositionState(); + this.mediaControllersMap.set(mediaController.id, { + controller: mediaController, + browser, + position: positionState.position, + duration: positionState.duration, + lastUpdated: Date.now(), + }); + + if (this._currentBrowser) this.switchController(); else { - this.deinitMediaController(this._currentMediaController); - this._currentMediaController = mediaController; - this._currentBrowser = browser; + this.setupMediaController(mediaController, browser); + this.setupMediaControlUI(metadata, positionState); } mediaController.addEventListener('positionstatechange', this.onPositionstateChange); @@ -169,28 +255,31 @@ class ZenMediaController { mediaController.addEventListener('supportedkeyschange', this.onSupportedKeysChange); mediaController.addEventListener('metadatachange', this.onMetadataChange); mediaController.addEventListener('deactivated', this.onDeactivated); + } - const metadata = mediaController.getMetadata(); - const positionState = mediaController.getPositionState(); - - this.setupMediaControl(metadata, positionState); + updatePipEligibility(browser, isEligible) { + this.pipEligibilityMap.set(browser.browserId, isEligible); } /** * @param {Event} event - The deactivation event. */ _onDeactivated(event) { - if (event.target === this._currentMediaController) { - this.deinitMediaController(event.target); - } + this.deinitMediaController(event.target, true, event.target.id === this._currentMediaController.id, true); + this.switchController(); } /** * Updates playback state and UI based on changes. * @param {Event} event - The playback state change event. */ - _onPlaybackstateChange(event) { - this.mediaControlBar.classList.toggle('playing', event.target.isPlaying); + _onPlaybackstateChange() { + if (this._currentMediaController?.isPlaying) { + this.mediaControlBar.classList.add('playing'); + } else { + this.switchController(); + this.mediaControlBar.classList.remove('playing'); + } } /** @@ -198,6 +287,7 @@ class ZenMediaController { * @param {Event} event - The supported keys change event. */ _onSupportedKeysChange(event) { + if (event.target !== this._currentMediaController) return; for (const key of this.supportedKeys) { const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`); button.disabled = !event.target.supportedKeys.includes(key); @@ -209,13 +299,61 @@ class ZenMediaController { * @param {Event} event - The position state change event. */ _onPositionstateChange(event) { - if (event.target !== this._currentMediaController) return; + if (event.target !== this._currentMediaController) { + const mediaController = this.mediaControllersMap.get(event.target.id); + this.mediaControllersMap.set(event.target.id, { + ...mediaController, + position: event.position, + duration: event.duration, + lastUpdated: Date.now(), + }); + } this._currentPosition = event.position; this._currentDuration = event.duration; this.updateMediaPosition(); } + switchController(force = false) { + let timeout = 3000; + + if (this._controllerSwitchTimeout) { + clearTimeout(this._controllerSwitchTimeout); + this._controllerSwitchTimeout = null; + } + + if (this.mediaControllersMap.size === 1) timeout = 0; + this._controllerSwitchTimeout = setTimeout(() => { + if (!this._currentMediaController?.isPlaying || force) { + const nextController = Array.from(this.mediaControllersMap.values()) + .filter( + (ctrl) => + ctrl.controller.isPlaying && + gBrowser.selectedBrowser.browserId !== ctrl.browser.browserId && + ctrl.controller.id !== this._currentMediaController?.id + ) + .sort((a, b) => b.lastUpdated - a.lastUpdated) + .shift(); + + if (nextController) { + this.deinitMediaController(this._currentMediaController, false, true, false).then(() => { + this.setupMediaController(nextController.controller, nextController.browser); + const elapsedTime = Math.floor((Date.now() - nextController.lastUpdated) / 1000); + + this.setupMediaControlUI(nextController.controller.getMetadata(), { + position: nextController.position + (nextController.controller.isPlaying ? elapsedTime : 0), + duration: nextController.duration, + }); + + this.showMediaControls(); + }); + } + } + + this._controllerSwitchTimeout = null; + }, timeout); + } + /** * Updates the media progress bar and time display. */ @@ -274,6 +412,9 @@ class ZenMediaController { * @param {Event} event - The metadata change event. */ _onMetadataChange(event) { + if (event.target !== this._currentMediaController) return; + this.updatePipButton(); + const metadata = event.target.getMetadata(); this.mediaTitle.textContent = metadata.title || ''; this.mediaArtist.textContent = metadata.artist || ''; @@ -327,6 +468,18 @@ class ZenMediaController { } } + onControllerClose() { + this._currentMediaController?.pause(); + this.switchController(true); + this.deinitMediaController(this._currentMediaController, true, true, true); + } + + onMediaPip() { + this._currentBrowser.browsingContext.currentWindowGlobal + .getActor('PictureInPictureLauncher') + .sendAsyncMessage('PictureInPicture:KeyToggle'); + } + updateMuteState() { if (!this._currentBrowser) return; if (this._currentBrowser._audioMuted) { @@ -335,6 +488,12 @@ class ZenMediaController { this.mediaControlBar.removeAttribute('muted'); } } + + updatePipButton() { + const isPipEligible = this.pipEligibilityMap.get(this._currentBrowser.browserId); + if (isPipEligible) this.mediaControlBar.setAttribute('can-pip', ''); + else this.mediaControlBar.removeAttribute('can-pip'); + } } window.gZenMediaController = new ZenMediaController(); diff --git a/src/browser/themes/shared/zen-icons/icons.css b/src/browser/themes/shared/zen-icons/icons.css index b6a47e67d..cf000af85 100644 --- a/src/browser/themes/shared/zen-icons/icons.css +++ b/src/browser/themes/shared/zen-icons/icons.css @@ -1182,3 +1182,11 @@ menupopup > menuitem:is([type='checkbox']) .menu-iconic-left { #zen-media-focus-button:hover { list-style-image: url('screen.svg') !important; } + +#zen-media-close-button { + list-style-image: url('close.svg') !important; +} + +#zen-media-pip-button { + list-style-image: url('chrome://global/skin/media/picture-in-picture-open.svg') !important; +} diff --git a/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch b/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch index a6be52467..feaef745e 100644 --- a/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch +++ b/src/toolkit/components/pictureinpicture/PictureInPicture-sys-mjs.patch @@ -1,5 +1,5 @@ diff --git a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs -index 5da0404b2672ba8cce7bcf808bf2373474776654..c3d58941b66c54f9d506698d015e294f8c8a5ceb 100644 +index 5da0404b2672ba8cce7bcf808bf2373474776654..44b62bd752294c2af96dd5b5d08c90ddf3dc513f 100644 --- a/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs +++ b/toolkit/components/pictureinpicture/PictureInPicture.sys.mjs @@ -488,13 +488,13 @@ export var PictureInPicture = { @@ -19,7 +19,15 @@ index 5da0404b2672ba8cce7bcf808bf2373474776654..c3d58941b66c54f9d506698d015e294f await this.closeSinglePipWindow({ reason: "Unpip", actorRef: pipActor }); }, -@@ -877,7 +877,7 @@ export var PictureInPicture = { +@@ -623,6 +623,7 @@ export var PictureInPicture = { + pipToggle.hidden = true; + } + ++ win.gZenMediaController.updatePipEligibility(browser, !pipToggle.hidden); + let browserHasPip = !!this.browserWeakMap.get(browser); + if (browserHasPip) { + this.setUrlbarPipIconActive(browser.ownerGlobal); +@@ -877,7 +878,7 @@ export var PictureInPicture = { win.setIsMutedState(videoData.isMuted); // set attribute which shows pip icon in tab From 2530740066e60906b2194eb414243f55be33de5a Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sun, 16 Mar 2025 21:13:01 +0700 Subject: [PATCH 21/62] remove unneeded params --- src/browser/base/zen-components/ZenMediaController.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 276c087f0..0087dbcbc 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -471,7 +471,7 @@ class ZenMediaController { onControllerClose() { this._currentMediaController?.pause(); this.switchController(true); - this.deinitMediaController(this._currentMediaController, true, true, true); + this.deinitMediaController(this._currentMediaController); } onMediaPip() { From 36cf513431b6707abb097d9212f4c5f7c53fdd12 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sun, 16 Mar 2025 21:25:04 +0700 Subject: [PATCH 22/62] adjust timeout --- src/browser/base/zen-components/ZenMediaController.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 0087dbcbc..e64e57342 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -323,6 +323,8 @@ class ZenMediaController { } if (this.mediaControllersMap.size === 1) timeout = 0; + if (this.mediaControlBar.hasAttribute('hidden')) timeout = 0; + this._controllerSwitchTimeout = setTimeout(() => { if (!this._currentMediaController?.isPlaying || force) { const nextController = Array.from(this.mediaControllersMap.values()) From d88e3ec982136c382cf3ff47a7b8057c199fb3f2 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sun, 16 Mar 2025 22:05:03 +0700 Subject: [PATCH 23/62] add a timeout just in case the control is still hiding.. --- .../zen-components/ZenMediaController.mjs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index e64e57342..d8db89036 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -68,6 +68,19 @@ class ZenMediaController { }); window.addEventListener('DOMAudioPlaybackStarted', (event) => { + setTimeout(() => { + if ( + this._currentMediaController?.isPlaying && + this.mediaControlBar.hasAttribute('hidden') && + !this.mediaControlBar.hasAttribute('pip') + ) { + const { selectedBrowser } = gBrowser; + if (selectedBrowser.browserId !== this._currentBrowser.browserId) { + this.showMediaControls(); + } + } + }, 1000); + this.activateMediaControls(event.target.browsingContext.mediaController, event.target); }); @@ -231,6 +244,7 @@ class ZenMediaController { */ activateMediaControls(mediaController, browser) { this.updateMuteState(); + this.switchController(); if (!mediaController.isActive || this._currentBrowser?.browserId === browser.browserId) return; @@ -244,8 +258,7 @@ class ZenMediaController { lastUpdated: Date.now(), }); - if (this._currentBrowser) this.switchController(); - else { + if (!this._currentBrowser) { this.setupMediaController(mediaController, browser); this.setupMediaControlUI(metadata, positionState); } @@ -323,8 +336,6 @@ class ZenMediaController { } if (this.mediaControllersMap.size === 1) timeout = 0; - if (this.mediaControlBar.hasAttribute('hidden')) timeout = 0; - this._controllerSwitchTimeout = setTimeout(() => { if (!this._currentMediaController?.isPlaying || force) { const nextController = Array.from(this.mediaControllersMap.values()) From bab0df47f0c0e8977f9df743b7fac784671d4ef0 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 16 Mar 2025 22:05:38 +0100 Subject: [PATCH 24/62] refactor media control styles and remove unused animations --- .../content/zen-styles/zen-animations.css | 13 -------- .../content/zen-styles/zen-media-controls.css | 33 ++++++++++++------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-animations.css b/src/browser/base/content/zen-styles/zen-animations.css index f27792485..4d820f320 100644 --- a/src/browser/base/content/zen-styles/zen-animations.css +++ b/src/browser/base/content/zen-styles/zen-animations.css @@ -290,16 +290,3 @@ transform: scale(1); } } - -@keyframes zen-marquee-h { - 0%, - 20%, - 80%, - 100% { - transform: translateX(0px); - } - 40%, - 60% { - transform: translateX(calc(-1 * max(0px, 100% - 266px))); - } -} diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index 3a810ca28..b5e39e817 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -15,6 +15,8 @@ #zen-media-buttons-hbox { align-items: start; + margin-top: -4px; + --toolbarbutton-outer-padding: 2px; } &:not([can-pip]) { @@ -91,12 +93,12 @@ & #zen-media-focus-button::after { content: ''; position: absolute; - width: 100%; - height: 100%; + width: 110%; + height: 110%; background-repeat: no-repeat; opacity: 1; background: url('chrome://browser/content/zen-images/note-indicator.svg') no-repeat; - top: -50%; + top: -70%; left: 50%; transform: translateX(-50%); z-index: 0; @@ -115,6 +117,13 @@ opacity 0.2s ease, transform 0.2s ease; position: relative; + + & image { + &:-moz-broken { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3C/svg%3E") !important; + background: color-mix(in srgb, var(--zen-primary-color) 70%, transparent 30%); + } + } } toolbaritem { @@ -139,10 +148,10 @@ padding: 0 6px; pointer-events: none; transition: - max-height 0.3s ease, - opacity 0.3s ease, - transform 0.3s ease, - padding 0.3s ease; + max-height 0.2s ease, + opacity 0.2s ease, + transform 0.2s ease, + padding 0.2s ease; } #zen-media-current-time, @@ -196,13 +205,13 @@ #zen-media-info-vbox { #zen-media-controls-toolbar:not([media-position-hidden='true']) & { transition-delay: 0.01s !important; - transform: translateY(-0.4rem); } overflow-x: hidden; overflow-x: visible; white-space: nowrap; /* Overflow inner box shadow from the left to simulate overflow */ mask-image: linear-gradient(to left, transparent, var(--zen-media-control-bg) 0.6em); + min-width: 1px; &::before { content: ''; @@ -220,7 +229,6 @@ min-height: 16px; margin-left: 0; font-weight: 500; - animation: zen-marquee-h 10s ease-in-out infinite; } } @@ -249,10 +257,13 @@ --toolbarbutton-outer-padding: 0; } +#zen-media-info-container { + padding-right: 0 !important; +} + #zen-media-controls-toolbar[can-pip] { #zen-media-info-vbox { - width: calc(100% - 58px); - flex-shrink: 0; + flex-shrink: 1; } #zen-media-pip-button { From fe9eb8884ea9cda9de3fd76e311ad161293474d2 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 16 Mar 2025 22:17:00 +0100 Subject: [PATCH 25/62] fix: adjust margin and remove unnecessary padding in vertical tabs styles --- .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 7ffe0b312..b2bb5a22e 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -108,7 +108,7 @@ } & #zen-sidebar-top-buttons { - margin: var(--zen-element-separation) 0 calc(var(--zen-toolbox-padding) / 2) 0; + margin: var(--zen-toolbox-padding) 0 calc(var(--zen-toolbox-padding) / 2) 0; } & #PanelUI-menu-button { @@ -153,8 +153,6 @@ min-width: var(--zen-toolbox-min-width); margin-top: 0 !important; /* Fix full screen mode */ - padding-bottom: var(--zen-element-separation) !important; - border: none; order: 0 !important; From 401085f2314f767128072357fb493924cba1bd98 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 16 Mar 2025 23:29:09 +0100 Subject: [PATCH 26/62] feat: add back-and-forth animation for media title and artist overflow labels --- .../content/zen-styles/zen-animations.css | 20 +++++++++++++++++++ .../content/zen-styles/zen-media-controls.css | 14 ++++++------- .../zen-styles/zen-tabs/vertical-tabs.css | 2 +- .../zen-components/ZenMediaController.mjs | 13 ++++++++++++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-animations.css b/src/browser/base/content/zen-styles/zen-animations.css index 4d820f320..2ea56928b 100644 --- a/src/browser/base/content/zen-styles/zen-animations.css +++ b/src/browser/base/content/zen-styles/zen-animations.css @@ -290,3 +290,23 @@ transform: scale(1); } } + +@keyframes zen-back-and-forth-text { + 0%, + 20% { + transform: translateX(0); + left: 0; + } + + 50%, + 60% { + transform: translateX(calc(-100% - 5px)); + left: 100%; + } + + 80%, + 100% { + transform: translateX(0); + left: 0; + } +} diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index b5e39e817..8be6a2545 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -75,11 +75,6 @@ } &:hover { - & #zen-media-main-vbox { - transition-delay: 0s; - gap: 6px; - } - .show-on-hover { max-height: 50px; padding: 5px; @@ -220,7 +215,7 @@ background: linear-gradient(to right, var(--zen-media-control-bg) 0%, transparent 100%); pointer-events: none; top: 6px; - left: -2px; + left: 0; height: calc(100% - 6px); z-index: 1; } @@ -229,14 +224,17 @@ min-height: 16px; margin-left: 0; font-weight: 500; + position: relative; /* For the animation */ + + &[overflow] { + animation: zen-back-and-forth-text 8s infinite ease-in-out; + } } } #zen-media-main-vbox { height: 100%; justify-content: space-between; - transition: gap 0.3s ease; - gap: 0px; } #zen-media-progress-hbox { diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index b2bb5a22e..506f7c586 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -269,7 +269,7 @@ &:not([src]), &:-moz-broken { content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3C/svg%3E") !important; - background: color-mix(in srgb, var(--zen-primary-color) 70%, transparent 30%); + background: color-mix(in srgb, var(--zen-primary-color) 30%, transparent 70%); } } diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index d8db89036..e4d304072 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -168,9 +168,22 @@ class ZenMediaController { }, {} ); + this.addLabelOverflows(); }); } + addLabelOverflows() { + const elements = [this.mediaTitle, this.mediaArtist]; + for (const element of elements) { + const parent = element.parentElement; + if (element.scrollWidth > parent.clientWidth) { + element.setAttribute('overflow', ''); + } else { + element.removeAttribute('overflow'); + } + } + } + setupMediaController(mediaController, browser) { this._currentMediaController = mediaController; this._currentBrowser = browser; From 7c387db3e855691c67710e4fc1b0b18ad4e510e8 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Mon, 17 Mar 2025 20:14:53 +0700 Subject: [PATCH 27/62] Fix media control not working for web panels --- .../zen-components/ZenMediaController.mjs | 97 +++++-------------- .../MediaController-webidl.patch | 9 +- .../mediacontrol/MediaController-cpp.patch | 10 +- 3 files changed, 40 insertions(+), 76 deletions(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index e4d304072..c9ef00ac2 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -35,6 +35,7 @@ class ZenMediaController { this.onSupportedKeysChange = this._onSupportedKeysChange.bind(this); this.onMetadataChange = this._onMetadataChange.bind(this); this.onDeactivated = this._onDeactivated.bind(this); + this.onPipModeChange = this._onPictureInPictureModeChange.bind(this); window.addEventListener('TabSelect', (event) => { const linkedBrowser = event.target.linkedBrowser; @@ -87,21 +88,13 @@ class ZenMediaController { window.addEventListener('DOMAudioPlaybackStopped', () => this.updateMuteState()); } - /** - * Deinitializes a media controller, removing all event listeners and resetting state. - * @param {Object} mediaController - The media controller to deinitialize. - */ async deinitMediaController(mediaController, shouldForget = true, shouldOverride = true, shouldHide = true) { if (!mediaController) return; const retrievedMediaController = this.mediaControllersMap.get(mediaController.id); - if (this.tabObserver && shouldOverride) { - this.tabObserver.disconnect(); - this.tabObserver = null; - } - if (shouldForget) { + mediaController.removeEventListener('pictureinpicturemodechange', this.onPipModeChange); mediaController.removeEventListener('positionstatechange', this.onPositionstateChange); mediaController.removeEventListener('playbackstatechange', this.onPlaybackstateChange); mediaController.removeEventListener('supportedkeyschange', this.onSupportedKeysChange); @@ -148,10 +141,9 @@ class ZenMediaController { } showMediaControls() { - const tab = gBrowser.getTabForBrowser(this._currentBrowser); - if (tab.hasAttribute('pictureinpicture')) return this.hideMediaControls(); - + if (this._currentMediaController.isBeingUsedInPIPModeOrFullscreen) return this.hideMediaControls(); if (!this.mediaControlBar.hasAttribute('hidden')) return; + this.updatePipButton(); this.mediaControlBar.removeAttribute('hidden'); @@ -190,27 +182,6 @@ class ZenMediaController { this.updatePipButton(); - this.tabObserver = new MutationObserver((entries) => { - for (const entry of entries) { - if (entry.target.hasAttribute('pictureinpicture')) { - this.hideMediaControls(); - this.mediaControlBar.setAttribute('pip', ''); - } else { - const { selectedBrowser } = gBrowser; - if (selectedBrowser.browserId !== this._currentBrowser.browserId) { - this.showMediaControls(); - } - - this.mediaControlBar.removeAttribute('pip'); - } - } - }); - - this.tabObserver.observe(gBrowser.getTabForBrowser(browser), { - attributes: true, - attributeFilter: ['pictureinpicture'], - }); - const positionState = mediaController.getPositionState(); this.mediaControllersMap.set(mediaController.id, { controller: mediaController, @@ -221,11 +192,6 @@ class ZenMediaController { }); } - /** - * Sets up the media control UI with metadata and position state. - * @param {Object} metadata - The media metadata (title, artist, etc.). - * @param {Object} positionState - The position state (position, duration). - */ setupMediaControlUI(metadata, positionState) { this.updatePipButton(); @@ -251,10 +217,6 @@ class ZenMediaController { } } - /** - * @param {Object} mediaController - The media controller to activate. - * @param {Object} browser - The browser associated with the media controller. - */ activateMediaControls(mediaController, browser) { this.updateMuteState(); this.switchController(); @@ -276,6 +238,7 @@ class ZenMediaController { this.setupMediaControlUI(metadata, positionState); } + mediaController.addEventListener('pictureinpicturemodechange', this.onPipModeChange); mediaController.addEventListener('positionstatechange', this.onPositionstateChange); mediaController.addEventListener('playbackstatechange', this.onPlaybackstateChange); mediaController.addEventListener('supportedkeyschange', this.onSupportedKeysChange); @@ -287,18 +250,11 @@ class ZenMediaController { this.pipEligibilityMap.set(browser.browserId, isEligible); } - /** - * @param {Event} event - The deactivation event. - */ _onDeactivated(event) { this.deinitMediaController(event.target, true, event.target.id === this._currentMediaController.id, true); this.switchController(); } - /** - * Updates playback state and UI based on changes. - * @param {Event} event - The playback state change event. - */ _onPlaybackstateChange() { if (this._currentMediaController?.isPlaying) { this.mediaControlBar.classList.add('playing'); @@ -308,24 +264,16 @@ class ZenMediaController { } } - /** - * Updates supported keys in the UI. - * @param {Event} event - The supported keys change event. - */ _onSupportedKeysChange(event) { - if (event.target !== this._currentMediaController) return; + if (event.target.id !== this._currentMediaController?.id) return; for (const key of this.supportedKeys) { const button = this.mediaControlBar.querySelector(`#zen-media-${key}-button`); button.disabled = !event.target.supportedKeys.includes(key); } } - /** - * Updates position state and UI when the media position changes. - * @param {Event} event - The position state change event. - */ _onPositionstateChange(event) { - if (event.target !== this._currentMediaController) { + if (event.target.id !== this._currentMediaController?.id) { const mediaController = this.mediaControllersMap.get(event.target.id); this.mediaControllersMap.set(event.target.id, { ...mediaController, @@ -362,7 +310,7 @@ class ZenMediaController { .shift(); if (nextController) { - this.deinitMediaController(this._currentMediaController, false, true, false).then(() => { + this.deinitMediaController(this._currentMediaController, false, true).then(() => { this.setupMediaController(nextController.controller, nextController.browser); const elapsedTime = Math.floor((Date.now() - nextController.lastUpdated) / 1000); @@ -380,9 +328,6 @@ class ZenMediaController { }, timeout); } - /** - * Updates the media progress bar and time display. - */ updateMediaPosition() { if (this._mediaUpdateInterval) { clearInterval(this._mediaUpdateInterval); @@ -413,11 +358,6 @@ class ZenMediaController { }, 1000); } - /** - * Formats seconds into a hours:minutes:seconds string. - * @param {number} seconds - The time in seconds. - * @returns {string} Formatted time string. - */ formatSecondsToTime(seconds) { if (!seconds || isNaN(seconds)) return '0:00'; @@ -433,12 +373,8 @@ class ZenMediaController { return `${minutes}:${secs.padStart(2, '0')}`; } - /** - * Updates metadata in the UI. - * @param {Event} event - The metadata change event. - */ _onMetadataChange(event) { - if (event.target !== this._currentMediaController) return; + if (event.target.id !== this._currentMediaController.id) return; this.updatePipButton(); const metadata = event.target.getMetadata(); @@ -446,6 +382,21 @@ class ZenMediaController { this.mediaArtist.textContent = metadata.artist || ''; } + _onPictureInPictureModeChange(event) { + if (event.target.id !== this._currentMediaController.id) return; + if (event.target.isBeingUsedInPIPModeOrFullscreen) { + this.hideMediaControls(); + this.mediaControlBar.setAttribute('pip', ''); + } else { + const { selectedBrowser } = gBrowser; + if (selectedBrowser.browserId !== this._currentBrowser.browserId) { + this.showMediaControls(); + } + + this.mediaControlBar.removeAttribute('pip'); + } + } + onMediaPlayPrev() { if (this._currentMediaController?.supportedKeys.includes('previoustrack')) { this._currentMediaController.prevTrack(); diff --git a/src/dom/chrome-webidl/MediaController-webidl.patch b/src/dom/chrome-webidl/MediaController-webidl.patch index 73a252539..d7c868534 100644 --- a/src/dom/chrome-webidl/MediaController-webidl.patch +++ b/src/dom/chrome-webidl/MediaController-webidl.patch @@ -1,5 +1,5 @@ diff --git a/dom/chrome-webidl/MediaController.webidl b/dom/chrome-webidl/MediaController.webidl -index 20f416d1c3b41798e0f90bbac5db40ed2a4ab000..06cb4c847fcfba964eeb93089613e293dc10bd87 100644 +index 20f416d1c3b41798e0f90bbac5db40ed2a4ab000..1c5d893f9166a3aa7bc7802bb0d1207d169033ee 100644 --- a/dom/chrome-webidl/MediaController.webidl +++ b/dom/chrome-webidl/MediaController.webidl @@ -20,6 +20,12 @@ enum MediaControlKey { @@ -15,7 +15,12 @@ index 20f416d1c3b41798e0f90bbac5db40ed2a4ab000..06cb4c847fcfba964eeb93089613e293 /** * MediaController is used to control media playback for a tab, and each tab * would only have one media controller, which can be accessed from the -@@ -36,6 +42,9 @@ interface MediaController : EventTarget { +@@ -32,10 +38,14 @@ interface MediaController : EventTarget { + readonly attribute boolean isAudible; + readonly attribute boolean isPlaying; + readonly attribute MediaSessionPlaybackState playbackState; ++ readonly attribute boolean isBeingUsedInPIPModeOrFullscreen; + [Throws] MediaMetadataInit getMetadata(); diff --git a/src/dom/media/mediacontrol/MediaController-cpp.patch b/src/dom/media/mediacontrol/MediaController-cpp.patch index 562756783..68b730922 100644 --- a/src/dom/media/mediacontrol/MediaController-cpp.patch +++ b/src/dom/media/mediacontrol/MediaController-cpp.patch @@ -1,5 +1,5 @@ diff --git a/dom/media/mediacontrol/MediaController.cpp b/dom/media/mediacontrol/MediaController.cpp -index 3f08d24d4ed56bb72ed513ed602b2c8fa48afe7b..690d9abdb0ab8efc019dd606743b82504834faa0 100644 +index 3f08d24d4ed56bb72ed513ed602b2c8fa48afe7b..98dfe4df48f5daebd2b619f0d4d4eb3ac873a66f 100644 --- a/dom/media/mediacontrol/MediaController.cpp +++ b/dom/media/mediacontrol/MediaController.cpp @@ -51,6 +51,25 @@ void MediaController::GetSupportedKeys( @@ -28,3 +28,11 @@ index 3f08d24d4ed56bb72ed513ed602b2c8fa48afe7b..690d9abdb0ab8efc019dd606743b8250 void MediaController::GetMetadata(MediaMetadataInit& aMetadata, ErrorResult& aRv) { if (!IsActive() || mShutdown) { +@@ -412,6 +431,7 @@ void MediaController::SetIsInPictureInPictureMode( + ForceToBecomeMainControllerIfNeeded(); + UpdateDeactivationTimerIfNeeded(); + mPictureInPictureModeChangedEvent.Notify(mIsInPictureInPictureMode); ++ DispatchAsyncEvent(u"pictureinpicturemodechange"_ns); + } + + void MediaController::NotifyMediaFullScreenState(uint64_t aBrowsingContextId, From 658e7eac1c2751b5d83903ee4cca379952ea83a7 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Mon, 17 Mar 2025 20:21:51 +0700 Subject: [PATCH 28/62] Null check just in case.. --- src/browser/base/zen-components/ZenMediaController.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index c9ef00ac2..1e181f5b0 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -374,7 +374,7 @@ class ZenMediaController { } _onMetadataChange(event) { - if (event.target.id !== this._currentMediaController.id) return; + if (event.target.id !== this._currentMediaController?.id) return; this.updatePipButton(); const metadata = event.target.getMetadata(); @@ -383,7 +383,7 @@ class ZenMediaController { } _onPictureInPictureModeChange(event) { - if (event.target.id !== this._currentMediaController.id) return; + if (event.target.id !== this._currentMediaController?.id) return; if (event.target.isBeingUsedInPIPModeOrFullscreen) { this.hideMediaControls(); this.mediaControlBar.setAttribute('pip', ''); From 0d968890189a72ea9872f96b1c1bb45eee923c3b Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Mon, 17 Mar 2025 20:22:20 +0100 Subject: [PATCH 29/62] fix: update media controller logic and improve CSS styles for better layout --- src/browser/base/content/browser-box-inc-xhtml.patch | 4 ++-- src/browser/base/content/zen-styles/zen-glance.css | 6 +++++- src/browser/base/zen-components/ZenMediaController.mjs | 3 ++- src/browser/themes/linux/browser-css.patch | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/browser/base/content/browser-box-inc-xhtml.patch b/src/browser/base/content/browser-box-inc-xhtml.patch index 5a4860b5d..3728cc0e3 100644 --- a/src/browser/base/content/browser-box-inc-xhtml.patch +++ b/src/browser/base/content/browser-box-inc-xhtml.patch @@ -1,8 +1,8 @@ diff --git a/browser/base/content/browser-box.inc.xhtml b/browser/base/content/browser-box.inc.xhtml -index 7f71abe7d80e4c09dd088517ec9ef106c7cb8654..7e764f08346a048fd352d7f7c06ea434f9b19903 100644 +index 7d7e8697f02f90d4f336c9ab0a73a89848e0c21c..2fd19f3b43db4bdd99e65fecd1481f80d4541a7a 100644 --- a/browser/base/content/browser-box.inc.xhtml +++ b/browser/base/content/browser-box.inc.xhtml -@@ -22,7 +22,14 @@ +@@ -23,7 +23,14 @@ diff --git a/src/browser/base/content/zen-styles/zen-glance.css b/src/browser/base/content/zen-styles/zen-glance.css index 9b1935495..8dcd4513f 100644 --- a/src/browser/base/content/zen-styles/zen-glance.css +++ b/src/browser/base/content/zen-styles/zen-glance.css @@ -49,6 +49,10 @@ & label { display: none; + + &::before { + text-overflow: unset; + } } & image { @@ -73,7 +77,7 @@ color: white; fill: white; & label { - max-width: 100px; + max-width: 4rem; margin-left: 8px; } diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index e4d304072..d41991c5f 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -59,6 +59,7 @@ class ZenMediaController { window.addEventListener('TabClose', (event) => { const linkedBrowser = event.target.linkedBrowser; + if (!linkedBrowser?.browsingContext?.mediaController) return; this.deinitMediaController( linkedBrowser.browsingContext.mediaController, true, @@ -109,7 +110,7 @@ class ZenMediaController { mediaController.removeEventListener('deactivated', this.onDeactivated); this.mediaControllersMap.delete(mediaController.id); - this.pipEligibilityMap.delete(retrievedMediaController.browser.browserId); + this.pipEligibilityMap.delete(retrievedMediaController?.browser?.browserId); } if (shouldOverride) { diff --git a/src/browser/themes/linux/browser-css.patch b/src/browser/themes/linux/browser-css.patch index 8c5ec4c6e..433a109c0 100644 --- a/src/browser/themes/linux/browser-css.patch +++ b/src/browser/themes/linux/browser-css.patch @@ -1,5 +1,5 @@ diff --git a/browser/themes/linux/browser.css b/browser/themes/linux/browser.css -index a9276a678f16a67e2a003474203c37cb5c9300ad..20cb1b022f7a94ad553f5e6df48014ee646f93ed 100644 +index dc95772553ef7130c27c1122178ff99028b601f2..81f7dbb40c35168376ca84eebfa9fba8d314cb90 100644 --- a/browser/themes/linux/browser.css +++ b/browser/themes/linux/browser.css @@ -42,21 +42,25 @@ From 630152b91e130585fb47949dc2404bf20f58f5b7 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Mon, 17 Mar 2025 20:41:24 +0100 Subject: [PATCH 30/62] feat: enhance panel UI positioning and improve hover state handling --- src/browser/base/content/ZenUIManager.mjs | 4 ++++ .../base/zen-components/ZenCompactMode.mjs | 8 ++++++- .../content/panelUI-inc-xhtml.patch | 24 ++++++++----------- .../customizableui/content/panelUI-js.patch | 21 ++++++++-------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 5a3089c5b..6b4226e74 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -261,6 +261,10 @@ var gZenUIManager = { this._toastContainer.setAttribute('hidden', 'true'); } }, + + get panelUIPosition() { + return gZenVerticalTabsManager._hasSetSingleToolbar ? 'bottomleft topleft' : 'bottomright topright'; + }, }; var gZenVerticalTabsManager = { diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 87aaf6389..9ae8232cc 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -40,6 +40,11 @@ var gZenCompactModeManager = { // Clear hover states when window state changes (minimize, maximize, etc.) window.addEventListener('sizemodechange', () => this._clearAllHoverStates()); + + window.addEventListener('mouseenter', (event) => { + const buttons = gZenVerticalTabsManager.actualWindowButtons; + buttons.removeAttribute('zen-has-hover'); + }); }, get preference() { @@ -363,13 +368,14 @@ var gZenCompactModeManager = { let target = this.hoverableElements[i].element; const onEnter = (event) => { if (event.type === 'mouseenter' && !event.target.matches(':hover')) return; + // Dont register the hover if the urlbar is floating and we are hovering over it + if (event.target.querySelector('#urlbar[zen-floating-urlbar]')) return; this.clearFlashTimeout('has-hover' + target.id); window.requestAnimationFrame(() => target.setAttribute('zen-has-hover', 'true')); }; const onLeave = (event) => { if (AppConstants.platform == 'macosx') { - 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 ( diff --git a/src/browser/components/customizableui/content/panelUI-inc-xhtml.patch b/src/browser/components/customizableui/content/panelUI-inc-xhtml.patch index 8e845316c..27e47d2fb 100644 --- a/src/browser/components/customizableui/content/panelUI-inc-xhtml.patch +++ b/src/browser/components/customizableui/content/panelUI-inc-xhtml.patch @@ -1,17 +1,13 @@ diff --git a/browser/components/customizableui/content/panelUI.inc.xhtml b/browser/components/customizableui/content/panelUI.inc.xhtml -index 956a6ae45d7adbec1513c5af528ebb687a4b7d0d..83b23e84cb6895497c1346f7c4aff15173e67b5c 100644 +index c78f08bdd3fc4d01e10552ef65c2d5813dd053e8..154fb1de2ab9384937d02c14cb7c9c607b330da9 100644 --- a/browser/components/customizableui/content/panelUI.inc.xhtml +++ b/browser/components/customizableui/content/panelUI.inc.xhtml -@@ -81,9 +81,10 @@ - - - -- -+ -+#if 0 - -- -+#endif - - - +@@ -132,7 +132,7 @@ + Date: Mon, 17 Mar 2025 20:51:47 +0100 Subject: [PATCH 31/62] fix: change mouse event from 'mouseenter' to 'mouseover' for better hover state handling --- src/browser/base/zen-components/ZenCompactMode.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 9ae8232cc..2456811c8 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -41,7 +41,7 @@ var gZenCompactModeManager = { // Clear hover states when window state changes (minimize, maximize, etc.) window.addEventListener('sizemodechange', () => this._clearAllHoverStates()); - window.addEventListener('mouseenter', (event) => { + window.addEventListener('mouseover', () => { const buttons = gZenVerticalTabsManager.actualWindowButtons; buttons.removeAttribute('zen-has-hover'); }); @@ -376,6 +376,7 @@ var gZenCompactModeManager = { const onLeave = (event) => { if (AppConstants.platform == 'macosx') { + 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 ( From dcb3e79f646f3cf13e9f704f545e513e216a68eb Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Mon, 17 Mar 2025 21:02:25 +0100 Subject: [PATCH 32/62] fix: refine mouse event handling for macOS window buttons to improve hover state accuracy --- src/browser/base/zen-components/ZenCompactMode.mjs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 2456811c8..41355a9cc 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -41,10 +41,13 @@ var gZenCompactModeManager = { // Clear hover states when window state changes (minimize, maximize, etc.) window.addEventListener('sizemodechange', () => this._clearAllHoverStates()); - window.addEventListener('mouseover', () => { - const buttons = gZenVerticalTabsManager.actualWindowButtons; - buttons.removeAttribute('zen-has-hover'); - }); + if (AppConstants.platform == 'macosx') { + window.addEventListener('mouseover', (event) => { + const buttons = gZenVerticalTabsManager.actualWindowButtons; + if (event.target.closest('.titlebar-buttonbox-container') === buttons) return; + buttons.removeAttribute('zen-has-hover'); + }); + } }, get preference() { From 072bc0269c6e25da5fe54c815d713b1d2efcdaac Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 18 Mar 2025 00:10:38 +0100 Subject: [PATCH 33/62] refactor: remove unused workspace icon strip preference and related styles --- l10n | 2 +- src/browser/app/profile/zen-browser.js | 1 - .../content/zen-styles/zen-animations.css | 8 +- .../content/zen-styles/zen-media-controls.css | 18 ++- .../base/content/zen-styles/zen-popup.css | 4 +- .../zen-styles/zen-tabs/vertical-tabs.css | 23 ++- .../base/content/zen-styles/zen-theme.css | 4 +- .../content/zen-styles/zen-workspaces.css | 152 +++++++----------- .../base/zen-components/ZenCompactMode.mjs | 8 +- .../zen-components/ZenMediaController.mjs | 9 +- .../base/zen-components/ZenWorkspaces.mjs | 116 +++++-------- .../components/preferences/zen-settings.js | 5 - .../preferences/zenTabsManagement.inc.xhtml | 3 - 13 files changed, 142 insertions(+), 211 deletions(-) diff --git a/l10n b/l10n index 0bc81a3d4..fdf67a1fe 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit 0bc81a3d4fc7f2fdcd99b7a2168db0c4f19bdaa9 +Subproject commit fdf67a1fe692e0af842dde2113bfefb9363e7893 diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index dae00c7d3..84fe71202 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -201,7 +201,6 @@ pref('zen.startup.smooth-scroll-in-tabs', true); pref('zen.workspaces.disabled_for_testing', false); pref('zen.workspaces.hide-deactivated-workspaces', false); pref('zen.workspaces.hide-default-container-indicator', true); -pref('zen.workspaces.show-icon-strip', true); pref('zen.workspaces.force-container-workspace', false); pref('zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', false); pref('zen.workspaces.show-workspace-indicator', true); diff --git a/src/browser/base/content/zen-styles/zen-animations.css b/src/browser/base/content/zen-styles/zen-animations.css index 2ea56928b..f30456e67 100644 --- a/src/browser/base/content/zen-styles/zen-animations.css +++ b/src/browser/base/content/zen-styles/zen-animations.css @@ -293,18 +293,18 @@ @keyframes zen-back-and-forth-text { 0%, - 20% { + 10% { transform: translateX(0); left: 0; } - 50%, - 60% { + 45%, + 65% { transform: translateX(calc(-100% - 5px)); left: 100%; } - 80%, + 90%, 100% { transform: translateX(0); left: 0; diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index 8be6a2545..734634406 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -71,6 +71,12 @@ height: calc(var(--progress-height) * 2); border-radius: 50%; cursor: pointer; + transform: scale(0); + transition: transform 0.15s ease-out; + } + + &:hover::-moz-range-thumb { + transform: scale(1); } } @@ -121,8 +127,8 @@ } } - toolbaritem { - --zen-media-control-bg: light-dark(rgb(255, 255, 255), rgb(10, 10, 10)) !important; + & > toolbaritem { + --zen-media-control-bg: light-dark(rgba(255, 255, 255, 0.87), rgba(0, 0, 0, 0.87)); flex-grow: 1; padding: 0; transition: padding 0.3s ease-out; @@ -131,9 +137,11 @@ bottom: 0; padding: 4px 6px; border-radius: var(--border-radius-medium); - background: var(--zen-media-control-bg) !important; + box-shadow: 0 0 6px rgba(0, 0, 0, 0.3); + background-color: var(--zen-media-control-bg); + backdrop-filter: saturate(3) contrast(2) blur(10px); width: 100%; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.05); + will-change: transform; } .show-on-hover { @@ -227,7 +235,7 @@ position: relative; /* For the animation */ &[overflow] { - animation: zen-back-and-forth-text 8s infinite ease-in-out; + animation: zen-back-and-forth-text 10s infinite ease-in-out; } } } diff --git a/src/browser/base/content/zen-styles/zen-popup.css b/src/browser/base/content/zen-styles/zen-popup.css index 5d0fb018b..b8ce600d5 100644 --- a/src/browser/base/content/zen-styles/zen-popup.css +++ b/src/browser/base/content/zen-styles/zen-popup.css @@ -360,9 +360,9 @@ menuitem { & .zen-toast { padding: 0.9rem 0.8rem; border-radius: 12px; - background-color: var(--button-primary-bgcolor); + background: linear-gradient(170deg, light-dark(rgb(187, 187, 187), rgb(240, 240, 240)) -40%, var(--zen-primary-color) 140%); color: var(--button-primary-color); - box-shadow: var(--zen-big-shadow); + box-shadow: 0 0 16px 3px rgba(0,0,0,.1); display: flex; font-weight: 500; gap: 5px; diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 506f7c586..0af7dae9a 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -255,13 +255,20 @@ } & .tabbrowser-tab { - transition: scale 0.07s ease; + &, + & .tab-content > image { + transition: scale 0.07s ease; + } &[zen-empty-tab] { display: none; } - #tabbrowser-tabs:not([movingtab]) &:active { + #tabbrowser-tabs:not([movingtab]) &:active:not(:has(.tab-content > image:active)) { + scale: var(--zen-active-tab-scale); + } + + #tabbrowser-tabs:not([movingtab]) & .tab-content > image:active { scale: var(--zen-active-tab-scale); } @@ -462,10 +469,6 @@ margin-top: 0; } - & #zen-workspaces-button[as-button='true'] { - width: calc(100% - 10px) !important; - } - & .zen-current-workspace-indicator-icon[no-icon='true'] { display: none; } @@ -762,14 +765,6 @@ } & #zen-workspaces-button { flex-direction: column; - &:not([as-button='true']) { - & toolbarbutton { - &[active='true']::after { - bottom: 50% !important; - transform: translateY(50%) !important; - } - } - } } } diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index 8f12e26b9..3ec3f6061 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -155,8 +155,8 @@ --input-bgcolor: var(--zen-colors-tertiary) !important; --input-border-color: var(--zen-input-border-color) !important; - --zen-themed-toolbar-bg: light-dark(rgb(240, 240, 244), #161616); - --zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #161616); + --zen-themed-toolbar-bg: light-dark(rgb(240, 240, 244), #171717); + --zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #171717); --zen-workspace-indicator-height: 45px; diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index 8e46cae98..daf77b3c2 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -17,98 +17,73 @@ display: none !important; } - &:not([as-button='true']) { - --toolbarbutton-hover-background: transparent !important; - border-radius: var(--zen-button-border-radius) !important; - background: transparent; - padding: 2px; - appearance: unset !important; - height: fit-content; - gap: 3px; + --toolbarbutton-hover-background: transparent !important; + border-radius: var(--zen-button-border-radius) !important; + background: transparent; + padding: 2px; + appearance: unset !important; + height: fit-content; + gap: 3px; - & toolbarbutton { - margin: auto; - width: 25px; - display: flex; - justify-content: center; - padding: 0 !important; - align-items: center; - position: relative; - - @media (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') { - &:not([active='true']):not(:hover) { - &::after { - content: ''; - position: absolute; - width: 4px; - border-radius: 99px; - height: 4px; - background: color-mix( - in srgb, - var(--zen-primary-color) 10%, - light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)) 90% - ); - left: 50%; - top: 50%; - filter: saturate(140%) brightness(110%) !important; - transform: translate(-50%, -50%); - } - - & .zen-workspace-icon { - display: none; - } - } - } - - @media not (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') { - & { - filter: grayscale(1); - opacity: 0.5; - transition: - filter 0.2s, - opacity 0.2s; - } - - &[active='true'], - &:hover { - filter: grayscale(0); - opacity: 1; - } - - &:hover { - background-color: var(--zen-toolbar-element-bg); - } - } - } - } - - &[as-button='true'] { - border-radius: var(--tab-border-radius); - - &:hover { - background: var(--toolbarbutton-hover-background); - } - } - - &[as-button='true'] { + & toolbarbutton { margin: auto; - padding: var(--toolbarbutton-inner-padding) !important; - width: calc(2 * var(--toolbarbutton-inner-padding) + 16px) !important; - height: calc(2 * var(--toolbarbutton-inner-padding) + 16px) !important; - border-radius: var(--tab-border-radius) !important; + width: 25px; + display: flex; + justify-content: center; + padding: 0 !important; + align-items: center; + position: relative; - :root:not([zen-sidebar-expanded='true']) #navigator-toolbox & { - & .zen-workspace-sidebar-name { - display: none; - } + @media (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') { + &:not([active='true']):not(:hover) { + &::after { + content: ''; + position: absolute; + width: 4px; + border-radius: 99px; + height: 4px; + background: color-mix( + in srgb, + var(--zen-primary-color) 10%, + light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)) 90% + ); + left: 50%; + top: 50%; + filter: saturate(140%) brightness(110%) !important; + transform: translate(-50%, -50%); + } - & .zen-workspace-sidebar-icon { - margin-inline-end: 0 !important; + & .zen-workspace-icon { + display: none; + } } } - &:hover { - background: var(--toolbarbutton-hover-background) !important; + & .zen-workspace-icon[no-icon='true'] { + width: 6px; + height: 6px; + background: light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)); + border-radius: 50%; + } + + @media not (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') { + & { + filter: grayscale(1); + opacity: 0.5; + transition: + filter 0.2s, + opacity 0.2s; + } + + &[active='true'], + &:hover { + filter: grayscale(0); + opacity: 1; + } + + &:hover { + background-color: var(--zen-toolbar-element-bg); + } } } } @@ -133,13 +108,6 @@ /** Keep these selectors in sync with the ones in vertical-tabs.css */ #navigator-toolbox { - & #zen-workspaces-button[as-button='true'] { - width: calc(100% - var(--toolbarbutton-outer-padding)); - margin: 2px; - min-width: calc(2 * var(--toolbarbutton-inner-padding) + 16px); - height: calc(2 * var(--toolbarbutton-inner-padding) + 16px); - } - & #zen-workspaces-button .zen-workspace-sidebar-name { display: block; } diff --git a/src/browser/base/zen-components/ZenCompactMode.mjs b/src/browser/base/zen-components/ZenCompactMode.mjs index 9ae8232cc..49310770f 100644 --- a/src/browser/base/zen-components/ZenCompactMode.mjs +++ b/src/browser/base/zen-components/ZenCompactMode.mjs @@ -77,7 +77,7 @@ var gZenCompactModeManager = { }, get sidebarIsOnRight() { - if (this._sidebarIsOnRight) { + if (typeof this._sidebarIsOnRight !== 'undefined') { return this._sidebarIsOnRight; } this._sidebarIsOnRight = Services.prefs.getBoolPref('zen.tabs.vertical.right-side'); @@ -342,9 +342,9 @@ var gZenCompactModeManager = { }, flashElement(element, duration, id, attrName = 'flash-popup') { - if (element.matches(':hover')) { - return; - } + //if (element.matches(':hover')) { + // return; + //} if (this._flashTimeouts[id]) { clearTimeout(this._flashTimeouts[id]); } else { diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index c7b5d8eb1..0096f971a 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -146,6 +146,10 @@ class ZenMediaController { if (!this.mediaControlBar.hasAttribute('hidden')) return; this.updatePipButton(); + const mediaInfoElements = [this.mediaTitle, this.mediaArtist]; + for (const element of mediaInfoElements) { + element.removeAttribute('overflow'); // So we can properly recalculate the overflow + } this.mediaControlBar.removeAttribute('hidden'); window.requestAnimationFrame(() => { @@ -161,12 +165,11 @@ class ZenMediaController { }, {} ); - this.addLabelOverflows(); + this.addLabelOverflows(mediaInfoElements); }); } - addLabelOverflows() { - const elements = [this.mediaTitle, this.mediaArtist]; + addLabelOverflows(elements) { for (const element of elements) { const parent = element.parentElement; if (element.scrollWidth > parent.clientWidth) { diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 5af8f2bc7..01c436c58 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -57,13 +57,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { XPCOMUtils.defineLazyPreferenceGetter(this, 'activationMethod', 'zen.workspaces.scroll-modifier-key', 'ctrl'); XPCOMUtils.defineLazyPreferenceGetter(this, 'naturalScroll', 'zen.workspaces.natural-scroll', true); XPCOMUtils.defineLazyPreferenceGetter(this, 'shouldWrapAroundNavigation', 'zen.workspaces.wrap-around-navigation', true); - XPCOMUtils.defineLazyPreferenceGetter( - this, - 'shouldShowIconStrip', - 'zen.workspaces.show-icon-strip', - true, - this._expandWorkspacesStrip.bind(this) - ); XPCOMUtils.defineLazyPreferenceGetter( this, 'shouldForceContainerTabsToWorkspace', @@ -139,7 +132,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { async _createDefaultWorkspaceIfNeeded() { const workspaces = await this._workspaces(); if (!workspaces.workspaces.length) { - await this.createAndSaveWorkspace('Default Workspace', true, '🏠', true); + await this.createAndSaveWorkspace('Default', true, null, true); this._workspaceCache = null; } } @@ -1323,82 +1316,55 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { button.setAttribute('showInPrivateBrowsing', 'false'); button.setAttribute('tooltiptext', 'Workspaces'); - if (this.shouldShowIconStrip) { - let workspaces = await this._workspaces(); + let workspaces = await this._workspaces(); - for (let workspace of workspaces.workspaces) { - let workspaceButton = browser.document.createXULElement('toolbarbutton'); - workspaceButton.className = 'subviewbutton'; - workspaceButton.setAttribute('tooltiptext', workspace.name); - workspaceButton.setAttribute('zen-workspace-id', workspace.uuid); + for (let workspace of workspaces.workspaces) { + let workspaceButton = browser.document.createXULElement('toolbarbutton'); + workspaceButton.className = 'subviewbutton'; + workspaceButton.setAttribute('tooltiptext', workspace.name); + workspaceButton.setAttribute('zen-workspace-id', workspace.uuid); - if (this.isWorkspaceActive(workspace)) { - workspaceButton.setAttribute('active', 'true'); - } else { - workspaceButton.removeAttribute('active'); - } - if (workspace.default) { - workspaceButton.setAttribute('default', 'true'); - } else { - workspaceButton.removeAttribute('default'); - } - - workspaceButton.addEventListener('click', async (event) => { - if (event.button !== 0) { - return; - } - await this.changeWorkspace(workspace); - }); - - let icon = browser.document.createXULElement('div'); - icon.className = 'zen-workspace-icon'; - icon.textContent = this.getWorkspaceIcon(workspace); - workspaceButton.appendChild(icon); - button.appendChild(workspaceButton); - } - - if (workspaces.workspaces.length <= 1) { - button.setAttribute('dont-show', true); + if (this.isWorkspaceActive(workspace)) { + workspaceButton.setAttribute('active', 'true'); } else { - button.removeAttribute('dont-show'); + workspaceButton.removeAttribute('active'); + } + if (workspace.default) { + workspaceButton.setAttribute('default', 'true'); + } else { + workspaceButton.removeAttribute('default'); } - this._workspaceButtonContextMenuListener = (event) => { - event.preventDefault(); - event.stopPropagation(); - this.openWorkspacesDialog(event); - }; - button.addEventListener('contextmenu', this._workspaceButtonContextMenuListener.bind(browser.ZenWorkspaces)); - } else { - let activeWorkspace = await this.getActiveWorkspace(); - if (activeWorkspace) { - button.setAttribute('as-button', 'true'); - button.classList.add('toolbarbutton-1', 'zen-sidebar-action-button'); - - this._workspacesButtonClickListener = browser.ZenWorkspaces.openWorkspacesDialog.bind(browser.ZenWorkspaces); - button.addEventListener('click', this._workspacesButtonClickListener); - - const wrapper = browser.document.createXULElement('hbox'); - wrapper.className = 'zen-workspace-sidebar-wrapper'; - - const icon = browser.document.createXULElement('div'); - icon.className = 'zen-workspace-sidebar-icon'; - icon.textContent = this.getWorkspaceIcon(activeWorkspace); - - const name = browser.document.createXULElement('div'); - name.className = 'zen-workspace-sidebar-name'; - name.textContent = activeWorkspace.name; - - if (!this.workspaceHasIcon(activeWorkspace)) { - icon.setAttribute('no-icon', 'true'); + workspaceButton.addEventListener('click', async (event) => { + if (event.button !== 0) { + return; } + await this.changeWorkspace(workspace); + }); - wrapper.appendChild(icon); - wrapper.appendChild(name); - - button.appendChild(wrapper); + let icon = browser.document.createXULElement('div'); + icon.className = 'zen-workspace-icon'; + if (this.workspaceHasIcon(workspace)) { + icon.textContent = this.getWorkspaceIcon(workspace); + } else { + icon.setAttribute('no-icon', 'true'); } + workspaceButton.appendChild(icon); + button.appendChild(workspaceButton); } + + if (workspaces.workspaces.length <= 1) { + button.setAttribute('dont-show', true); + } else { + button.removeAttribute('dont-show'); + } + + this._workspaceButtonContextMenuListener = (event) => { + event.preventDefault(); + event.stopPropagation(); + this.openWorkspacesDialog(event); + }; + button.addEventListener('contextmenu', this._workspaceButtonContextMenuListener.bind(browser.ZenWorkspaces)); } closeWorkspacesSubView() { diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index 19892d0fa..6383e9b3f 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -944,11 +944,6 @@ Preferences.addAll([ type: 'bool', default: true, }, - { - id: 'zen.workspaces.show-icon-strip', - type: 'bool', - default: true, - }, { id: 'zen.tab-unloader.enabled', type: 'bool', diff --git a/src/browser/components/preferences/zenTabsManagement.inc.xhtml b/src/browser/components/preferences/zenTabsManagement.inc.xhtml index 458e05120..7e148a9b6 100644 --- a/src/browser/components/preferences/zenTabsManagement.inc.xhtml +++ b/src/browser/components/preferences/zenTabsManagement.inc.xhtml @@ -20,9 +20,6 @@ - From b0f7a06749eff921d94ffc49451d1675cf7f9c3c Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 18 Mar 2025 00:20:23 +0100 Subject: [PATCH 34/62] chore: update subproject commit reference in localization --- l10n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l10n b/l10n index fdf67a1fe..c5a36ae64 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit fdf67a1fe692e0af842dde2113bfefb9363e7893 +Subproject commit c5a36ae64fb0d040c3fb7f0392f8c86f2002f238 From 5e32c09d9f78dd71ec0997e680dd8d300e00ac43 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Tue, 18 Mar 2025 00:21:28 +0100 Subject: [PATCH 35/62] Lint before release --- src/browser/base/content/zen-styles/zen-popup.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-popup.css b/src/browser/base/content/zen-styles/zen-popup.css index b8ce600d5..8bb7e3367 100644 --- a/src/browser/base/content/zen-styles/zen-popup.css +++ b/src/browser/base/content/zen-styles/zen-popup.css @@ -362,7 +362,7 @@ menuitem { border-radius: 12px; background: linear-gradient(170deg, light-dark(rgb(187, 187, 187), rgb(240, 240, 240)) -40%, var(--zen-primary-color) 140%); color: var(--button-primary-color); - box-shadow: 0 0 16px 3px rgba(0,0,0,.1); + box-shadow: 0 0 16px 3px rgba(0, 0, 0, 0.1); display: flex; font-weight: 500; gap: 5px; From bfe83dd653099c00c96347c527966b57cfc875b9 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Tue, 18 Mar 2025 08:56:10 +0700 Subject: [PATCH 36/62] enhance media focus handling to support sidebar opening --- src/browser/base/zen-components/ZenMediaController.mjs | 5 ++++- src/browser/base/zen-components/ZenSidebarManager.mjs | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 0096f971a..6aded7022 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -428,7 +428,10 @@ class ZenMediaController { } onMediaFocus() { - this._currentMediaController?.focus(); + if (!this._currentBrowser) return; + const sidebarId = this._currentBrowser.getAttribute('zen-sidebar-id'); + if (sidebarId) gZenBrowserManagerSidebar.open(sidebarId); + else this._currentMediaController?.focus(); } onMediaMute() { diff --git a/src/browser/base/zen-components/ZenSidebarManager.mjs b/src/browser/base/zen-components/ZenSidebarManager.mjs index 2b695a35d..3dfaa8a99 100644 --- a/src/browser/base/zen-components/ZenSidebarManager.mjs +++ b/src/browser/base/zen-components/ZenSidebarManager.mjs @@ -280,8 +280,10 @@ class ZenBrowserManagerSidebar extends ZenDOMOperatedFeature { this.close(); } - open() { + open(id = null) { let sidebar = document.getElementById('zen-sidebar-web-panel'); + if (id) this._currentPanel = id; + sidebar.removeAttribute('hidden'); this.update(); } From ad04961d196a6ec20211696aec85c211b2089ad9 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Tue, 18 Mar 2025 12:34:54 +0100 Subject: [PATCH 37/62] refactor: adjust toast animation duration and update styling for improved visibility --- src/browser/base/content/ZenUIManager.mjs | 2 +- src/browser/base/content/zen-styles/zen-popup.css | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/browser/base/content/ZenUIManager.mjs b/src/browser/base/content/ZenUIManager.mjs index 6b4226e74..08f481493 100644 --- a/src/browser/base/content/ZenUIManager.mjs +++ b/src/browser/base/content/ZenUIManager.mjs @@ -250,7 +250,7 @@ var gZenUIManager = { const toast = this._createToastElement(messageId, options); this._toastContainer.removeAttribute('hidden'); this._toastContainer.appendChild(toast); - await this.motion.animate(toast, { opacity: [0, 1], scale: [0.8, 1] }, { type: 'spring', bounce: 0.5, duration: 0.5 }); + await this.motion.animate(toast, { opacity: [0, 1], scale: [0.8, 1] }, { type: 'spring', bounce: 0.5, duration: 0.7 }); await new Promise((resolve) => setTimeout(resolve, 3000)); await this.motion.animate(toast, { opacity: [1, 0], scale: [1, 0.9] }, { duration: 0.2, bounce: 0 }); const toastHeight = toast.getBoundingClientRect().height; diff --git a/src/browser/base/content/zen-styles/zen-popup.css b/src/browser/base/content/zen-styles/zen-popup.css index 8bb7e3367..721664d97 100644 --- a/src/browser/base/content/zen-styles/zen-popup.css +++ b/src/browser/base/content/zen-styles/zen-popup.css @@ -360,9 +360,10 @@ menuitem { & .zen-toast { padding: 0.9rem 0.8rem; border-radius: 12px; - background: linear-gradient(170deg, light-dark(rgb(187, 187, 187), rgb(240, 240, 240)) -40%, var(--zen-primary-color) 140%); + background: linear-gradient(170deg, var(--zen-primary-color) -40%, color-mix(in srgb, var(--zen-primary-color) 85%, #0f0f0f 15%)); color: var(--button-primary-color); - box-shadow: 0 0 16px 3px rgba(0, 0, 0, 0.1); + box-shadow: 0 0 14px 3px rgba(0, 0, 0, 0.05); + border: 1px solid rgba(0, 0, 0, 0.1); display: flex; font-weight: 500; gap: 5px; From 025f994c62d6739b6bb2d427f35670f339725b51 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Tue, 18 Mar 2025 15:46:13 +0100 Subject: [PATCH 38/62] fix: enhance tab unloading logic with permitUnload check and update candidate version and update to firefox `136.0.2` --- README.md | 2 +- firefox-cache/l10n-last-commit-hash | 2 +- scripts/update_ff.py | 6 ++++++ src/browser/base/content/zen-styles/zen-popup.css | 6 +++++- .../base/content/zen-styles/zen-tabs/vertical-tabs.css | 2 +- src/browser/base/zen-components/ZenPinnedTabManager.mjs | 7 +++++-- src/browser/base/zen-components/ZenTabUnloader.mjs | 9 ++++++--- surfer.json | 6 +++--- 8 files changed, 28 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e38fb038e..d1ed17ff0 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ ## 🖥️ Compatibility -Zen is currently built using Firefox version `136.0.1`! 🚀 +Zen is currently built using Firefox version `136.0.2`! 🚀 - [`Zen Twilight`](https://zen-browser.app/download?twilight) - Is currently built using Firefox version `RC 136.0`! - Check out the latest [release notes](https://zen-browser.app/release-notes)! diff --git a/firefox-cache/l10n-last-commit-hash b/firefox-cache/l10n-last-commit-hash index 2991f1839..d1765242d 100644 --- a/firefox-cache/l10n-last-commit-hash +++ b/firefox-cache/l10n-last-commit-hash @@ -1 +1 @@ -6ad0ab3c43a6208d8bcd997b40e802fccd48ba0a \ No newline at end of file +6013afe489c3d5e19c5f0d0f6c3f94b91f5bd7d1 \ No newline at end of file diff --git a/scripts/update_ff.py b/scripts/update_ff.py index 40f94f84b..0784d2f9b 100644 --- a/scripts/update_ff.py +++ b/scripts/update_ff.py @@ -64,6 +64,12 @@ def update_l10n_last_commit_hash(): if not os.path.exists("firefox-cache"): os.mkdir("firefox-cache") os.system("cat l10n-temp/.git/refs/heads/main > firefox-cache/l10n-last-commit-hash") + # Remove new line character + data = "" + with open("firefox-cache/l10n-last-commit-hash", "r") as f: + data = f.read() + with open("firefox-cache/l10n-last-commit-hash", "w") as f: + f.write(data.strip()) except KeyboardInterrupt: print("Exiting...") shutil.rmtree("l10n-temp") diff --git a/src/browser/base/content/zen-styles/zen-popup.css b/src/browser/base/content/zen-styles/zen-popup.css index 721664d97..63fc98beb 100644 --- a/src/browser/base/content/zen-styles/zen-popup.css +++ b/src/browser/base/content/zen-styles/zen-popup.css @@ -360,7 +360,11 @@ menuitem { & .zen-toast { padding: 0.9rem 0.8rem; border-radius: 12px; - background: linear-gradient(170deg, var(--zen-primary-color) -40%, color-mix(in srgb, var(--zen-primary-color) 85%, #0f0f0f 15%)); + background: linear-gradient( + 170deg, + var(--zen-primary-color) -40%, + color-mix(in srgb, var(--zen-primary-color) 85%, #0f0f0f 15%) + ); color: var(--button-primary-color); box-shadow: 0 0 14px 3px rgba(0, 0, 0, 0.05); border: 1px solid rgba(0, 0, 0, 0.1); diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 0af7dae9a..5b0110255 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -269,7 +269,7 @@ } #tabbrowser-tabs:not([movingtab]) & .tab-content > image:active { - scale: var(--zen-active-tab-scale); + scale: 0.92; } & .tab-icon-image { diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index aae3f515b..f7c3bda56 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -510,6 +510,10 @@ case 'unload-switch': case 'reset-switch': case 'switch': + let { permitUnload } = selectedTab.linkedBrowser?.permitUnload(); + if (!permitUnload) { + return; + } this._handleTabSwitch(selectedTab); if (behavior.includes('reset')) { this._resetTabToStoredState(selectedTab); @@ -520,8 +524,7 @@ } // Do not unload about:* pages if (!selectedTab.linkedBrowser?.currentURI.spec.startsWith('about:')) { - gBrowser.explicitUnloadTabs([selectedTab]); - selectedTab.removeAttribute('linkedpanel'); + gZenTabUnloader.explicitUnloadTabs([selectedTab], { permitUnload }); } } break; diff --git a/src/browser/base/zen-components/ZenTabUnloader.mjs b/src/browser/base/zen-components/ZenTabUnloader.mjs index 01219d57a..5ea8f46fe 100644 --- a/src/browser/base/zen-components/ZenTabUnloader.mjs +++ b/src/browser/base/zen-components/ZenTabUnloader.mjs @@ -235,9 +235,9 @@ this.explicitUnloadTabs(tabs); } - explicitUnloadTabs(tabs) { + explicitUnloadTabs(tabs, extraArgs = {}) { for (let i = 0; i < tabs.length; i++) { - if (this.canUnloadTab(tabs[i], Date.now(), this.intervalUnloader.excludedUrls, true)) { + if (this.canUnloadTab(tabs[i], Date.now(), this.intervalUnloader.excludedUrls, true, extraArgs)) { this.unload(tabs[i]); } } @@ -259,7 +259,7 @@ } } - canUnloadTab(tab, currentTimestamp, excludedUrls, ignoreTimestamp = false) { + canUnloadTab(tab, currentTimestamp, excludedUrls, ignoreTimestamp = false, extraArgs = {}) { if ( (tab.pinned && !ignoreTimestamp) || tab.selected || @@ -271,6 +271,9 @@ tab.attention || tab.hasAttribute('glance-id') || tab.linkedBrowser?.zenModeActive || + (typeof extraArgs.permitUnload === 'undefined' + ? !tab.linkedBrowser?.permitUnload()?.permitUnload + : !extraArgs.permitUnload) || (tab.pictureinpicture && !ignoreTimestamp) || (tab.soundPlaying && !ignoreTimestamp) || (tab.zenIgnoreUnload && !ignoreTimestamp) || diff --git a/surfer.json b/surfer.json index 107a1a18c..4c8a87cce 100644 --- a/surfer.json +++ b/surfer.json @@ -5,8 +5,8 @@ "binaryName": "zen", "version": { "product": "firefox", - "version": "136.0.1", - "candidate": "136.0.1" + "version": "136.0.2", + "candidate": "136.0.2" }, "buildOptions": { "generateBranding": true @@ -53,4 +53,4 @@ "licenseType": "MPL-2.0" }, "updateHostname": "updates.zen-browser.app" -} +} \ No newline at end of file From 09c0f5143d3076c2796b5d8810dc890cc33a7a1b Mon Sep 17 00:00:00 2001 From: UnownPlain <38232575+UnownPlain@users.noreply.github.com> Date: Tue, 18 Mar 2025 18:45:20 -0400 Subject: [PATCH 39/62] Fix stable build release notes generation --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b45930535..27653b5bb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -517,6 +517,8 @@ jobs: repository: ./updates-server - name: Generate Release Notes + env: + RELEASE_BRANCH: ${{ inputs.update_branch }} run: bash .github/workflows/src/generate_release_notes.sh # If we are on Twilight, we want to just update the Twilight tag's release From 1f3b3f15ab15271cf2fdcc1c3b21cf7855aa317b Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Tue, 18 Mar 2025 23:57:05 +0100 Subject: [PATCH 40/62] chore: update subproject commit reference in localization --- l10n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l10n b/l10n index c5a36ae64..7c14b58a2 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit c5a36ae64fb0d040c3fb7f0392f8c86f2002f238 +Subproject commit 7c14b58a28845a131a00153eb11c8ca5395bf26b From 2609248564642dade0cabc5c491a4711895eb52f Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Wed, 19 Mar 2025 00:51:42 +0100 Subject: [PATCH 41/62] refactor: remove openWelcomeTab function to streamline tab management --- src/browser/base/zen-components/ZenWelcome.mjs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/browser/base/zen-components/ZenWelcome.mjs b/src/browser/base/zen-components/ZenWelcome.mjs index 9e19d08fd..bce632742 100644 --- a/src/browser/base/zen-components/ZenWelcome.mjs +++ b/src/browser/base/zen-components/ZenWelcome.mjs @@ -52,13 +52,6 @@ } } - function openWelcomeTab() { - const tab = window.gBrowser.addTrustedTab('https://zen-browser.app/welcome', { - inBackground: true, - }); - gBrowser.selectedTab = tab; - } - class ZenWelcomePages { constructor(pages) { this._currentPage = -1; @@ -410,7 +403,6 @@ _tabsToPinEssentials.push(createdTab); } openInitialPinTab(); - openWelcomeTab(); }, }, { From a53b3130c8a8aa8708d8d0f41d09f898b02c3c6e Mon Sep 17 00:00:00 2001 From: Sarangem <156000180+Sarangem@users.noreply.github.com> Date: Wed, 19 Mar 2025 07:47:02 +0000 Subject: [PATCH 42/62] Update flatpak manifest file Update variable $MESA_SHADER_CACHE_DIR to /var/cache/ which is mounted at ~/.var/app/$FLATPAK_ID/cache. Solves issue #3813 Signed-off-by: Sarangem <156000180+Sarangem@users.noreply.github.com> --- flatpak/app.zen_browser.zen.yml.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flatpak/app.zen_browser.zen.yml.template b/flatpak/app.zen_browser.zen.yml.template index a8f5adeac..20b242489 100644 --- a/flatpak/app.zen_browser.zen.yml.template +++ b/flatpak/app.zen_browser.zen.yml.template @@ -28,7 +28,7 @@ finish-args: - --system-talk-name=org.freedesktop.NetworkManager - --talk-name=org.a11y.Bus - --env=GTK_PATH=/app/lib/gtkmodules - - --env=MESA_SHADER_CACHE_DIR=$XDG_RUNTIME_DIR/app/$FLATPAK_ID/cache/mesa_shader_cache_db + - --env=MESA_SHADER_CACHE_DIR=/var/cache/mesa_shader_cache_db modules: - name: zen_browser buildsystem: simple From e01291afd66f90f93edb0006666b33cb0754210c Mon Sep 17 00:00:00 2001 From: noaione Date: Wed, 19 Mar 2025 18:54:26 +0700 Subject: [PATCH 43/62] fix(pinnedTab): not working on private window --- src/browser/base/zen-components/ZenPinnedTabManager.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index f7c3bda56..d091e0f2e 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -834,7 +834,7 @@ removeTabContainersDragoverClass() { this.dragIndicator.remove(); this._dragIndicator = null; - ZenWorkspaces.activeWorkspaceIndicator.removeAttribute('open'); + ZenWorkspaces.activeWorkspaceIndicator?.removeAttribute('open'); } get dragIndicator() { @@ -894,9 +894,9 @@ targetTab = targetTab?.group || targetTab; if (event.target.closest('.zen-current-workspace-indicator')) { this.removeTabContainersDragoverClass(); - ZenWorkspaces.activeWorkspaceIndicator.setAttribute('open', true); + ZenWorkspaces.activeWorkspaceIndicator?.setAttribute('open', true); } else { - ZenWorkspaces.activeWorkspaceIndicator.removeAttribute('open'); + ZenWorkspaces.activeWorkspaceIndicator?.removeAttribute('open'); } // If there's no valid target tab, nothing to do From 2cbec90c969ba2de3e012541ae3888928a66a197 Mon Sep 17 00:00:00 2001 From: Bellisario <72039923+Bellisario@users.noreply.github.com> Date: Wed, 19 Mar 2025 23:34:49 +0100 Subject: [PATCH 44/62] use tabular-nums on media controls --- src/browser/base/content/zen-styles/zen-media-controls.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/base/content/zen-styles/zen-media-controls.css b/src/browser/base/content/zen-styles/zen-media-controls.css index 734634406..3532afffb 100644 --- a/src/browser/base/content/zen-styles/zen-media-controls.css +++ b/src/browser/base/content/zen-styles/zen-media-controls.css @@ -163,6 +163,7 @@ font-size: x-small; opacity: 0.7; font-weight: 500; + font-variant-numeric: tabular-nums; } } From 37b5ab916ce946504381916c5d6897c7064d07a2 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Thu, 20 Mar 2025 08:47:07 +0700 Subject: [PATCH 45/62] fix(MediaController): restore scrollbar when updating ui & don't update time from other tab --- .../zen-components/ZenMediaController.mjs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 6aded7022..e6c7e9542 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -138,6 +138,7 @@ class ZenMediaController { .then(() => { this.mediaControlBar.setAttribute('hidden', 'true'); gZenUIManager.updateTabsToolbar(); + gZenUIManager.restoreScrollbarState(); }); } @@ -157,6 +158,7 @@ class ZenMediaController { this.mediaControlBar.querySelector('toolbaritem').getBoundingClientRect().height + 'px'; this.mediaControlBar.style.opacity = 0; gZenUIManager.updateTabsToolbar(); + gZenUIManager.restoreScrollbarState(); gZenUIManager.motion.animate( this.mediaControlBar, { @@ -210,6 +212,7 @@ class ZenMediaController { this.mediaArtist.textContent = metadata.artist || ''; gZenUIManager.updateTabsToolbar(); + gZenUIManager.restoreScrollbarState(); this._currentPosition = positionState.position; this._currentDuration = positionState.duration; @@ -277,15 +280,15 @@ class ZenMediaController { } _onPositionstateChange(event) { - if (event.target.id !== this._currentMediaController?.id) { - const mediaController = this.mediaControllersMap.get(event.target.id); - this.mediaControllersMap.set(event.target.id, { - ...mediaController, - position: event.position, - duration: event.duration, - lastUpdated: Date.now(), - }); - } + const mediaController = this.mediaControllersMap.get(event.target.id); + this.mediaControllersMap.set(event.target.id, { + ...mediaController, + position: event.position, + duration: event.duration, + lastUpdated: Date.now(), + }); + + if (event.target.id !== this._currentMediaController?.id) return; this._currentPosition = event.position; this._currentDuration = event.duration; From 2b1f2fe01907e5c8459420fe84a24c9418b61f4d Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Thu, 20 Mar 2025 10:49:06 +0700 Subject: [PATCH 46/62] feat: add minimize button to pip window --- .../pictureinpicture/content/player-js.patch | 16 ++++++++++ .../content/player-xhtml.patch | 29 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/toolkit/components/pictureinpicture/content/player-js.patch create mode 100644 src/toolkit/components/pictureinpicture/content/player-xhtml.patch diff --git a/src/toolkit/components/pictureinpicture/content/player-js.patch b/src/toolkit/components/pictureinpicture/content/player-js.patch new file mode 100644 index 000000000..ac2f0f4eb --- /dev/null +++ b/src/toolkit/components/pictureinpicture/content/player-js.patch @@ -0,0 +1,16 @@ +diff --git a/toolkit/components/pictureinpicture/content/player.js b/toolkit/components/pictureinpicture/content/player.js +index 9a4971d5d24dba6e543be8ea321c6be8c43ad859..b0788967e51736b1ec95daf96a1504bfd7c1dea7 100644 +--- a/toolkit/components/pictureinpicture/content/player.js ++++ b/toolkit/components/pictureinpicture/content/player.js +@@ -722,6 +722,11 @@ let Player = { + document.getElementById("large").click(); + break; + } ++ ++ case "minimize": { ++ this.closePipWindow({ reason: "CloseButton" }); ++ break; ++ } + } + // If the click came from a element that is not inside the subtitles settings panel + // then we want to hide the panel diff --git a/src/toolkit/components/pictureinpicture/content/player-xhtml.patch b/src/toolkit/components/pictureinpicture/content/player-xhtml.patch new file mode 100644 index 000000000..92d9b9543 --- /dev/null +++ b/src/toolkit/components/pictureinpicture/content/player-xhtml.patch @@ -0,0 +1,29 @@ +diff --git a/toolkit/components/pictureinpicture/content/player.xhtml b/toolkit/components/pictureinpicture/content/player.xhtml +index 440ce51e8e67e4d3a7bdcb78f38f2fb6684c9848..6b48a3178f9de460dd3b08728f5638ef2751de21 100644 +--- a/toolkit/components/pictureinpicture/content/player.xhtml ++++ b/toolkit/components/pictureinpicture/content/player.xhtml +@@ -52,13 +52,22 @@ + tabindex="10" + #endif + /> +- ++ +
From e0de3b410bc4e8b628660d60b39ccdb37baef76d Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Thu, 20 Mar 2025 10:51:23 +0700 Subject: [PATCH 47/62] add css --- .../shared/pictureinpicture/player-css.patch | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/toolkit/themes/shared/pictureinpicture/player-css.patch diff --git a/src/toolkit/themes/shared/pictureinpicture/player-css.patch b/src/toolkit/themes/shared/pictureinpicture/player-css.patch new file mode 100644 index 000000000..3a77b5c78 --- /dev/null +++ b/src/toolkit/themes/shared/pictureinpicture/player-css.patch @@ -0,0 +1,22 @@ +diff --git a/toolkit/themes/shared/pictureinpicture/player.css b/toolkit/themes/shared/pictureinpicture/player.css +index a3ffe31d47cc81a0cb578acc9177aaa6f41668eb..cf69507804b7c50f9afcfabb744098cfbe409396 100644 +--- a/toolkit/themes/shared/pictureinpicture/player.css ++++ b/toolkit/themes/shared/pictureinpicture/player.css +@@ -724,3 +724,17 @@ input:checked + .slider::before { + justify-self: center; + } + } ++ ++#minimize { ++ background-image: url("chrome://browser/skin/zen-icons/unpin.svg"); ++ background-color: rgba(255, 255, 255, .8); ++ position: absolute; ++ fill: var(--close-btn-fill-color); ++ right: 50px; ++ top: 10px; ++} ++ ++#minimize[mac="true"] { ++ right: auto; ++ left: 50px; ++} From 38770d9393b9c4c80e508c2f3dc8e99988990076 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Thu, 20 Mar 2025 13:34:10 +0100 Subject: [PATCH 48/62] refactor(styles): update CSS variables and layout for improved theming and spacing --- .../base/content/zen-styles/zen-browser-ui.css | 2 +- .../content/zen-styles/zen-tabs/vertical-tabs.css | 4 ++-- src/browser/base/content/zen-styles/zen-theme.css | 2 +- .../base/content/zen-styles/zen-workspaces.css | 11 +++++------ .../base/zen-components/ZenGradientGenerator.mjs | 7 +++++-- src/browser/base/zen-components/ZenTabUnloader.mjs | 13 ++++++++----- src/browser/base/zen-components/ZenViewSplitter.mjs | 2 +- 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-browser-ui.css b/src/browser/base/content/zen-styles/zen-browser-ui.css index 2235c3881..ada3d5667 100644 --- a/src/browser/base/content/zen-styles/zen-browser-ui.css +++ b/src/browser/base/content/zen-styles/zen-browser-ui.css @@ -109,7 +109,7 @@ } #zen-main-app-wrapper { - background: transparent; + background: var(--zen-themed-toolbar-bg-transparent); overflow: hidden; & > * { diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index 5b0110255..a5fcf745e 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -1050,14 +1050,14 @@ #zen-essentials-container { padding-bottom: var(--zen-toolbox-padding); overflow: hidden; - gap: 3px; + gap: calc(var(--zen-toolbox-padding) - 2px); } #zen-essentials-container { overflow: hidden; transition: max-height 0.3s ease-out; opacity: 1; - grid-template-columns: repeat(auto-fit, minmax(48px, auto)); + grid-template-columns: repeat(auto-fit, minmax(49px, auto)); overflow: hidden; scrollbar-width: thin; display: grid; diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index 3ec3f6061..ac751160f 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -158,7 +158,7 @@ --zen-themed-toolbar-bg: light-dark(rgb(240, 240, 244), #171717); --zen-themed-toolbar-bg-transparent: light-dark(var(--zen-branding-bg), #171717); - --zen-workspace-indicator-height: 45px; + --zen-workspace-indicator-height: 48px; @media (-moz-windows-mica) or (-moz-platform: macos) { background: transparent; diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index daf77b3c2..dc3ff6c85 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -425,7 +425,7 @@ } .zen-current-workspace-indicator { - padding: 15px calc(4px + var(--tab-inline-padding)); + padding: calc(15px + var(--zen-toolbox-padding)) calc(4px + var(--tab-inline-padding)); font-weight: 600; position: absolute; max-height: var(--zen-workspace-indicator-height); @@ -443,11 +443,10 @@ pointer-events: none; content: ''; position: absolute; - top: 4px; - left: 2px; - z-index: -1; - width: calc(100% - 4px); - height: calc(100% - 10px); + top: var(--zen-toolbox-padding); + left: calc(var(--zen-toolbox-padding) / 2); + width: calc(100% - var(--zen-toolbox-padding)); + height: calc(100% - var(--zen-toolbox-padding) * 2); } &:hover, diff --git a/src/browser/base/zen-components/ZenGradientGenerator.mjs b/src/browser/base/zen-components/ZenGradientGenerator.mjs index fc18114e5..1dd3a8e7e 100644 --- a/src/browser/base/zen-components/ZenGradientGenerator.mjs +++ b/src/browser/base/zen-components/ZenGradientGenerator.mjs @@ -870,8 +870,11 @@ if (color.isCustom) { return color.c; } - const toolbarBg = forToolbar ? this.getToolbarModifiedBase() : 'var(--zen-themed-toolbar-bg-transparent)'; - return `color-mix(in srgb, rgb(${color.c[0]}, ${color.c[1]}, ${color.c[2]}) ${this.currentOpacity * 100}%, ${toolbarBg} ${(1 - this.currentOpacity) * 100}%)`; + if (forToolbar) { + const toolbarBg = this.getToolbarModifiedBase(); + return `color-mix(in srgb, rgb(${color.c[0]}, ${color.c[1]}, ${color.c[2]}) ${this.currentOpacity * 100}%, ${toolbarBg} ${(1 - this.currentOpacity) * 100}%)`; + } + return `rgba(${color.c[0]}, ${color.c[1]}, ${color.c[2]}, ${this.currentOpacity})`; } getGradient(colors, forToolbar = false) { diff --git a/src/browser/base/zen-components/ZenTabUnloader.mjs b/src/browser/base/zen-components/ZenTabUnloader.mjs index 5ea8f46fe..a3479e412 100644 --- a/src/browser/base/zen-components/ZenTabUnloader.mjs +++ b/src/browser/base/zen-components/ZenTabUnloader.mjs @@ -271,9 +271,6 @@ tab.attention || tab.hasAttribute('glance-id') || tab.linkedBrowser?.zenModeActive || - (typeof extraArgs.permitUnload === 'undefined' - ? !tab.linkedBrowser?.permitUnload()?.permitUnload - : !extraArgs.permitUnload) || (tab.pictureinpicture && !ignoreTimestamp) || (tab.soundPlaying && !ignoreTimestamp) || (tab.zenIgnoreUnload && !ignoreTimestamp) || @@ -283,7 +280,7 @@ return false; } if (ignoreTimestamp) { - return true; + return this._tabPermitsUnload(tab, extraArgs); } const lastActivity = tab.lastActivity; if (!lastActivity) { @@ -291,7 +288,13 @@ } const diff = currentTimestamp - lastActivity; // Check if the tab has been inactive for more than the timeout - return diff > lazy.zenTabUnloaderTimeout * 60 * 1000; + return diff > lazy.zenTabUnloaderTimeout * 60 * 1000 && this._tabPermitsUnload(tab, extraArgs); + } + + _tabPermitsUnload(tab, extraArgs) { + return typeof extraArgs.permitUnload === 'undefined' + ? !tab.linkedBrowser?.permitUnload()?.permitUnload + : !extraArgs.permitUnload; } } diff --git a/src/browser/base/zen-components/ZenViewSplitter.mjs b/src/browser/base/zen-components/ZenViewSplitter.mjs index f9a0734fd..b50a6f4f0 100644 --- a/src/browser/base/zen-components/ZenViewSplitter.mjs +++ b/src/browser/base/zen-components/ZenViewSplitter.mjs @@ -230,7 +230,6 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { const halfWidth = panelsWidth / 2; const side = event.clientX > halfWidth ? 'right' : 'left'; this.fakeBrowser = document.createXULElement('vbox'); - this.fakeBrowser.addEventListener('dragleave', this.onBrowserDragEndToSplit); window.addEventListener('dragend', this.onBrowserDragEndToSplit, { once: true }); const padding = Services.prefs.getIntPref('zen.theme.content-element-separation', 0); this.fakeBrowser.setAttribute('flex', '1'); @@ -277,6 +276,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature { ]); if (this._finishAllAnimatingPromise) { this._finishAllAnimatingPromise.then(() => { + this.fakeBrowser.addEventListener('dragleave', this.onBrowserDragEndToSplit); this._canDrop = true; draggedTab._visuallySelected = true; }); From 34c78dff5209bda6d9e8baae188aa88e5703cdec Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Thu, 20 Mar 2025 22:09:43 +0700 Subject: [PATCH 49/62] add config to disable media controls --- src/browser/app/profile/zen-browser.js | 2 ++ src/browser/base/zen-components/ZenMediaController.mjs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 84fe71202..2e2cb0f4d 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -90,6 +90,8 @@ pref('zen.tabs.show-newtab-vertical', true); pref('zen.view.show-newtab-button-border-top', false); pref('zen.view.show-newtab-button-top', true); +perf('zen.mediacontrols.enabled', true); + #ifdef MOZILLA_OFFICIAL pref('zen.rice.api.url', 'https://share.zen-browser.app', locked); pref('zen.injections.match-urls', 'https://zen-browser.app/*,https://share.zen-browser.app/*', locked); diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index e6c7e9542..a07530a53 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -21,6 +21,8 @@ class ZenMediaController { _controllerSwitchTimeout = null; init() { + if (!Services.prefs.getBoolPref('zen.mediacontrols.enabled', true)) return; + this.mediaTitle = document.querySelector('#zen-media-title'); this.mediaArtist = document.querySelector('#zen-media-artist'); this.mediaControlBar = document.querySelector('#zen-media-controls-toolbar'); From 5d0807de4c903d366aa5f3c3c4efb443a883eb92 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Thu, 20 Mar 2025 19:22:55 +0100 Subject: [PATCH 50/62] refactor: update workspace settings and improve CSS styles for better layout and responsiveness --- l10n | 2 +- src/browser/app/profile/zen-browser.js | 1 - .../zen-styles/zen-gradient-generator.css | 2 +- .../zen-styles/zen-tabs/vertical-tabs.css | 3 - .../content/zen-styles/zen-workspaces.css | 73 +++++++++++-------- .../zen-components/ZenGradientGenerator.mjs | 7 +- .../zen-components/ZenMediaController.mjs | 23 +++--- .../base/zen-components/ZenTabUnloader.mjs | 10 +-- .../base/zen-components/ZenWorkspaces.mjs | 20 +++++ .../components/preferences/zen-settings.js | 5 -- .../preferences/zenTabsManagement.inc.xhtml | 3 - 11 files changed, 82 insertions(+), 67 deletions(-) diff --git a/l10n b/l10n index 7c14b58a2..778cb128c 160000 --- a/l10n +++ b/l10n @@ -1 +1 @@ -Subproject commit 7c14b58a28845a131a00153eb11c8ca5395bf26b +Subproject commit 778cb128c659c7b8f57080e99fbc04f8d93c30a2 diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 84fe71202..e6408b985 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -199,7 +199,6 @@ pref('zen.startup.smooth-scroll-in-tabs', true); // Zen Workspaces pref('zen.workspaces.disabled_for_testing', false); -pref('zen.workspaces.hide-deactivated-workspaces', false); pref('zen.workspaces.hide-default-container-indicator', true); pref('zen.workspaces.force-container-workspace', false); pref('zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', false); diff --git a/src/browser/base/content/zen-styles/zen-gradient-generator.css b/src/browser/base/content/zen-styles/zen-gradient-generator.css index 09971dd3d..998fa95b8 100644 --- a/src/browser/base/content/zen-styles/zen-gradient-generator.css +++ b/src/browser/base/content/zen-styles/zen-gradient-generator.css @@ -5,7 +5,7 @@ */ #PanelUI-zen-gradient-generator { - --panel-width: 300px; + --panel-width: 320px; --panel-padding: 10px; min-width: var(--panel-width); } diff --git a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css index a5fcf745e..65473b89e 100644 --- a/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css +++ b/src/browser/base/content/zen-styles/zen-tabs/vertical-tabs.css @@ -474,9 +474,6 @@ } & #zen-workspaces-button { - margin-left: 2px; - margin-right: 2px; - & .zen-workspace-sidebar-icon[no-icon='true'] { display: none; } diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index dc3ff6c85..d69e930d3 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -20,11 +20,13 @@ --toolbarbutton-hover-background: transparent !important; border-radius: var(--zen-button-border-radius) !important; background: transparent; - padding: 2px; appearance: unset !important; height: fit-content; gap: 3px; + container-type: inline-size; + width: 100%; + & toolbarbutton { margin: auto; width: 25px; @@ -34,8 +36,44 @@ align-items: center; position: relative; - @media (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') { - &:not([active='true']):not(:hover) { + & .zen-workspace-icon[no-icon='true'] { + width: 6px; + height: 6px; + background: light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)); + border-radius: 50%; + } + + filter: grayscale(1); + opacity: 0.5; + transition: + filter 0.2s, + opacity 0.2s, + width 0.1s; + + &[active='true'], + &:hover { + filter: grayscale(0); + opacity: 1; + } + + &:hover { + background-color: var(--zen-toolbar-element-bg); + } + } + + &[overflow] { + gap: 0 !important; + + & toolbarbutton { + margin: 0; + } + + & toolbarbutton:not([active='true']), + &:has(toolbarbutton:hover) toolbarbutton[active='true'] { + &:not(:hover) { + width: min(var(--zen-overflowed-workspace-button-width), 25px); + min-width: 10px; + &::after { content: ''; position: absolute; @@ -58,33 +96,6 @@ } } } - - & .zen-workspace-icon[no-icon='true'] { - width: 6px; - height: 6px; - background: light-dark(rgba(0, 0, 0, 0.4), rgba(255, 255, 255, 0.4)); - border-radius: 50%; - } - - @media not (-moz-bool-pref: 'zen.workspaces.hide-deactivated-workspaces') { - & { - filter: grayscale(1); - opacity: 0.5; - transition: - filter 0.2s, - opacity 0.2s; - } - - &[active='true'], - &:hover { - filter: grayscale(0); - opacity: 1; - } - - &:hover { - background-color: var(--zen-toolbar-element-bg); - } - } } } @@ -118,8 +129,6 @@ & #zen-workspaces-button { overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; display: flex; gap: 0.5ch; } diff --git a/src/browser/base/zen-components/ZenGradientGenerator.mjs b/src/browser/base/zen-components/ZenGradientGenerator.mjs index 1dd3a8e7e..97dce58c9 100644 --- a/src/browser/base/zen-components/ZenGradientGenerator.mjs +++ b/src/browser/base/zen-components/ZenGradientGenerator.mjs @@ -500,9 +500,8 @@ const centerPosition = { x: rect.width / 2, y: rect.height / 2 }; const harmonyAngles = getColorHarmonyType(dots.length + (action === 'add' ? 1 : action === 'remove' ? -1 : 0), this.dots); - if (!harmonyAngles || harmonyAngles.angles.length === 0) return dots; - this.useAlgo = harmonyAngles.type; + if (!harmonyAngles || harmonyAngles.angles.length === 0) return dots; let primaryDot = dots.find((dot) => dot.ID === 0); if (!primaryDot) return []; @@ -638,7 +637,7 @@ } }); - let colorPositions = this.calculateCompliments(this.dots, 'remove', this.useAlgo); + let colorPositions = this.calculateCompliments(this.dots, 'remove'); this.handleColorPositions(colorPositions); this.updateCurrentWorkspace(); return; @@ -780,7 +779,7 @@ } }); - let colorPositions = this.calculateCompliments(this.dots, 'remove', this.useAlgo); + let colorPositions = this.calculateCompliments(this.dots, 'remove'); this.handleColorPositions(colorPositions); this.updateCurrentWorkspace(); diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index e6c7e9542..e21c99882 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -58,16 +58,8 @@ class ZenMediaController { } }); - window.addEventListener('TabClose', (event) => { - const linkedBrowser = event.target.linkedBrowser; - if (!linkedBrowser?.browsingContext?.mediaController) return; - this.deinitMediaController( - linkedBrowser.browsingContext.mediaController, - true, - linkedBrowser.browserId === this._currentBrowser?.browserId, - true - ); - }); + const onTabDiscardedOrClosed = this.onTabDiscardedOrClosed.bind(this); + window.addEventListener('TabClose', onTabDiscardedOrClosed); window.addEventListener('DOMAudioPlaybackStarted', (event) => { setTimeout(() => { @@ -89,6 +81,17 @@ class ZenMediaController { window.addEventListener('DOMAudioPlaybackStopped', () => this.updateMuteState()); } + onTabDiscardedOrClosed(event) { + const linkedBrowser = event.target.linkedBrowser; + if (!linkedBrowser?.browsingContext?.mediaController) return; + this.deinitMediaController( + linkedBrowser.browsingContext.mediaController, + true, + linkedBrowser.browserId === this._currentBrowser?.browserId, + true + ); + } + async deinitMediaController(mediaController, shouldForget = true, shouldOverride = true, shouldHide = true) { if (!mediaController) return; diff --git a/src/browser/base/zen-components/ZenTabUnloader.mjs b/src/browser/base/zen-components/ZenTabUnloader.mjs index a3479e412..07ea6a373 100644 --- a/src/browser/base/zen-components/ZenTabUnloader.mjs +++ b/src/browser/base/zen-components/ZenTabUnloader.mjs @@ -22,8 +22,6 @@ 'TabAttrModified', 'TabPinned', 'TabUnpinned', - 'TabBrowserInserted', - 'TabBrowserDiscarded', 'TabShow', 'TabHide', 'TabOpen', @@ -150,8 +148,6 @@ switch (action) { case 'TabPinned': case 'TabUnpinned': - case 'TabBrowserInserted': - case 'TabBrowserDiscarded': case 'TabShow': case 'TabHide': break; @@ -265,9 +261,9 @@ tab.selected || (tab.multiselected && !ignoreTimestamp) || (tab.hasAttribute('busy') && !ignoreTimestamp) || - tab.hasAttribute('pending') || !tab.linkedPanel || tab.splitView || + tab.group?.hasAttribute('split-view-group') || tab.attention || tab.hasAttribute('glance-id') || tab.linkedBrowser?.zenModeActive || @@ -293,8 +289,8 @@ _tabPermitsUnload(tab, extraArgs) { return typeof extraArgs.permitUnload === 'undefined' - ? !tab.linkedBrowser?.permitUnload()?.permitUnload - : !extraArgs.permitUnload; + ? tab.linkedBrowser?.permitUnload()?.permitUnload + : extraArgs.permitUnload; } } diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 01c436c58..f1c37c2be 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -77,6 +77,8 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { ); ChromeUtils.defineLazyGetter(this, 'tabContainer', () => document.getElementById('tabbrowser-tabs')); this._activeWorkspace = Services.prefs.getStringPref('zen.workspaces.active', ''); + + window.addEventListener('resize', this.onWindowResize.bind(this)); } async afterLoadInit() { @@ -599,6 +601,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { } catch (e) { console.error('ZenWorkspaces: Error initializing theme picker', e); } + this.onWindowResize(); await this._selectStartPage(); this._fixTabPositions(); this._resolveInitialized(); @@ -2368,4 +2371,21 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { const workspace = workspaces.workspaces.find((workspace) => workspace.uuid === activeWorkspace); return workspace.containerTabId; } + + onWindowResize() { + // Check if workspace icons overflow the parent container + const parent = document.getElementById('zen-workspaces-button'); + if (!parent) { + return; + } + // Once we are overflowing, we align the buttons to always stay inside the container, + // meaning we need to remove the overflow attribute to reset the width + parent.removeAttribute('overflow'); + const overflow = parent.scrollWidth > parent.clientWidth; + parent.toggleAttribute('overflow', overflow); + // The maximum width a button has when it overflows based on the number of buttons + const numButtons = parent.children.length + 1; // +1 to exclude the active button + const maxWidth = 100 / numButtons; + parent.style.setProperty('--zen-overflowed-workspace-button-width', `${maxWidth}%`); + } })(); diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index 6383e9b3f..1c9f283ec 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -959,11 +959,6 @@ Preferences.addAll([ type: 'int', default: 10, }, - { - id: 'zen.workspaces.hide-deactivated-workspaces', - type: 'bool', - default: true, - }, { id: 'zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', type: 'bool', diff --git a/src/browser/components/preferences/zenTabsManagement.inc.xhtml b/src/browser/components/preferences/zenTabsManagement.inc.xhtml index 7e148a9b6..47236d364 100644 --- a/src/browser/components/preferences/zenTabsManagement.inc.xhtml +++ b/src/browser/components/preferences/zenTabsManagement.inc.xhtml @@ -23,9 +23,6 @@ - Date: Thu, 20 Mar 2025 19:42:42 +0100 Subject: [PATCH 51/62] style: update CSS variables for improved toolbar button contrast --- src/browser/themes/windows/browser-css.patch | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/browser/themes/windows/browser-css.patch b/src/browser/themes/windows/browser-css.patch index 9c49c2201..146262177 100644 --- a/src/browser/themes/windows/browser-css.patch +++ b/src/browser/themes/windows/browser-css.patch @@ -1,8 +1,15 @@ diff --git a/browser/themes/windows/browser.css b/browser/themes/windows/browser.css -index f49604e53780763b9aa19897458c45f0be6cbc9b..aa9da99641ba4a3b7f67a27acbbf6c75c1346ced 100644 +index f49604e53780763b9aa19897458c45f0be6cbc9b..5ea9098a9b689470ef4ddfea91069cd23391d020 100644 --- a/browser/themes/windows/browser.css +++ b/browser/themes/windows/browser.css -@@ -47,7 +47,7 @@ +@@ -40,14 +40,13 @@ + * override these on the tabs toolbar because the accent color is + * arbitrary, so the hardcoded colors from browser-custom-colors might + * not provide sufficient contrast. */ +- --toolbarbutton-icon-fill: currentColor; + --toolbarbutton-hover-background: color-mix(in srgb, currentColor 17%, transparent); + --toolbarbutton-active-background: color-mix(in srgb, currentColor 30%, transparent); + } } &[sizemode="normal"] #navigator-toolbox { From 1651956cbdf9dd60c25105f26adec3d2aef03378 Mon Sep 17 00:00:00 2001 From: "mr. m" <91018726+mauro-balades@users.noreply.github.com> Date: Thu, 20 Mar 2025 20:04:56 +0100 Subject: [PATCH 52/62] Bumped version to `1.10.1b` Signed-off-by: mr. m <91018726+mauro-balades@users.noreply.github.com> --- surfer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/surfer.json b/surfer.json index 4c8a87cce..c821cdef9 100644 --- a/surfer.json +++ b/surfer.json @@ -19,7 +19,7 @@ "brandShortName": "Zen", "brandFullName": "Zen Browser", "release": { - "displayVersion": "1.10b", + "displayVersion": "1.10.1b", "github": { "repo": "zen-browser/desktop" }, @@ -39,7 +39,7 @@ "brandShortName": "Twilight", "brandFullName": "Zen Twilight", "release": { - "displayVersion": "1.10t", + "displayVersion": "1.10.1t", "github": { "repo": "zen-browser/desktop" } @@ -53,4 +53,4 @@ "licenseType": "MPL-2.0" }, "updateHostname": "updates.zen-browser.app" -} \ No newline at end of file +} From ba5f816772dca2f6a2dcbd85c8b3dc5c175bf279 Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 21 Mar 2025 00:37:15 +0100 Subject: [PATCH 53/62] fix(styles): adjust toolbarbutton margin for consistent alignment --- src/browser/base/content/zen-styles/zen-workspaces.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index dc3ff6c85..d20d11b95 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -26,7 +26,7 @@ gap: 3px; & toolbarbutton { - margin: auto; + margin: 0; width: 25px; display: flex; justify-content: center; From 5d1021350d1271bbc8f6712e485144e3104cc2fa Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 21 Mar 2025 00:43:26 +0100 Subject: [PATCH 54/62] fix(workspaces): trigger onWindowResize after changing workspace --- src/browser/base/zen-components/ZenWorkspaces.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index f1c37c2be..866831a00 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -1931,6 +1931,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { } await this.changeWorkspace(workspaceData); } + this.onWindowResize(); return workspaceData; } From 04308fbaea36a36e6e88e34ac9d76acf3c7f78ab Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 21 Mar 2025 00:48:43 +0100 Subject: [PATCH 55/62] fix(workspaces): ensure onWindowResize is triggered after workspace removal and optimize button alignment logic --- .../base/zen-components/ZenWorkspaces.mjs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 866831a00..2ca0adb55 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -873,6 +873,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { await ZenWorkspacesStorage.removeWorkspace(windowID); await this._propagateWorkspaceData(); await this._updateWorkspacesChangeContextMenu(); + this.onWindowResize(); } isWorkspaceActive(workspace) { @@ -2379,14 +2380,16 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if (!parent) { return; } - // Once we are overflowing, we align the buttons to always stay inside the container, - // meaning we need to remove the overflow attribute to reset the width - parent.removeAttribute('overflow'); - const overflow = parent.scrollWidth > parent.clientWidth; - parent.toggleAttribute('overflow', overflow); - // The maximum width a button has when it overflows based on the number of buttons - const numButtons = parent.children.length + 1; // +1 to exclude the active button - const maxWidth = 100 / numButtons; - parent.style.setProperty('--zen-overflowed-workspace-button-width', `${maxWidth}%`); + window.requestAnimationFrame(() => { + // Once we are overflowing, we align the buttons to always stay inside the container, + // meaning we need to remove the overflow attribute to reset the width + parent.removeAttribute('overflow'); + const overflow = parent.scrollWidth > parent.clientWidth; + parent.toggleAttribute('overflow', overflow); + // The maximum width a button has when it overflows based on the number of buttons + const numButtons = parent.children.length + 1; // +1 to exclude the active button + const maxWidth = 100 / numButtons; + parent.style.setProperty('--zen-overflowed-workspace-button-width', `${maxWidth}%`); + }); } })(); From ba89f392d6f97f2c4588b7e35735d012c1007bdf Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 21 Mar 2025 07:51:24 +0100 Subject: [PATCH 56/62] fix: prevent unnecessary window resize handling when event is not from the window --- src/browser/base/zen-components/ZenWorkspaces.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index f1c37c2be..757353a33 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -2372,7 +2372,8 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { return workspace.containerTabId; } - onWindowResize() { + onWindowResize(event = undefined) { + if (!(!event || event.target === window)) return; // Check if workspace icons overflow the parent container const parent = document.getElementById('zen-workspaces-button'); if (!parent) { From 4f140893c9dcf46b50df5265fe34c6a013d22093 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Fri, 21 Mar 2025 07:59:30 +0100 Subject: [PATCH 57/62] fix(workspaces): adjust toolbar background transparency and optimize button alignment during resize --- src/browser/base/content/zen-styles/zen-theme.css | 2 +- src/browser/base/zen-components/ZenWorkspaces.mjs | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-theme.css b/src/browser/base/content/zen-styles/zen-theme.css index ac751160f..f47f42089 100644 --- a/src/browser/base/content/zen-styles/zen-theme.css +++ b/src/browser/base/content/zen-styles/zen-theme.css @@ -164,7 +164,7 @@ background: transparent; --zen-themed-toolbar-bg-transparent: transparent; @media (-moz-bool-pref: 'zen.widget.windows.acrylic') { - --zen-themed-toolbar-bg-transparent: color-mix(in srgb, var(--zen-themed-toolbar-bg) 75%, transparent 25%); + --zen-themed-toolbar-bg-transparent: color-mix(in srgb, var(--zen-themed-toolbar-bg) 35%, transparent 65%); } } diff --git a/src/browser/base/zen-components/ZenWorkspaces.mjs b/src/browser/base/zen-components/ZenWorkspaces.mjs index 6b4774e52..cc2d497aa 100644 --- a/src/browser/base/zen-components/ZenWorkspaces.mjs +++ b/src/browser/base/zen-components/ZenWorkspaces.mjs @@ -2378,19 +2378,21 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature { if (!(!event || event.target === window)) return; // Check if workspace icons overflow the parent container const parent = document.getElementById('zen-workspaces-button'); - if (!parent) { + if (!parent || this._processingResize) { return; } - window.requestAnimationFrame(() => { - // Once we are overflowing, we align the buttons to always stay inside the container, - // meaning we need to remove the overflow attribute to reset the width - parent.removeAttribute('overflow'); + this._processingResize = true; + // Once we are overflowing, we align the buttons to always stay inside the container, + // meaning we need to remove the overflow attribute to reset the width + parent.removeAttribute('overflow'); + requestAnimationFrame(() => { const overflow = parent.scrollWidth > parent.clientWidth; parent.toggleAttribute('overflow', overflow); // The maximum width a button has when it overflows based on the number of buttons const numButtons = parent.children.length + 1; // +1 to exclude the active button const maxWidth = 100 / numButtons; parent.style.setProperty('--zen-overflowed-workspace-button-width', `${maxWidth}%`); + this._processingResize = false; }); } })(); From 4ec493950c614dd9bc938c8ff4722b6dbe978767 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Fri, 21 Mar 2025 18:03:39 +0700 Subject: [PATCH 58/62] MediaController: account for playbackRate --- src/browser/base/zen-components/ZenMediaController.mjs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index cc10e5707..067451a36 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -221,6 +221,8 @@ class ZenMediaController { this._currentPosition = positionState.position; this._currentDuration = positionState.duration; + this._currentPlaybackRate = positionState.playbackRate; + this.updateMediaPosition(); for (const key of this.supportedKeys) { @@ -297,6 +299,8 @@ class ZenMediaController { this._currentPosition = event.position; this._currentDuration = event.duration; + this._currentPlaybackRate = event.playbackRate; + this.updateMediaPosition(); } @@ -357,7 +361,7 @@ class ZenMediaController { this._mediaUpdateInterval = setInterval(() => { if (this._currentMediaController?.isPlaying) { - this._currentPosition += 1; + this._currentPosition += 1 * this._currentPlaybackRate; if (this._currentPosition > this._currentDuration) { this._currentPosition = this._currentDuration; } From 491234b310e12dba9e6b3a98ec639777c425565f Mon Sep 17 00:00:00 2001 From: "mr. m" Date: Fri, 21 Mar 2025 12:50:43 +0100 Subject: [PATCH 59/62] fix(styles): update z-index for sidebar splitter and remove min-width from workspace button --- src/browser/base/content/zen-styles/zen-sidebar-panels.css | 2 +- src/browser/base/content/zen-styles/zen-workspaces.css | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/browser/base/content/zen-styles/zen-sidebar-panels.css b/src/browser/base/content/zen-styles/zen-sidebar-panels.css index da116f8df..3bdb4ebdf 100644 --- a/src/browser/base/content/zen-styles/zen-sidebar-panels.css +++ b/src/browser/base/content/zen-styles/zen-sidebar-panels.css @@ -111,7 +111,7 @@ background: transparent; border: none; cursor: ew-resize; - z-index: 2; + z-index: 3; &:is(.zen-split-view-splitter[orient='vertical']) { /* Bit of a hacky solution, but it works */ diff --git a/src/browser/base/content/zen-styles/zen-workspaces.css b/src/browser/base/content/zen-styles/zen-workspaces.css index 497f52cdf..ab55b1a59 100644 --- a/src/browser/base/content/zen-styles/zen-workspaces.css +++ b/src/browser/base/content/zen-styles/zen-workspaces.css @@ -72,7 +72,6 @@ &:has(toolbarbutton:hover) toolbarbutton[active='true'] { &:not(:hover) { width: min(var(--zen-overflowed-workspace-button-width), 25px); - min-width: 10px; &::after { content: ''; From c3d09c486c6ae1f2c1d20dce1f611b13066ed01a Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sat, 22 Mar 2025 08:46:40 +0700 Subject: [PATCH 60/62] fix: import string to pip window --- .../pictureinpicture/content/player-xhtml.patch | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/toolkit/components/pictureinpicture/content/player-xhtml.patch b/src/toolkit/components/pictureinpicture/content/player-xhtml.patch index 92d9b9543..6c0086210 100644 --- a/src/toolkit/components/pictureinpicture/content/player-xhtml.patch +++ b/src/toolkit/components/pictureinpicture/content/player-xhtml.patch @@ -1,8 +1,16 @@ diff --git a/toolkit/components/pictureinpicture/content/player.xhtml b/toolkit/components/pictureinpicture/content/player.xhtml -index 440ce51e8e67e4d3a7bdcb78f38f2fb6684c9848..6b48a3178f9de460dd3b08728f5638ef2751de21 100644 +index 440ce51e8e67e4d3a7bdcb78f38f2fb6684c9848..3db687ff753c47faf2dac63183f025c5ff456250 100644 --- a/toolkit/components/pictureinpicture/content/player.xhtml +++ b/toolkit/components/pictureinpicture/content/player.xhtml -@@ -52,13 +52,22 @@ +@@ -14,6 +14,7 @@ + + + ++ + + + +@@ -52,13 +53,22 @@ tabindex="10" #endif /> From c2f2a589ed1591009f7e8b30352f2de11d23d5a3 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sat, 22 Mar 2025 08:52:39 +0700 Subject: [PATCH 61/62] shorter export --- .../pictureinpicture/content/player-xhtml.patch | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/toolkit/components/pictureinpicture/content/player-xhtml.patch b/src/toolkit/components/pictureinpicture/content/player-xhtml.patch index 6c0086210..ff25ccce3 100644 --- a/src/toolkit/components/pictureinpicture/content/player-xhtml.patch +++ b/src/toolkit/components/pictureinpicture/content/player-xhtml.patch @@ -1,15 +1,15 @@ diff --git a/toolkit/components/pictureinpicture/content/player.xhtml b/toolkit/components/pictureinpicture/content/player.xhtml -index 440ce51e8e67e4d3a7bdcb78f38f2fb6684c9848..3db687ff753c47faf2dac63183f025c5ff456250 100644 +index 440ce51e8e67e4d3a7bdcb78f38f2fb6684c9848..38912579310314a13d516328ec770db6b589d243 100644 --- a/toolkit/components/pictureinpicture/content/player.xhtml +++ b/toolkit/components/pictureinpicture/content/player.xhtml -@@ -14,6 +14,7 @@ - - - -+ +@@ -17,6 +17,7 @@ ++ + + + @@ -52,13 +53,22 @@ tabindex="10" #endif From d9d8437b6dd9aa581e3b101ed54a5b1b8e880be1 Mon Sep 17 00:00:00 2001 From: Slowlife01 Date: Sat, 22 Mar 2025 09:46:20 +0700 Subject: [PATCH 62/62] fix(MediaController): recheck overflow on metadata change --- src/browser/base/zen-components/ZenMediaController.mjs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/browser/base/zen-components/ZenMediaController.mjs b/src/browser/base/zen-components/ZenMediaController.mjs index 067451a36..19c28220a 100644 --- a/src/browser/base/zen-components/ZenMediaController.mjs +++ b/src/browser/base/zen-components/ZenMediaController.mjs @@ -396,6 +396,13 @@ class ZenMediaController { const metadata = event.target.getMetadata(); this.mediaTitle.textContent = metadata.title || ''; this.mediaArtist.textContent = metadata.artist || ''; + + const mediaInfoElements = [this.mediaTitle, this.mediaArtist]; + for (const element of mediaInfoElements) { + element.removeAttribute('overflow'); + } + + this.addLabelOverflows(mediaInfoElements); } _onPictureInPictureModeChange(event) {