mirror of
https://github.com/zen-browser/desktop.git
synced 2026-01-11 23:55:32 +00:00
Compare commits
24 Commits
chore/6198
...
feat/164
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f67fa2339b | ||
|
|
7f29800982 | ||
|
|
3c7fb093db | ||
|
|
ec4a55e1f8 | ||
|
|
b0f3839426 | ||
|
|
a537f0f91d | ||
|
|
11f29c12c5 | ||
|
|
e7631ce9cc | ||
|
|
481163a756 | ||
|
|
281ec6693d | ||
|
|
9820bd5772 | ||
|
|
75f4f0c3e6 | ||
|
|
591193b748 | ||
|
|
2628ba7dd8 | ||
|
|
2fd0935bf5 | ||
|
|
7683b2675a | ||
|
|
ea7024aae4 | ||
|
|
be8cbce23e | ||
|
|
9c2b8426a9 | ||
|
|
beb4f94fd2 | ||
|
|
f39ca33aa5 | ||
|
|
7743ad968c | ||
|
|
7470df4cf6 | ||
|
|
aef8400841 |
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
@@ -336,7 +336,7 @@ jobs:
|
||||
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
|
||||
use-sccache: ${{ inputs.use-sccache }}
|
||||
|
||||
mac:
|
||||
mac-pgo-generate:
|
||||
name: macOS build
|
||||
uses: ./.github/workflows/macos-release-build.yml
|
||||
permissions:
|
||||
@@ -348,6 +348,21 @@ jobs:
|
||||
release-branch: ${{ inputs.update_branch }}
|
||||
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
|
||||
use-sccache: ${{ inputs.use-sccache }}
|
||||
generate-pgo-data: true
|
||||
|
||||
mac:
|
||||
name: macOS build
|
||||
uses: ./.github/workflows/macos-release-build.yml
|
||||
permissions:
|
||||
contents: write
|
||||
secrets: inherit
|
||||
needs: [build-data, buildid, mac-pgo-generate]
|
||||
with:
|
||||
build-version: ${{ needs.build-data.outputs.version }}
|
||||
release-branch: ${{ inputs.update_branch }}
|
||||
MOZ_BUILD_DATE: ${{needs.buildid.outputs.buildids}}
|
||||
use-sccache: ${{ inputs.use-sccache }}
|
||||
generate-pgo-data: false
|
||||
|
||||
mac-uni:
|
||||
name: macOS build (Universal)
|
||||
|
||||
39
.github/workflows/macos-release-build.yml
vendored
39
.github/workflows/macos-release-build.yml
vendored
@@ -22,6 +22,11 @@ on:
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
generate-pgo-data:
|
||||
description: 'Generate PGO data'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
mac-build:
|
||||
@@ -68,8 +73,8 @@ jobs:
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.email "mauro-balades@users.noreply.github.com"
|
||||
git config --global user.name "mauro-balades"
|
||||
git config --global user.email "mr-cheffy@users.noreply.github.com"
|
||||
git config --global user.name "mr-cheffy"
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
@@ -120,6 +125,20 @@ jobs:
|
||||
SURFER_COMPAT: ${{ matrix.arch }}
|
||||
run: npm run import -- --verbose
|
||||
|
||||
- name: Download PGO data
|
||||
if: ${{ inputs.generate-pgo-data == false }}
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: zen-macos-pgo-data-${{ matrix.arch }}
|
||||
|
||||
- name: Move PGO data
|
||||
if: ${{ inputs.generate-pgo-data == false }}
|
||||
run: |
|
||||
mkdir -p $(echo ~)/artifact
|
||||
mv $GITHUB_WORKSPACE/zen-macos-pgo-data-${{ matrix.arch }}/* $(echo ~)/artifact
|
||||
chmod +x ~/artifact/en-US.log
|
||||
chmod +x ~/artifact/merged.profdata
|
||||
|
||||
- name: Bootstrap
|
||||
run: |
|
||||
cd engine
|
||||
@@ -141,6 +160,7 @@ jobs:
|
||||
env:
|
||||
SURFER_COMPAT: ${{ matrix.arch }}
|
||||
ZEN_RELEASE_BRANCH: ${{ inputs.release-branch }}
|
||||
ZEN_GENERATE_PGO_DATA: ${{ inputs.generate-pgo-data && '1' || '0' }}
|
||||
run: |
|
||||
export SURFER_PLATFORM="darwin"
|
||||
if [[ -n ${{ inputs.MOZ_BUILD_DATE }} ]];then
|
||||
@@ -149,6 +169,7 @@ jobs:
|
||||
bash .github/workflows/src/release-build.sh
|
||||
|
||||
- name: Package
|
||||
if: ${{ !inputs.generate-pgo-data }}
|
||||
env:
|
||||
SURFER_COMPAT: ${{ matrix.arch }}
|
||||
ZEN_GA_DISABLE_PGO: true
|
||||
@@ -162,6 +183,7 @@ jobs:
|
||||
rm -rf ~/.zen-keys
|
||||
|
||||
- name: Rename artifacts
|
||||
if: ${{ !inputs.generate-pgo-data }}
|
||||
run: |
|
||||
echo "Tarballing DMG"
|
||||
set -ex
|
||||
@@ -171,6 +193,7 @@ jobs:
|
||||
|
||||
- name: Upload dist dmg
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ !inputs.generate-pgo-data }}
|
||||
with:
|
||||
retention-days: 1
|
||||
name: zen-${{ matrix.arch }}-apple-darwin-dist.dmg
|
||||
@@ -178,7 +201,7 @@ jobs:
|
||||
|
||||
- name: Upload host mar
|
||||
uses: actions/upload-artifact@v4
|
||||
if: matrix.arch == 'aarch64'
|
||||
if: matrix.arch == 'aarch64' && !inputs.generate-pgo-data
|
||||
with:
|
||||
retention-days: 1
|
||||
name: zen-macos-host-mar
|
||||
@@ -186,8 +209,16 @@ jobs:
|
||||
|
||||
- name: Upload platform.ini
|
||||
uses: actions/upload-artifact@v4
|
||||
if: matrix.arch == 'x86_64'
|
||||
if: matrix.arch == 'x86_64' && !inputs.generate-pgo-data
|
||||
with:
|
||||
retention-days: 1
|
||||
name: platform.ini
|
||||
path: ./platform.ini
|
||||
|
||||
- name: Upload PGO data
|
||||
uses: actions/upload-artifact@v4
|
||||
if: inputs.generate-pgo-data
|
||||
with:
|
||||
retention-days: 1
|
||||
name: zen-macos-pgo-data-${{ matrix.arch }}
|
||||
path: ./zen-macos-pgo-data
|
||||
|
||||
19
.github/workflows/src/release-build.sh
vendored
19
.github/workflows/src/release-build.sh
vendored
@@ -28,3 +28,22 @@ else
|
||||
export ZEN_RELEASE=1
|
||||
npm run build
|
||||
fi
|
||||
|
||||
if test "$ZEN_GENERATE_PGO_DATA" = "1"; then
|
||||
cd engine
|
||||
export UPLOAD_PATH=../zen-macos-pgo-data
|
||||
export MOZ_FETCHES_DIR=/Users/runner/.mozbuild
|
||||
mkdir -p $UPLOAD_PATH
|
||||
|
||||
export JARLOG_FILE="en-US.log"
|
||||
|
||||
export LLVM_PROFDATA=$MOZ_FETCHES_DIR/clang/bin/llvm-profdata
|
||||
|
||||
set -v
|
||||
|
||||
./mach python build/pgo/profileserver.py --binary obj-*-apple-darwin/dist/*.app/Contents/MacOS/zen
|
||||
|
||||
mv merged.profdata $UPLOAD_PATH/
|
||||
mv $JARLOG_FILE $UPLOAD_PATH/
|
||||
cd ..
|
||||
fi
|
||||
|
||||
14
.github/workflows/sync-upstream.yml
vendored
14
.github/workflows/sync-upstream.yml
vendored
@@ -47,6 +47,12 @@ jobs:
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: npm ci
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: |
|
||||
git config --global user.email "mr-cheffy@users.noreply.github.com"
|
||||
git config --global user.name "mr-cheffy"
|
||||
|
||||
- name: Setup surfer CI
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: |
|
||||
@@ -67,6 +73,12 @@ jobs:
|
||||
npm run sync
|
||||
fi
|
||||
|
||||
- name: Run formatter
|
||||
if: steps.check-upstream-branch.outputs.branch_exists == 'false'
|
||||
run: |
|
||||
sudo apt install python3-autopep8
|
||||
npm run pretty
|
||||
|
||||
- name: Check if any files changed
|
||||
id: git-check
|
||||
run: |
|
||||
@@ -97,7 +109,7 @@ jobs:
|
||||
|
||||
- name: Import external tests
|
||||
if: steps.git-check.outputs.files_changed == 'true'
|
||||
run: python3 scripts/import_external_tests.py
|
||||
run: python3 scripts/import_external_tests.py || true
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
|
||||
@@ -79,12 +79,6 @@ if test "$ZEN_RELEASE"; then
|
||||
MOZILLA_OFFICIAL=1
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export OPT_LEVEL="3"
|
||||
ac_add_options OPT_LEVEL="3"
|
||||
|
||||
export RUSTC_OPT_LEVEL="3"
|
||||
ac_add_options RUSTC_OPT_LEVEL="3"
|
||||
|
||||
mk_add_options AUTOCLOBBER=1
|
||||
export AUTOCLOBBER=1
|
||||
|
||||
|
||||
@@ -14,42 +14,44 @@ if test "$ZEN_RELEASE"; then
|
||||
ac_add_options --enable-lto=cross,thin
|
||||
fi
|
||||
|
||||
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
|
||||
|
||||
if test "$ZEN_RELEASE"; then
|
||||
ac_add_options --enable-wasm-avx
|
||||
ac_add_options --enable-optimize="-march=nehalem -mtune=haswell -O3 -w"
|
||||
|
||||
export CFLAGS="-O3 -march=nehalem"
|
||||
export CPPFLAGS="-O3 -march=nehalem"
|
||||
export CXXFLAGS="-O3 -march=nehalem"
|
||||
export LDFLAGS="-Wl,-O3 -march=nehalem"
|
||||
export RUSTFLAGS="-Ctarget-cpu=nehalem"
|
||||
ac_add_options --enable-optimize="-march=nehalem -mtune=haswell -O2 -w"
|
||||
fi
|
||||
else
|
||||
ac_add_options --enable-clang-plugin
|
||||
ac_add_options --target=aarch64-apple-darwin
|
||||
|
||||
if test "$ZEN_RELEASE"; then
|
||||
ac_add_options --enable-optimize="-O3 -mcpu=apple-m1 -march=armv8.3-a+simd"
|
||||
ac_add_options --enable-optimize="-O2 -mcpu=apple-m1"
|
||||
|
||||
# As of Clang 13, the default is -mcpu=apple-m1 when using a aarch64-apple-macos target,
|
||||
# but we're using apple64-apple-darwin, which defaults to -mcpu=apple-a7, which disables
|
||||
# a bunch of # performance-enabling CPU features.
|
||||
export CFLAGS="-O3 -march=armv8.3-a+simd -mcpu=apple-m1"
|
||||
export CPPFLAGS="-O3 -march=armv8.3-a+simd -mcpu=apple-m1"
|
||||
export CXXFLAGS="-O3 -march=armv8.3-a+simd -mcpu=apple-m1"
|
||||
export LDFLAGS="-Wl,-O3 -march=armv8.3-a+simd -mcpu=apple-m1"
|
||||
export RUSTFLAGS="-C target-feature=+v8.3a -Ctarget-cpu=apple-m1"
|
||||
# TODO: We'll want to switch to aarch64-apple-macos eventually.
|
||||
export CFLAGS="$CFLAGS -mcpu=apple-m1"
|
||||
export CXXFLAGS="$CXXFLAGS -mcpu=apple-m1"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Keep using ld64 on PGO/LTO builds because of performance regressions when using lld.
|
||||
# Mozilla sets "MOZ_LD64_KNOWN_GOOD" to true when they do automated builds with PGO/LTO on macOS.
|
||||
# See https://searchfox.org/firefox-main/rev/e61d59b5c9a651fd7bf28043f87c0dc669833496/build/moz.configure/lto-pgo.configure#261
|
||||
export MOZ_LD64_KNOWN_GOOD=1
|
||||
ac_add_options --enable-linker=ld64
|
||||
|
||||
if test "$ZEN_RELEASE"; then
|
||||
if ! test "$ZEN_GA_DISABLE_PGO"; then
|
||||
if test "$ZEN_GENERATE_PGO_DATA"; then
|
||||
mk_add_options "export MOZ_AUTOMATION_PACKAGE_GENERATED_SOURCES=0"
|
||||
ac_add_options --enable-profile-generate=cross
|
||||
else
|
||||
ac_add_options --enable-profile-use=cross
|
||||
ac_add_options --with-pgo-profile-path=$(echo ~)/artifact/merged.profdata
|
||||
ac_add_options --with-pgo-jarlog=$(echo ~)/artifact/en-US.log
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -36,8 +36,8 @@ if test "$SURFER_COMPAT" = "x86_64"; then
|
||||
|
||||
ac_add_options --enable-optimize="-O3 -w -ftree-vectorize -mfpmath=sse -mprfchw -msse3 -mcx16 -msahf"
|
||||
|
||||
export LDFLAGS="-Wl,-O3"
|
||||
export RUSTFLAGS="-Clink-args=--icf=safe"
|
||||
export LDFLAGS="$LDFLAGS -Wl,-O3"
|
||||
export RUSTFLAGS="$RUSTFLAGS -Clink-args=--icf=safe"
|
||||
elif test "$SURFER_COMPAT" = "aarch64"; then
|
||||
ac_add_options --target=aarch64-pc-windows-msvc
|
||||
ac_add_options --enable-eme=widevine
|
||||
@@ -62,9 +62,7 @@ if test "$ZEN_CROSS_COMPILING"; then
|
||||
ac_add_options --enable-profile-generate=cross
|
||||
elif test "$SURFER_COMPAT" = "x86_64"; then
|
||||
# Dont use PGO on aarch64 builds and the ZEN_GA_DISABLE_PGO flag is not set
|
||||
if test "$ZEN_GA_DISABLE_PGO"; then
|
||||
export ZEN_DUMMY=1
|
||||
else
|
||||
if ! test "$ZEN_GA_DISABLE_PGO"; then
|
||||
ac_add_options --enable-profile-use=cross
|
||||
ac_add_options --with-pgo-profile-path=$(echo ~)/artifact/merged.profdata
|
||||
ac_add_options --with-pgo-jarlog=$(echo ~)/artifact/en-US.log
|
||||
|
||||
@@ -10,7 +10,10 @@ zen-menubar-toggle-pinned-tabs =
|
||||
}
|
||||
|
||||
zen-menubar-appearance =
|
||||
.label = Website Appearance
|
||||
.label = Appearance
|
||||
|
||||
zen-menubar-appearance-description =
|
||||
.label = Websites will use:
|
||||
|
||||
zen-menubar-appearance-auto =
|
||||
.label = Automatic
|
||||
|
||||
6
prefs/zen/share.yaml
Normal file
6
prefs/zen/share.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
- name: zen.share.enabled
|
||||
value: true
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..41bddb36fef7bb74212c261f1c07e40b30ab5f08 100644
|
||||
index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..429a26849cec23836f5bff3bd1a6376050311377 100644
|
||||
--- a/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
+++ b/browser/components/sessionstore/SessionStore.sys.mjs
|
||||
@@ -127,6 +127,9 @@ const TAB_EVENTS = [
|
||||
@@ -211,17 +211,20 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..41bddb36fef7bb74212c261f1c07e40b
|
||||
tabbrowser.removeTab(tabbrowser.tabs[i]);
|
||||
}
|
||||
}
|
||||
@@ -5821,6 +5851,9 @@ var SessionStoreInternal = {
|
||||
@@ -5821,6 +5851,12 @@ var SessionStoreInternal = {
|
||||
savedTabGroup => !openTabGroupIdsInWindow.has(savedTabGroup.id)
|
||||
);
|
||||
}
|
||||
+ if (winData.isZenUnsynced) {
|
||||
+ aWindow.document.documentElement.setAttribute("zen-unsynced-window", "true");
|
||||
+ }
|
||||
+ aWindow.gZenFolders?.restoreDataFromSessionStore(winData.folders);
|
||||
+ aWindow.gZenViewSplitter?.restoreDataFromSessionStore(winData.splitViewData);
|
||||
+ aWindow.gZenWorkspaces?.restoreWorkspacesFromSessionStore(winData);
|
||||
|
||||
// Move the originally open tabs to the end.
|
||||
if (initialTabs) {
|
||||
@@ -6372,6 +6405,25 @@ var SessionStoreInternal = {
|
||||
@@ -6372,6 +6408,25 @@ var SessionStoreInternal = {
|
||||
|
||||
// Most of tabData has been restored, now continue with restoring
|
||||
// attributes that may trigger external events.
|
||||
@@ -247,7 +250,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..41bddb36fef7bb74212c261f1c07e40b
|
||||
|
||||
if (tabData.pinned) {
|
||||
tabbrowser.pinTab(tab);
|
||||
@@ -7290,7 +7342,7 @@ var SessionStoreInternal = {
|
||||
@@ -7290,7 +7345,7 @@ var SessionStoreInternal = {
|
||||
|
||||
let groupsToSave = new Map();
|
||||
for (let tIndex = 0; tIndex < window.tabs.length; ) {
|
||||
@@ -256,7 +259,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..41bddb36fef7bb74212c261f1c07e40b
|
||||
// Adjust window.selected
|
||||
if (tIndex + 1 < window.selected) {
|
||||
window.selected -= 1;
|
||||
@@ -7305,7 +7357,7 @@ var SessionStoreInternal = {
|
||||
@@ -7305,7 +7360,7 @@ var SessionStoreInternal = {
|
||||
);
|
||||
// We don't want to increment tIndex here.
|
||||
continue;
|
||||
|
||||
12
src/build/moz-configure/lto-pgo-configure.patch
Normal file
12
src/build/moz-configure/lto-pgo-configure.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/build/moz.configure/lto-pgo.configure b/build/moz.configure/lto-pgo.configure
|
||||
index 165541b79842672d8bac48722220532f3913556d..6781b84b9c06ff26a41a0e7d8be5a958600fda62 100644
|
||||
--- a/build/moz.configure/lto-pgo.configure
|
||||
+++ b/build/moz.configure/lto-pgo.configure
|
||||
@@ -258,7 +258,6 @@ option(
|
||||
help="Indicate that ld64 is free of symbol aliasing bugs",
|
||||
)
|
||||
|
||||
-imply_option("MOZ_LD64_KNOWN_GOOD", moz_automation)
|
||||
|
||||
use_fat_lto = cxx_compiler.try_link(
|
||||
ldflags=depends(stlport_libs)(
|
||||
13
src/build/moz-configure/toolchain-configure.patch
Normal file
13
src/build/moz-configure/toolchain-configure.patch
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure
|
||||
index 3d8d2ea651fa1320306b32b0f7b1b73e0da1df61..257f75a92a26d7a724353c614365924d230aef83 100644
|
||||
--- a/build/moz.configure/toolchain.configure
|
||||
+++ b/build/moz.configure/toolchain.configure
|
||||
@@ -1991,7 +1991,7 @@ def select_linker_tmpl(host_or_target):
|
||||
# ensure consistent output.
|
||||
env["LC_ALL"] = "C"
|
||||
retcode, stdout, stderr = get_cmd_output(*cmd, env=env)
|
||||
- if retcode == 1 and "Logging ld64 options" in stderr:
|
||||
+ if retcode == 1 and "ld: unknown options: --version" in stderr:
|
||||
kind = "ld64"
|
||||
|
||||
elif retcode != 0:
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/toolkit/components/prompts/content/commonDialog.css b/toolkit/components/prompts/content/commonDialog.css
|
||||
index d811fb62d502cf6fc0bf8163f11e1d264dee9e82..0095175bce6fb4520aca357e5209e1ad7329bbdb 100644
|
||||
--- a/toolkit/components/prompts/content/commonDialog.css
|
||||
+++ b/toolkit/components/prompts/content/commonDialog.css
|
||||
@@ -88,7 +88,7 @@ dialog[insecureauth] {
|
||||
|
||||
/* Fix padding/spacing */
|
||||
dialog {
|
||||
- --grid-padding: 16px;
|
||||
+ --grid-padding: 24px;
|
||||
/* All the inner items should have 4px inline margin, leading to 1.16em spacing
|
||||
* between the dialog and its contents, and 8px horizontal spacing between items. */
|
||||
padding: var(--grid-padding) calc(var(--grid-padding) - 4px);
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/toolkit/themes/shared/design-system/tokens-brand.css b/toolkit/themes/shared/design-system/tokens-brand.css
|
||||
index 3ad65bc44fe06be77c4e5e679bb52bd0813cc972..3906b0bbcbbe6149ed7131460305074f079090a7 100644
|
||||
--- a/toolkit/themes/shared/design-system/tokens-brand.css
|
||||
+++ b/toolkit/themes/shared/design-system/tokens-brand.css
|
||||
@@ -6,6 +6,7 @@
|
||||
* and run `npm run build` to see your changes. */
|
||||
|
||||
@import url("chrome://global/skin/design-system/tokens-shared.css");
|
||||
+@import url("chrome://browser/content/zen-styles/zen-theme.css");
|
||||
|
||||
@layer tokens-foundation {
|
||||
:root,
|
||||
@@ -1,16 +1,7 @@
|
||||
diff --git a/toolkit/themes/shared/in-content/common-shared.css b/toolkit/themes/shared/in-content/common-shared.css
|
||||
index 41f65a1f2c3065631780b02d820f632abdf542af..c01c2957367da968d106c83117e45800bb6b15e5 100644
|
||||
index 41f65a1f2c3065631780b02d820f632abdf542af..d15ff979c5d2deecca3d232f68551bec10ba6b8f 100644
|
||||
--- a/toolkit/themes/shared/in-content/common-shared.css
|
||||
+++ b/toolkit/themes/shared/in-content/common-shared.css
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
@import url("chrome://global/skin/design-system/tokens-brand.css");
|
||||
@import url("chrome://global/skin/design-system/text-and-typography.css");
|
||||
-
|
||||
+@import url("chrome://browser/content/zen-styles/zen-theme.css");
|
||||
@namespace html "http://www.w3.org/1999/xhtml";
|
||||
@namespace xul "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
* this in forced colors mode, as we should be using system colours then.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ class nsZenMenuBar {
|
||||
let appearanceMenu = window.MozXULElement.parseXULToFragment(`
|
||||
<menu data-l10n-id="zen-menubar-appearance">
|
||||
<menupopup>
|
||||
<menuitem data-l10n-id="zen-menubar-appearance-description" disabled="true" />
|
||||
<menuitem data-l10n-id="zen-menubar-appearance-auto" data-type="auto" type="radio" checked="true" />
|
||||
<menuitem data-l10n-id="zen-menubar-appearance-light" data-type="light" type="radio" />
|
||||
<menuitem data-l10n-id="zen-menubar-appearance-dark" data-type="dark" type="radio" />
|
||||
|
||||
@@ -86,3 +86,15 @@
|
||||
box-shadow: 0 0 250px color-mix(in srgb, var(--zen-primary-color), transparent 100%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zen-dialog-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
background: var(--zen-main-browser-background);
|
||||
opacity: var(--zen-background-opacity);
|
||||
transition: 0s;
|
||||
background-blend-mode: screen;
|
||||
}
|
||||
|
||||
&:is(.zen-toolbar-background) {
|
||||
@@ -70,6 +71,7 @@
|
||||
background: var(--zen-main-browser-background-old);
|
||||
opacity: calc(1 - var(--zen-background-opacity));
|
||||
transition: 0s;
|
||||
background-blend-mode: screen;
|
||||
}
|
||||
|
||||
&:is(.zen-toolbar-background) {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
/** These types of buttons look INSAINELY bad in the preferences page */
|
||||
xul|button {
|
||||
--size-item-large: 34px;
|
||||
|
||||
border-radius: var(--zen-button-border-radius) !important;
|
||||
padding: var(--zen-button-padding) !important;
|
||||
transition: 0.1s;
|
||||
@@ -18,6 +20,7 @@ xul|button {
|
||||
font-weight: 500 !important;
|
||||
|
||||
border: 1px solid var(--zen-colors-border);
|
||||
border-bottom-width: 2px;
|
||||
}
|
||||
|
||||
button:not(#zen-workspaces-button):active {
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
/* Zen Welcome dialog override */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.dialogBox:not(.spotlightBox) {
|
||||
border: 1px solid var(--zen-colors-border);
|
||||
.dialogBox {
|
||||
border: none;
|
||||
outline: 1px solid #a8a8a9;
|
||||
animation: zen-dialog-fade-in 0.3s ease-out;
|
||||
border-radius: 12px !important;
|
||||
@media (prefers-color-scheme: dark) {
|
||||
outline-color: #44495a;
|
||||
outline-offset: -2px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
}
|
||||
.dialogBox:not(.spotlightBox) {
|
||||
min-width: min(80vw, 376px);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ body > #confetti {
|
||||
|
||||
/* Customizable modes */
|
||||
#customization-container {
|
||||
--toolbar-bgcolor: var(--zen-dialog-background);
|
||||
--toolbar-bgcolor: var(--arrowpanel-background);
|
||||
}
|
||||
|
||||
/* Site Data popup */
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
--zen-background-opacity: 1;
|
||||
|
||||
/* Branding */
|
||||
--zen-branding-dark: #1d1d1d;
|
||||
--zen-branding-paper: #ebebeb;
|
||||
--zen-branding-dark: #101010;
|
||||
--zen-branding-paper: #e2e2e2;
|
||||
|
||||
--zen-branding-bg: light-dark(var(--zen-branding-paper), var(--zen-branding-dark));
|
||||
--zen-branding-bg-reverse: light-dark(var(--zen-branding-dark), var(--zen-branding-paper));
|
||||
@@ -46,8 +46,8 @@
|
||||
color-mix(in srgb, var(--zen-primary-color) 80%, white 20%)
|
||||
);
|
||||
--zen-colors-border: light-dark(
|
||||
color-mix(in srgb, var(--zen-colors-secondary) 97%, black 3%),
|
||||
color-mix(in srgb, var(--zen-colors-secondary) 20%, rgb(79, 79, 79) 80%)
|
||||
color-mix(in srgb, var(--zen-colors-secondary) 50%, transparent),
|
||||
color-mix(in srgb, var(--zen-colors-secondary) 20%, rgb(79, 79, 79))
|
||||
);
|
||||
--zen-colors-border-contrast: light-dark(
|
||||
color-mix(in srgb, var(--zen-colors-secondary) 10%, rgba(181, 181, 181, 0.11) 90%),
|
||||
@@ -59,7 +59,7 @@
|
||||
color-mix(in srgb, var(--zen-primary-color) 1%, var(--zen-branding-bg) 99%)
|
||||
);
|
||||
|
||||
--zen-dialog-background: light-dark(rgb(244, 244, 244), rgb(31, 31, 31));
|
||||
--zen-dialog-background: light-dark(#FAFBFF, #161C31);
|
||||
--zen-urlbar-background: light-dark(
|
||||
color-mix(in srgb, var(--zen-primary-color) 3%, #f4f4f4 97%),
|
||||
color-mix(in srgb, var(--zen-primary-color) 4%, rgb(24, 24, 24) 96%)
|
||||
@@ -113,6 +113,9 @@
|
||||
--button-primary-active-bgcolor: var(--in-content-primary-button-background-active) !important;
|
||||
--button-primary-color: var(--in-content-primary-button-text-color) !important;
|
||||
|
||||
/* For dialogs / modals */
|
||||
--button-background-color-primary: var(--button-primary-bgcolor) !important;
|
||||
|
||||
--button-background-color: var(--in-content-button-background) !important;
|
||||
--button-background-color-hover: var(--in-content-button-background-hover) !important;
|
||||
--button-background-color-active: color-mix(in srgb, currentColor 5%, transparent 95%) !important;
|
||||
@@ -247,7 +250,7 @@
|
||||
}
|
||||
|
||||
--toolbar-field-background-color: var(--zen-colors-input-bg) !important;
|
||||
--arrowpanel-background: var(--zen-dialog-background) !important;
|
||||
--arrowpanel-background: light-dark(rgb(244, 244, 244), rgb(31, 31, 31)) !important;
|
||||
|
||||
--panel-separator-color: color-mix(in srgb, currentColor 15%, transparent) !important;
|
||||
|
||||
|
||||
@@ -433,18 +433,16 @@ window.gZenCompactModeManager = {
|
||||
}
|
||||
if (canHideSidebar && isCompactMode) {
|
||||
this._setElementExpandAttribute(this.sidebar, false);
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
gZenUIManager
|
||||
.elementAnimate(
|
||||
this.sidebar,
|
||||
{
|
||||
marginRight: [0, this.sidebarIsOnRight ? `-${sidebarWidth}px` : 0],
|
||||
marginLeft: [0, this.sidebarIsOnRight ? 0 : `-${sidebarWidth}px`],
|
||||
marginRight: ['0px', this.sidebarIsOnRight ? `-${sidebarWidth}px` : '0px'],
|
||||
marginLeft: ['0px', this.sidebarIsOnRight ? '0px' : `-${sidebarWidth}px`],
|
||||
},
|
||||
{
|
||||
ease: 'easeIn',
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
duration: 0.12,
|
||||
easing: 'ease-in',
|
||||
duration: 120,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
@@ -467,8 +465,6 @@ window.gZenCompactModeManager = {
|
||||
});
|
||||
}
|
||||
|
||||
this.sidebar.style.removeProperty('margin-right');
|
||||
this.sidebar.style.removeProperty('margin-left');
|
||||
this.sidebar.style.removeProperty('transition');
|
||||
this.sidebar.style.removeProperty('transform');
|
||||
this.sidebar.style.removeProperty('point-events');
|
||||
@@ -716,14 +712,8 @@ window.gZenCompactModeManager = {
|
||||
// If we want the toolbars to be draggable, we need to make sure to check the hover state after a short delay.
|
||||
// This is because the mouse is left to be handled natively so firefox thinks the mouse left the window for a split second.
|
||||
setTimeout(() => {
|
||||
let isHovered = event.target.matches(':hover');
|
||||
MousePosTracker._callListener({
|
||||
onMouseEnter: () => (isHovered = true),
|
||||
onMouseLeave: () => {},
|
||||
getMouseTargetRect: () => target.getBoundingClientRect(),
|
||||
});
|
||||
// Let's double check if the mouse is still hovering over the element, see the bug above.
|
||||
if (isHovered) {
|
||||
if (event.target.matches(':hover')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,12 +122,15 @@
|
||||
}
|
||||
// Apply a transform translate to the tab in order to center it within the drag image
|
||||
// based on the event coordinates.
|
||||
tabClone.style.transform = `translate(${(tabRect.width - dragData.offsetX) / 2}px, ${(tabRect.height - dragData.offsetY) / 2}px)`;
|
||||
if (!movingTabs.length > 1) {
|
||||
tabClone.style.transform = `translate(${(tabRect.width - dragData.offsetX) / 2}px, ${(tabRect.height - dragData.offsetY) / 2}px)`;
|
||||
}
|
||||
wrapper.appendChild(tabClone);
|
||||
}
|
||||
this.#maybeCreateDragImageDot(movingTabs, wrapper);
|
||||
wrapper.style.width = tabRect.width + 'px';
|
||||
wrapper.style.height = tabRect.height * movingTabs.length + 'px';
|
||||
wrapper.style.overflow = 'clip';
|
||||
wrapper.style.position = 'fixed';
|
||||
wrapper.style.top = '-9999px';
|
||||
periphery.appendChild(wrapper);
|
||||
|
||||
@@ -118,6 +118,9 @@ export class nsZenFolder extends MozTabbrowserTabGroup {
|
||||
}
|
||||
|
||||
get childActiveGroups() {
|
||||
if (this.tagName === 'zen-workspace-collapsible-pins') {
|
||||
return Array.from(this.parentElement.querySelectorAll('zen-folder[has-active]'));
|
||||
}
|
||||
return Array.from(this.querySelectorAll('zen-folder[has-active]'));
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
ARC_HEIGHT_RATIO: 0.2, // Arc height = distance * ratio (capped at MAX_ARC_HEIGHT)
|
||||
});
|
||||
|
||||
#GLANCE_ANIMATION_DURATION = Services.prefs.getIntPref('zen.glance.animation-duration');
|
||||
#GLANCE_ANIMATION_DURATION = Services.prefs.getIntPref('zen.glance.animation-duration') / 1000;
|
||||
|
||||
init() {
|
||||
this.#setupEventListeners();
|
||||
@@ -253,21 +253,19 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
const xOffset = gZenVerticalTabsManager._prefsRightSide ? 20 : -20;
|
||||
|
||||
setTimeout(() => {
|
||||
gZenUIManager.elementAnimate(
|
||||
container,
|
||||
{
|
||||
opacity: [0, 1],
|
||||
x: [xOffset, 0],
|
||||
},
|
||||
{
|
||||
duration: 200,
|
||||
easing: 'ease-in-out',
|
||||
fill: 'forwards',
|
||||
delay: this.#GLANCE_ANIMATION_DURATION - 200,
|
||||
}
|
||||
);
|
||||
});
|
||||
gZenUIManager.motion.animate(
|
||||
container,
|
||||
{
|
||||
opacity: [0, 1],
|
||||
x: [xOffset, 0],
|
||||
},
|
||||
{
|
||||
duration: 0.2,
|
||||
type: 'spring',
|
||||
delay: this.#GLANCE_ANIMATION_DURATION - 0.2,
|
||||
bounce: 0,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,7 +403,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
'.browserSidebarContainer'
|
||||
);
|
||||
|
||||
gZenUIManager.elementAnimate(
|
||||
gZenUIManager.motion.animate(
|
||||
parentSidebarContainer,
|
||||
{
|
||||
scale: [1, 0.98],
|
||||
@@ -413,8 +411,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
},
|
||||
{
|
||||
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||
easing: 'ease-in-out',
|
||||
fill: 'forwards',
|
||||
type: 'spring',
|
||||
bounce: 0.2,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -430,7 +428,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
this.overlay.removeAttribute('fade-out');
|
||||
this.browserWrapper.setAttribute('animate', true);
|
||||
this.browserWrapper.style.transform = `translate(${left}px, ${top}px)`;
|
||||
this.browserWrapper.style.top = `${top}px`;
|
||||
this.browserWrapper.style.left = `${left}px`;
|
||||
this.browserWrapper.style.width = `${width}px`;
|
||||
this.browserWrapper.style.height = `${height}px`;
|
||||
|
||||
@@ -442,18 +441,9 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* Store the original position for later restoration
|
||||
*/
|
||||
#storeOriginalPosition() {
|
||||
let transform = this.browserWrapper.style.transform;
|
||||
let [top, left] = [0, 0];
|
||||
if (transform && transform.startsWith('translate(')) {
|
||||
const match = transform.match(/translate\(([-\d.]+)px,\s*([-\d.]+)px\)/);
|
||||
if (match) {
|
||||
left = parseFloat(match[1]);
|
||||
top = parseFloat(match[2]);
|
||||
}
|
||||
}
|
||||
this.#glances.get(this.#currentGlanceID).originalPosition = {
|
||||
top,
|
||||
left,
|
||||
top: this.browserWrapper.style.top,
|
||||
left: this.browserWrapper.style.left,
|
||||
width: this.browserWrapper.style.width,
|
||||
height: this.browserWrapper.style.height,
|
||||
};
|
||||
@@ -483,14 +473,14 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.browserWrapper.prepend(imageDataElement);
|
||||
this.#glances.get(this.#currentGlanceID).elementImageData = data.elementData;
|
||||
|
||||
gZenUIManager.elementAnimate(
|
||||
gZenUIManager.motion.animate(
|
||||
imageDataElement,
|
||||
{
|
||||
opacity: [1, 0],
|
||||
},
|
||||
{
|
||||
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
||||
easing: 'ease-in-out',
|
||||
easing: 'easeInOut',
|
||||
}
|
||||
);
|
||||
|
||||
@@ -510,6 +500,16 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
browserElement.style.minHeight = `${minHeight}px`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transform origin for the animation
|
||||
* @param {Object} data - Glance data with position and dimensions
|
||||
* @returns {string} The transform origin CSS value
|
||||
*/
|
||||
#getTransformOrigin(data) {
|
||||
const { clientX, clientY } = data;
|
||||
return `${clientX}px ${clientY}px`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the main glance animation
|
||||
* @param {Object} data - Glance data
|
||||
@@ -521,18 +521,21 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
|
||||
// Create curved animation sequence
|
||||
const arcSequence = this.#createGlanceArcSequence(data, 'opening');
|
||||
const transformOrigin = this.#getTransformOrigin(data);
|
||||
|
||||
this.browserWrapper.style.transformOrigin = transformOrigin;
|
||||
|
||||
// Only animate if there is element data, so we can apply a
|
||||
// nice fade-in effect to the content. But if it doesn't exist,
|
||||
// we just fall back to always showing the browser directly.
|
||||
if (data.elementData) {
|
||||
gZenUIManager
|
||||
.elementAnimate(
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
this.contentWrapper,
|
||||
{ opacity: [0, 1] },
|
||||
{
|
||||
duration: this.#GLANCE_ANIMATION_DURATION / 2,
|
||||
easing: 'ease-in-out',
|
||||
easing: 'easeInOut',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
@@ -541,9 +544,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
}
|
||||
|
||||
this.#animateParentBackground();
|
||||
gZenUIManager
|
||||
.elementAnimate(this.browserWrapper, arcSequence, {
|
||||
gZenUIManager.motion
|
||||
.animate(this.browserWrapper, arcSequence, {
|
||||
duration: gZenUIManager.testingEnabled ? 0 : this.#GLANCE_ANIMATION_DURATION,
|
||||
ease: 'easeInOut',
|
||||
})
|
||||
.then(() => {
|
||||
this.#finalizeGlanceOpening(imageDataElement, browserElement, resolve);
|
||||
@@ -603,29 +607,28 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
);
|
||||
|
||||
const sequence = {
|
||||
transform: [],
|
||||
top: [],
|
||||
left: [],
|
||||
width: [],
|
||||
height: [],
|
||||
transform: [],
|
||||
};
|
||||
|
||||
const steps = this.#ARC_CONFIG.ARC_STEPS;
|
||||
const arcDirection = shouldArcDownward ? 1 : -1;
|
||||
|
||||
function easeOutBack(x) {
|
||||
const c1 = 0.4;
|
||||
const c3 = c1 + 1;
|
||||
|
||||
return 1 + c3 * (x - 1) ** 3 + c1 * (x - 1) ** 2;
|
||||
function easeInOutQuad(t) {
|
||||
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
||||
}
|
||||
|
||||
function easeInQuint(x) {
|
||||
return x * x * x * x * x;
|
||||
function easeOutCubic(t) {
|
||||
return 1 - Math.pow(1 - t, 6);
|
||||
}
|
||||
|
||||
// First, create the main animation steps
|
||||
for (let i = 0; i <= steps; i++) {
|
||||
const progress = i / steps;
|
||||
const eased = direction === 'opening' ? easeOutBack(progress) : easeInQuint(progress);
|
||||
const eased = direction === 'opening' ? easeInOutQuad(progress) : easeOutCubic(progress);
|
||||
|
||||
// Calculate size interpolation
|
||||
const currentWidth = startPosition.width + (endPosition.width - startPosition.width) * eased;
|
||||
@@ -640,11 +643,32 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
const y =
|
||||
startPosition.y + distanceY * eased + arcDirection * arcHeight * (1 - (2 * eased - 1) ** 2);
|
||||
|
||||
sequence.transform.push(`translate(${x}px, ${y}px)`);
|
||||
sequence.transform.push(`translate(-50%, -50%) scale(1)`);
|
||||
sequence.top.push(`${y}px`);
|
||||
sequence.left.push(`${x}px`);
|
||||
sequence.width.push(`${currentWidth}px`);
|
||||
sequence.height.push(`${currentHeight}px`);
|
||||
}
|
||||
|
||||
let scale = 1;
|
||||
const bounceSteps = 60;
|
||||
if (direction === 'opening') {
|
||||
for (let i = 0; i < bounceSteps; i++) {
|
||||
const progress = i / bounceSteps;
|
||||
// Scale up slightly then back to normal
|
||||
scale = 1 + 0.003 * Math.sin(progress * Math.PI);
|
||||
// If we are at the last step, ensure scale is exactly 1
|
||||
if (i === bounceSteps - 1) {
|
||||
scale = 1;
|
||||
}
|
||||
sequence.transform.push(`translate(-50%, -50%) scale(${scale})`);
|
||||
sequence.top.push(sequence.top[sequence.top.length - 1]);
|
||||
sequence.left.push(sequence.left[sequence.left.length - 1]);
|
||||
sequence.width.push(sequence.width[sequence.width.length - 1]);
|
||||
sequence.height.push(sequence.height[sequence.height.length - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
@@ -700,6 +724,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
imageDataElement.remove();
|
||||
}
|
||||
|
||||
this.browserWrapper.style.transformOrigin = '';
|
||||
|
||||
browserElement.style.minWidth = '';
|
||||
browserElement.style.minHeight = '';
|
||||
|
||||
@@ -866,14 +892,14 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
*/
|
||||
#animateSidebarButtons(sidebarButtons) {
|
||||
if (sidebarButtons) {
|
||||
gZenUIManager
|
||||
.elementAnimate(
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
sidebarButtons,
|
||||
{ opacity: [1, 0] },
|
||||
{
|
||||
duration: 100,
|
||||
easing: 'ease-in-out',
|
||||
fill: 'forwards',
|
||||
duration: 0.2,
|
||||
type: 'spring',
|
||||
bounce: this.#GLANCE_ANIMATION_DURATION - 0.1,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
@@ -902,8 +928,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
* @param {Element} browserSidebarContainer - The sidebar container
|
||||
*/
|
||||
#animateParentBackgroundClose(browserSidebarContainer) {
|
||||
gZenUIManager
|
||||
.elementAnimate(
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
browserSidebarContainer,
|
||||
{
|
||||
scale: [0.98, 1],
|
||||
@@ -911,7 +937,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
},
|
||||
{
|
||||
duration: this.#GLANCE_ANIMATION_DURATION / 1.5,
|
||||
easing: 'ease-in-out',
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
@@ -938,9 +965,10 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
const closingData = this.#createClosingDataFromOriginalPosition(originalPosition);
|
||||
const arcSequence = this.#createGlanceArcSequence(closingData, 'closing');
|
||||
|
||||
gZenUIManager
|
||||
.elementAnimate(this.browserWrapper, arcSequence, {
|
||||
gZenUIManager.motion
|
||||
.animate(this.browserWrapper, arcSequence, {
|
||||
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||
ease: 'easeOut',
|
||||
})
|
||||
.then(() => {
|
||||
// Remove element preview after closing animation
|
||||
@@ -1457,7 +1485,7 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
this.browserWrapper.style.width = `${browserRect.width}px`;
|
||||
this.browserWrapper.style.height = `${browserRect.height}px`;
|
||||
|
||||
await gZenUIManager.elementAnimate(
|
||||
await gZenUIManager.motion.animate(
|
||||
this.browserWrapper,
|
||||
{
|
||||
width: ['85%', '100%'],
|
||||
@@ -1465,7 +1493,8 @@ class nsZenGlanceManager extends nsZenDOMOperatedFeature {
|
||||
},
|
||||
{
|
||||
duration: this.#GLANCE_ANIMATION_DURATION,
|
||||
easing: 'ease-in-out',
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
left: 0;
|
||||
flex: unset !important;
|
||||
/* Promote to its own layer during transitions to reduce jank */
|
||||
will-change: transform;
|
||||
will-change: transform, top, left;
|
||||
width: 85%;
|
||||
height: 100%;
|
||||
|
||||
@@ -148,10 +148,6 @@
|
||||
box-shadow: var(--zen-big-shadow);
|
||||
}
|
||||
|
||||
&:not([has-finished-animation='true']) .browserStack {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
& browser {
|
||||
background: light-dark(rgb(255, 255, 255), rgb(32, 32, 32)) !important;
|
||||
width: 100%;
|
||||
|
||||
@@ -15,4 +15,5 @@ DIRS += [
|
||||
"urlbar",
|
||||
"toolkit",
|
||||
"sessionstore",
|
||||
"share",
|
||||
]
|
||||
|
||||
@@ -14,6 +14,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
SessionStore: 'resource:///modules/sessionstore/SessionStore.sys.mjs',
|
||||
SessionSaver: 'resource:///modules/sessionstore/SessionSaver.sys.mjs',
|
||||
setTimeout: 'resource://gre/modules/Timer.sys.mjs',
|
||||
gWindowSyncEnabled: 'resource:///modules/zen/ZenWindowSync.sys.mjs',
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(lazy, 'gShouldLog', 'zen.session-store.log', true);
|
||||
@@ -71,10 +72,6 @@ export class nsZenSessionManager {
|
||||
compression: SHOULD_COMPRESS_FILE ? 'lz4' : undefined,
|
||||
backupFile,
|
||||
});
|
||||
|
||||
lazy.SessionStore.promiseAllWindowsRestored.then(() => {
|
||||
delete this._migrationData;
|
||||
});
|
||||
}
|
||||
|
||||
log(...args) {
|
||||
@@ -125,6 +122,7 @@ export class nsZenSessionManager {
|
||||
*/
|
||||
async readFile() {
|
||||
try {
|
||||
this.log('Reading Zen session file from disk');
|
||||
let promises = [];
|
||||
promises.push(this.#file.load());
|
||||
if (!Services.prefs.getBoolPref(MIGRATION_PREF, false)) {
|
||||
@@ -145,6 +143,7 @@ export class nsZenSessionManager {
|
||||
* The initial session state read from the session file.
|
||||
*/
|
||||
onFileRead(initialState) {
|
||||
if (!lazy.gWindowSyncEnabled) return;
|
||||
// For the first time after migration, we restore the tabs
|
||||
// That where going to be restored by SessionStore. The sidebar
|
||||
// object will always be empty after migration because we haven't
|
||||
@@ -175,6 +174,7 @@ export class nsZenSessionManager {
|
||||
// Save the state to the sidebar object so that it gets written
|
||||
// to the session file.
|
||||
this.saveState(initialState);
|
||||
delete this._migrationData;
|
||||
return;
|
||||
}
|
||||
// If there are no windows, we create an empty one. By default,
|
||||
@@ -233,7 +233,7 @@ export class nsZenSessionManager {
|
||||
* @param state The current session state.
|
||||
*/
|
||||
saveState(state) {
|
||||
if (!state?.windows?.length) {
|
||||
if (!state?.windows?.length || !lazy.gWindowSyncEnabled) {
|
||||
// Don't save (or even collect) anything in permanent private
|
||||
// browsing mode. We also don't want to save if there are no windows.
|
||||
return;
|
||||
@@ -350,7 +350,7 @@ export class nsZenSessionManager {
|
||||
* Whether this new window is being restored from a closed window.
|
||||
*/
|
||||
restoreNewWindow(aWindow, SessionStoreInternal, fromClosedWindow = false) {
|
||||
if (aWindow.gZenWorkspaces?.privateWindowOrDisabled) {
|
||||
if (aWindow.gZenWorkspaces?.privateWindowOrDisabled || !lazy.gWindowSyncEnabled) {
|
||||
return;
|
||||
}
|
||||
this.log('Restoring new window with Zen session data');
|
||||
@@ -401,6 +401,7 @@ export class nsZenSessionManager {
|
||||
* @returns
|
||||
*/
|
||||
onNewEmptySession(aWindow) {
|
||||
this.log('Restoring empty session with Zen session data');
|
||||
aWindow.gZenWorkspaces.restoreWorkspacesFromSessionStore({
|
||||
spaces: this.#sidebar.spaces || [],
|
||||
});
|
||||
|
||||
@@ -68,6 +68,12 @@ class nsZenWindowSync {
|
||||
lastHandlerPromise: Promise.resolve(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Map of sync handlers for different event types.
|
||||
* Each handler is a function that takes the event as an argument.
|
||||
*/
|
||||
#syncHandlers = new Set();
|
||||
|
||||
/**
|
||||
* Last focused window.
|
||||
* Used to determine which window to sync tab contents visibility from.
|
||||
@@ -90,12 +96,7 @@ class nsZenWindowSync {
|
||||
#browserWindows = {
|
||||
*[Symbol.iterator]() {
|
||||
for (let window of lazy.BrowserWindowTracker.orderedWindows) {
|
||||
if (
|
||||
window.__SSi &&
|
||||
!window.closed &&
|
||||
window.gZenStartup.isReady &&
|
||||
!window.gZenWorkspaces?.privateWindowOrDisabled
|
||||
) {
|
||||
if (window.__SSi && !window.closed && !window.gZenWorkspaces?.privateWindowOrDisabled) {
|
||||
yield window;
|
||||
}
|
||||
}
|
||||
@@ -280,6 +281,25 @@ class nsZenWindowSync {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sync handler for a specific event type.
|
||||
* @param {Function} aHandler - The sync handler function to add.
|
||||
*/
|
||||
addSyncHandler(aHandler) {
|
||||
if (!aHandler || this.#syncHandlers.has(aHandler)) {
|
||||
return;
|
||||
}
|
||||
this.#syncHandlers.add(aHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a sync handler for a specific event type.
|
||||
* @param {Function} aHandler - The sync handler function to remove.
|
||||
*/
|
||||
removeSyncHandler(aHandler) {
|
||||
this.#syncHandlers.delete(aHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the next event by calling the appropriate handler method.
|
||||
*
|
||||
@@ -289,7 +309,17 @@ class nsZenWindowSync {
|
||||
const handler = `on_${aEvent.type}`;
|
||||
try {
|
||||
if (typeof this[handler] === 'function') {
|
||||
return this[handler](aEvent) || Promise.resolve();
|
||||
let promise = this[handler](aEvent) || Promise.resolve();
|
||||
promise.then(() => {
|
||||
for (let syncHandler of this.#syncHandlers) {
|
||||
try {
|
||||
syncHandler(aEvent);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
} else {
|
||||
throw new Error(`No handler for event type: ${aEvent.type}`);
|
||||
}
|
||||
@@ -308,7 +338,7 @@ class nsZenWindowSync {
|
||||
}
|
||||
let permanentKey = aTab.linkedBrowser.permanentKey;
|
||||
this.#runOnAllWindows(null, (win) => {
|
||||
const tab = this.#getItemFromWindow(win, aTab.id);
|
||||
const tab = this.getItemFromWindow(win, aTab.id);
|
||||
if (tab) {
|
||||
tab.linkedBrowser.permanentKey = permanentKey;
|
||||
tab.permanentKey = permanentKey;
|
||||
@@ -323,7 +353,7 @@ class nsZenWindowSync {
|
||||
* @param {string} aItemId - The ID of the item to retrieve.
|
||||
* @returns {MozTabbrowserTab|MozTabbrowserTabGroup|null} The item element if found, otherwise null.
|
||||
*/
|
||||
#getItemFromWindow(aWindow, aItemId) {
|
||||
getItemFromWindow(aWindow, aItemId) {
|
||||
if (!aItemId) {
|
||||
return null;
|
||||
}
|
||||
@@ -453,7 +483,7 @@ class nsZenWindowSync {
|
||||
let container;
|
||||
const parentGroup = aOriginalItem.group;
|
||||
if (parentGroup?.hasAttribute('id')) {
|
||||
container = this.#getItemFromWindow(aWindow, parentGroup.getAttribute('id'));
|
||||
container = this.getItemFromWindow(aWindow, parentGroup.getAttribute('id'));
|
||||
if (container) {
|
||||
if (container?.tabs?.length) {
|
||||
// First tab in folders is the empty tab placeholder.
|
||||
@@ -480,7 +510,7 @@ class nsZenWindowSync {
|
||||
}
|
||||
return;
|
||||
}
|
||||
const relativeTab = this.#getItemFromWindow(aWindow, originalSibling.id);
|
||||
const relativeTab = this.getItemFromWindow(aWindow, originalSibling.id);
|
||||
if (relativeTab) {
|
||||
gBrowser.tabContainer.tabDragAndDrop.handle_drop_transition(
|
||||
relativeTab,
|
||||
@@ -502,7 +532,7 @@ class nsZenWindowSync {
|
||||
#syncItemForAllWindows(aItem, flags = 0) {
|
||||
const window = aItem.ownerGlobal;
|
||||
this.#runOnAllWindows(window, (win) => {
|
||||
this.#syncItemWithOriginal(aItem, this.#getItemFromWindow(win, aItem.id), win, flags);
|
||||
this.#syncItemWithOriginal(aItem, this.getItemFromWindow(win, aItem.id), win, flags);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -713,7 +743,7 @@ class nsZenWindowSync {
|
||||
*/
|
||||
#getActiveTabFromOtherWindows(aWindow, aTabId, filter = (tab) => tab?._zenContentsVisible) {
|
||||
return this.#runOnAllWindows(aWindow, (win) => {
|
||||
const tab = this.#getItemFromWindow(win, aTabId);
|
||||
const tab = this.getItemFromWindow(win, aTabId);
|
||||
if (filter(tab)) {
|
||||
return tab;
|
||||
}
|
||||
@@ -735,7 +765,7 @@ class nsZenWindowSync {
|
||||
(tab) => tab._zenContentsVisible
|
||||
);
|
||||
for (let tab of activeTabsOnClosedWindow) {
|
||||
const targetTab = this.#getItemFromWindow(mostRecentWindow, tab.id);
|
||||
const targetTab = this.getItemFromWindow(mostRecentWindow, tab.id);
|
||||
if (targetTab) {
|
||||
targetTab._zenContentsVisible = true;
|
||||
this.log(`Moving active tab ${tab.id} to most recent window on close`);
|
||||
@@ -830,7 +860,7 @@ class nsZenWindowSync {
|
||||
image: state.image,
|
||||
};
|
||||
this.#runOnAllWindows(null, (win) => {
|
||||
const targetTab = this.#getItemFromWindow(win, aTab.id);
|
||||
const targetTab = this.getItemFromWindow(win, aTab.id);
|
||||
if (targetTab) {
|
||||
targetTab._zenPinnedInitialState = initialState;
|
||||
}
|
||||
@@ -958,7 +988,7 @@ class nsZenWindowSync {
|
||||
on_TabUnpinned(aEvent) {
|
||||
const tab = aEvent.target;
|
||||
this.#runOnAllWindows(null, (win) => {
|
||||
const targetTab = this.#getItemFromWindow(win, tab.id);
|
||||
const targetTab = this.getItemFromWindow(win, tab.id);
|
||||
if (targetTab) {
|
||||
delete targetTab._zenPinnedInitialState;
|
||||
}
|
||||
@@ -978,7 +1008,7 @@ class nsZenWindowSync {
|
||||
const tab = aEvent.target;
|
||||
const window = tab.ownerGlobal;
|
||||
this.#runOnAllWindows(window, (win) => {
|
||||
const targetTab = this.#getItemFromWindow(win, tab.id);
|
||||
const targetTab = this.getItemFromWindow(win, tab.id);
|
||||
if (targetTab) {
|
||||
win.gBrowser.removeTab(targetTab, { animate: true });
|
||||
}
|
||||
@@ -1052,7 +1082,7 @@ class nsZenWindowSync {
|
||||
const tabGroup = aEvent.target;
|
||||
const window = tabGroup.ownerGlobal;
|
||||
this.#runOnAllWindows(window, (win) => {
|
||||
const targetGroup = this.#getItemFromWindow(win, tabGroup.id);
|
||||
const targetGroup = this.getItemFromWindow(win, tabGroup.id);
|
||||
if (targetGroup) {
|
||||
if (targetGroup.isZenFolder) {
|
||||
targetGroup.delete();
|
||||
@@ -1075,7 +1105,7 @@ class nsZenWindowSync {
|
||||
const tab = aEvent.target;
|
||||
const window = tab.ownerGlobal;
|
||||
this.#runOnAllWindows(window, (win) => {
|
||||
const targetTab = this.#getItemFromWindow(win, tab.id);
|
||||
const targetTab = this.getItemFromWindow(win, tab.id);
|
||||
if (targetTab && win.gZenViewSplitter) {
|
||||
win.gZenViewSplitter.removeTabFromGroup(targetTab);
|
||||
}
|
||||
@@ -1088,7 +1118,7 @@ class nsZenWindowSync {
|
||||
const tabs = tabGroup.tabs;
|
||||
this.#runOnAllWindows(window, (win) => {
|
||||
const otherWindowTabs = tabs
|
||||
.map((tab) => this.#getItemFromWindow(win, tab.id))
|
||||
.map((tab) => this.getItemFromWindow(win, tab.id))
|
||||
.filter(Boolean);
|
||||
if (otherWindowTabs.length > 0 && win.gZenViewSplitter) {
|
||||
const group = win.gZenViewSplitter.splitTabs(otherWindowTabs, 'grid', -1);
|
||||
@@ -1104,4 +1134,5 @@ class nsZenWindowSync {
|
||||
}
|
||||
}
|
||||
|
||||
export const gWindowSyncEnabled = lazy.gWindowSyncEnabled;
|
||||
export const ZenWindowSync = new nsZenWindowSync();
|
||||
|
||||
7
src/zen/share/moz.build
Normal file
7
src/zen/share/moz.build
Normal file
@@ -0,0 +1,7 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES.zen.share += [
|
||||
"share.schema.json",
|
||||
]
|
||||
154
src/zen/share/share.schema.json
Normal file
154
src/zen/share/share.schema.json
Normal file
@@ -0,0 +1,154 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"title": "Share Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
},
|
||||
"shared": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/shareable"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["shared"],
|
||||
"additionalProperties": false,
|
||||
|
||||
"$defs": {
|
||||
"shareable": {
|
||||
"oneOf": [
|
||||
{ "$ref": "#/$defs/space" },
|
||||
{ "$ref": "#/$defs/folder" },
|
||||
{ "$ref": "#/$defs/splitView" },
|
||||
{ "$ref": "#/$defs/gradientPreset" }
|
||||
]
|
||||
},
|
||||
|
||||
"gradientPreset": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "const": "gradientPreset" },
|
||||
"theme": { "$ref": "#/$defs/theme" }
|
||||
},
|
||||
"required": ["type", "theme"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"space": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "const": "space" },
|
||||
"name": { "type": "string" },
|
||||
"theme": { "$ref": "#/$defs/theme" },
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/spaceItem" }
|
||||
}
|
||||
},
|
||||
"required": ["type", "name", "items"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"theme": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["gradient"]
|
||||
},
|
||||
"gradientColors": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/gradientColor" }
|
||||
}
|
||||
},
|
||||
"required": ["type", "gradientColors"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"gradientColor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"c": {
|
||||
"type": "array",
|
||||
"items": { "type": "number" },
|
||||
"minItems": 3,
|
||||
"maxItems": 3
|
||||
},
|
||||
"isCustom": { "type": "boolean" },
|
||||
"algorithm": { "type": "string" },
|
||||
"isPrimary": { "type": "boolean" },
|
||||
"lightness": { "type": "string" },
|
||||
"position": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x": { "type": "number" },
|
||||
"y": { "type": "number" }
|
||||
},
|
||||
"required": ["x", "y"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"type": { "type": "string" }
|
||||
},
|
||||
"required": ["c", "type"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"folder": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "const": "folder" },
|
||||
"name": { "type": "string" },
|
||||
"icon": { "type": "string" },
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/folderItem" }
|
||||
}
|
||||
},
|
||||
"required": ["type", "name", "items"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"tab": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "const": "tab" },
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"label": { "type": "string" },
|
||||
"image": { "type": "string" },
|
||||
"isPinned": { "type": "boolean" }
|
||||
},
|
||||
"required": ["type", "url"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"splitView": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "const": "splitView" },
|
||||
"tabs": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"maxItems": 4,
|
||||
"items": { "$ref": "#/$defs/tab" }
|
||||
}
|
||||
},
|
||||
"required": ["type", "tabs"],
|
||||
"additionalProperties": false
|
||||
},
|
||||
|
||||
"spaceItem": {
|
||||
"oneOf": [{ "$ref": "#/$defs/tab" }, { "$ref": "#/$defs/folder" }]
|
||||
},
|
||||
|
||||
"folderItem": {
|
||||
"oneOf": [{ "$ref": "#/$defs/tab" }, { "$ref": "#/$defs/folder" }]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1063,6 +1063,7 @@
|
||||
|
||||
@media -moz-pref('zen.tabs.show-newtab-vertical') {
|
||||
#tabs-newtab-button {
|
||||
max-height: var(--tab-min-height);
|
||||
display: flex !important;
|
||||
transition: scale 0.1s ease;
|
||||
#tabbrowser-tabs[movingtab] & {
|
||||
|
||||
@@ -13,6 +13,7 @@ BROWSER_CHROME_MANIFESTS += [
|
||||
"ub-actions/browser.toml",
|
||||
"urlbar/browser.toml",
|
||||
"welcome/browser.toml",
|
||||
"window_sync/browser.toml",
|
||||
"workspaces/browser.toml",
|
||||
]
|
||||
|
||||
|
||||
12
src/zen/tests/window_sync/browser.toml
Normal file
12
src/zen/tests/window_sync/browser.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
[DEFAULT]
|
||||
prefs = ["zen.window-sync.enabled=true", "zen.urlbar.replace-newtab=false"]
|
||||
support-files = [
|
||||
"head.js",
|
||||
]
|
||||
|
||||
["browser_sync_tab_open.js"]
|
||||
["browser_sync_tab_label.js"]
|
||||
39
src/zen/tests/window_sync/browser_sync_tab_label.js
Normal file
39
src/zen/tests/window_sync/browser_sync_tab_label.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_SimpleLabelChange() {
|
||||
let newLabel = 'Test Label';
|
||||
await withNewTabAndWindow(async (newTab, win) => {
|
||||
let otherTab = gZenWindowSync.getItemFromWindow(win, newTab.id);
|
||||
await runSyncAction(
|
||||
() => {
|
||||
gBrowser._setTabLabel(newTab, newLabel);
|
||||
Assert.equal(newTab.label, newLabel, 'The original tab label should be changed');
|
||||
},
|
||||
async () => {
|
||||
Assert.equal(
|
||||
otherTab.label,
|
||||
newLabel,
|
||||
'The synced tab label should match the changed label'
|
||||
);
|
||||
},
|
||||
'ZenTabLabelChanged'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
add_task(async function test_DontChangeBluredTabLabel() {
|
||||
let newLabel = 'Test Label';
|
||||
await withNewTabAndWindow(async (newTab, win) => {
|
||||
let otherTab = gZenWindowSync.getItemFromWindow(win, newTab.id);
|
||||
Assert.ok(!otherTab._zenContentsVisible, 'The synced tab should be blured');
|
||||
gBrowser._setTabLabel(newTab, newLabel);
|
||||
Assert.notEqual(
|
||||
otherTab.label,
|
||||
newLabel,
|
||||
'The synced tab label should NOT match the changed label'
|
||||
);
|
||||
});
|
||||
});
|
||||
14
src/zen/tests/window_sync/browser_sync_tab_open.js
Normal file
14
src/zen/tests/window_sync/browser_sync_tab_open.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
https://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
'use strict';
|
||||
|
||||
add_task(async function test_SimpleTabOpen() {
|
||||
await withNewTabAndWindow(async (newTab, win) => {
|
||||
let tabId = newTab.id;
|
||||
let otherTab = gZenWindowSync.getItemFromWindow(win, tabId);
|
||||
Assert.ok(otherTab, 'The opened tab should be found in the synced window');
|
||||
Assert.ok(newTab._zenContentsVisible, 'The opened tab should be visible');
|
||||
Assert.equal(otherTab.id, tabId, 'The opened tab ID should match the synced tab ID');
|
||||
});
|
||||
});
|
||||
47
src/zen/tests/window_sync/head.js
Normal file
47
src/zen/tests/window_sync/head.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
async function withNewSyncedWindow(action) {
|
||||
await gZenWorkspaces.promiseInitialized;
|
||||
const win = await BrowserTestUtils.openNewBrowserWindow();
|
||||
await win.gZenWorkspaces.promiseInitialized;
|
||||
await action(win);
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
}
|
||||
|
||||
async function runSyncAction(action, callback, type) {
|
||||
await new Promise((resolve) => {
|
||||
window.gZenWindowSync.addSyncHandler(async function handler(aEvent) {
|
||||
if (aEvent.type === type) {
|
||||
window.gZenWindowSync.removeSyncHandler(handler);
|
||||
await callback(aEvent);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
action();
|
||||
});
|
||||
}
|
||||
|
||||
function getTabState(tab) {
|
||||
return JSON.parse(SessionStore.getTabState(tab));
|
||||
}
|
||||
|
||||
async function withNewTabAndWindow(action) {
|
||||
let newTab = null;
|
||||
await withNewSyncedWindow(async (win) => {
|
||||
await runSyncAction(
|
||||
() => {
|
||||
newTab = gBrowser.addTrustedTab('https://example.com/', { inBackground: true });
|
||||
},
|
||||
async (aEvent) => {
|
||||
Assert.equal(aEvent.type, 'TabOpen', 'Event type should be TabOpen');
|
||||
await action(newTab, win);
|
||||
},
|
||||
'TabOpen'
|
||||
);
|
||||
});
|
||||
let portalTabClosing = BrowserTestUtils.waitForTabClosing(newTab);
|
||||
BrowserTestUtils.removeTab(newTab);
|
||||
await portalTabClosing;
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export class ZenUrlbarProviderGlobalActions extends UrlbarProvider {
|
||||
if (window.gZenWorkspaces.privateWindowOrDisabled) {
|
||||
return [];
|
||||
}
|
||||
const workspaces = window.gZenWorkspaces._workspaceCache?.workspaces;
|
||||
const workspaces = window.gZenWorkspaces.getWorkspaces();
|
||||
if (!workspaces?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
|
||||
let hue = (angle / 360) * 360; // Normalize angle to [0, 360)
|
||||
let saturation = normalizedDistance * 100; // stays high even in center
|
||||
if (type !== EXPLICIT_LIGHTNESS_TYPE) {
|
||||
saturation = 80 + (1 - normalizedDistance) * 20;
|
||||
saturation = 90 + (1 - normalizedDistance) * 10;
|
||||
// Set the current lightness to how far we are from the center of the circle
|
||||
// For example, moving the dot outside will have higher lightness, while moving it inside will have lower lightness
|
||||
this.#currentLightness = Math.round((1 - normalizedDistance) * 100);
|
||||
@@ -1216,9 +1216,9 @@ export class nsZenThemePicker extends nsZenMultiWindowFeature {
|
||||
let color2 = this.getSingleRGBColor(themedColors[0], forToolbar);
|
||||
let color3 = this.getSingleRGBColor(themedColors[1], forToolbar);
|
||||
return [
|
||||
`radial-gradient(circle at 0% 0%, ${color2} -10%, transparent 100%)`,
|
||||
`linear-gradient(to top, ${color1} -50%, transparent 125%)`,
|
||||
`radial-gradient(circle at 100% -100%, ${color3} -100%, transparent 400%)`,
|
||||
`linear-gradient(-5deg, ${color1} 10%, transparent 80%)`,
|
||||
`radial-gradient(circle at 95% 0%, ${color3} 0%, transparent 75%)`,
|
||||
`radial-gradient(circle at 0% 0%, ${color2} 10%, transparent 70%)`,
|
||||
].join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,9 +158,9 @@ export class nsZenWorkspace extends MozXULElement {
|
||||
});
|
||||
|
||||
this.indicator.addEventListener('click', (event) => {
|
||||
if (this.hasPinnedTabs) {
|
||||
if (this.hasPinnedTabs && event.button === 0) {
|
||||
event.stopPropagation();
|
||||
this.collapsiblePins.collapsed = !this.collapsiblePins.collapsed;
|
||||
this.collapsiblePins.toggle();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -207,8 +207,8 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
|
||||
await this.#cleanup();
|
||||
|
||||
await gZenWorkspaces._organizeWorkspaceStripLocations(workspace, true);
|
||||
await gZenWorkspaces.updateTabsContainers();
|
||||
gZenWorkspaces._organizeWorkspaceStripLocations(workspace, true);
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
}
|
||||
@@ -321,8 +321,8 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
|
||||
const workspace = gZenWorkspaces.getActiveWorkspace();
|
||||
await gZenWorkspaces._organizeWorkspaceStripLocations(workspace);
|
||||
await gZenWorkspaces.updateTabsContainers();
|
||||
gZenWorkspaces._organizeWorkspaceStripLocations(workspace);
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
|
||||
await gZenUIManager.motion.animate(
|
||||
[gBrowser.tabContainer, gURLBar.textbox],
|
||||
|
||||
@@ -119,8 +119,10 @@ class nsZenWorkspaces {
|
||||
window.addEventListener('resize', this.onWindowResize.bind(this));
|
||||
this.addPopupListeners();
|
||||
|
||||
await this.#waitForPromises();
|
||||
await this.afterLoadInit();
|
||||
if (this.privateWindowOrDisabled) {
|
||||
await this.#waitForPromises();
|
||||
await this.restoreWorkspacesFromSessionStore({});
|
||||
}
|
||||
}
|
||||
|
||||
log(...args) {
|
||||
@@ -129,11 +131,15 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
|
||||
async afterLoadInit() {
|
||||
if (!this._hasInitializedTabsStrip) {
|
||||
await this.delayedStartup();
|
||||
}
|
||||
this._initializeWorkspaceTabContextMenus();
|
||||
async #afterLoadInit() {
|
||||
const onResize = (...args) => {
|
||||
requestAnimationFrame(() => {
|
||||
this.onPinnedTabsResize(...args);
|
||||
});
|
||||
};
|
||||
this._pinnedTabsResizeObserver = new ResizeObserver(onResize);
|
||||
this.registerPinnedResizeObserver();
|
||||
this.#initializeWorkspaceTabContextMenus();
|
||||
|
||||
// Non UI related initializations
|
||||
if (
|
||||
@@ -274,21 +280,6 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
|
||||
async delayedStartup() {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
const onResize = (...args) => {
|
||||
requestAnimationFrame(() => {
|
||||
this.onPinnedTabsResize(...args);
|
||||
});
|
||||
};
|
||||
this._pinnedTabsResizeObserver = new ResizeObserver(onResize);
|
||||
if (this.privateWindowOrDisabled) {
|
||||
await this.restoreWorkspacesFromSessionStore({});
|
||||
}
|
||||
}
|
||||
|
||||
#initializeEmptyTab() {
|
||||
for (const tab of gBrowser.tabs) {
|
||||
// Check if session store has an empty tab
|
||||
@@ -310,9 +301,6 @@ class nsZenWorkspaces {
|
||||
return;
|
||||
}
|
||||
this._pinnedTabsResizeObserver.disconnect();
|
||||
for (let element of document.querySelectorAll('.zen-workspace-pinned-tabs-section')) {
|
||||
this._pinnedTabsResizeObserver.observe(element, { box: 'border-box' });
|
||||
}
|
||||
for (let element of document.getElementById('zen-essentials').children) {
|
||||
if (element.classList.contains('tabbrowser-tab')) {
|
||||
continue;
|
||||
@@ -402,7 +390,6 @@ class nsZenWorkspaces {
|
||||
}
|
||||
perifery.setAttribute('hidden', 'true');
|
||||
this._hasInitializedTabsStrip = true;
|
||||
this.registerPinnedResizeObserver();
|
||||
this._fixIndicatorsNames(workspaces);
|
||||
}
|
||||
|
||||
@@ -438,7 +425,9 @@ class nsZenWorkspaces {
|
||||
|
||||
getCurrentSpaceContainerId() {
|
||||
const currentWorkspace = this.getActiveWorkspaceFromCache();
|
||||
return currentWorkspace?.containerTabId || 0;
|
||||
return typeof currentWorkspace?.containerTabId === 'number'
|
||||
? currentWorkspace.containerTabId
|
||||
: 0;
|
||||
}
|
||||
|
||||
getCurrentEssentialsContainer() {
|
||||
@@ -812,10 +801,6 @@ class nsZenWorkspaces {
|
||||
);
|
||||
return ZenSessionStore.getClonedSpaces();
|
||||
}
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
this._workspaceCache = this._tempWorkspace ? [this._tempWorkspace] : [];
|
||||
this.#activeWorkspace = this._tempWorkspace?.uuid;
|
||||
}
|
||||
return [...this._workspaceCache];
|
||||
}
|
||||
|
||||
@@ -863,7 +848,7 @@ class nsZenWorkspaces {
|
||||
const spacesFromStore = aWinData.spaces || [];
|
||||
this._workspaceCache = spacesFromStore.length
|
||||
? [...spacesFromStore]
|
||||
: [this.#createWorkspaceData('Space', undefined, true)];
|
||||
: [this.#createWorkspaceData('Space', undefined)];
|
||||
this.activeWorkspace = aWinData.activeZenSpace || this._workspaceCache[0].uuid;
|
||||
let promise = this.#initializeWorkspaces();
|
||||
for (const workspace of spacesFromStore) {
|
||||
@@ -901,6 +886,8 @@ class nsZenWorkspaces {
|
||||
this.#initializeTabsStripSections();
|
||||
this.#initializeEmptyTab();
|
||||
return (async () => {
|
||||
await this.#waitForPromises();
|
||||
await this.#afterLoadInit();
|
||||
await this.workspaceBookmarks();
|
||||
await this.changeWorkspace(activeWorkspace, { onInit: true });
|
||||
this.#fixTabPositions();
|
||||
@@ -925,7 +912,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
|
||||
async selectStartPage() {
|
||||
if (!this.workspaceEnabled) {
|
||||
if (!this.workspaceEnabled || gZenUIManager.testingEnabled) {
|
||||
return;
|
||||
}
|
||||
await this.promiseInitialized;
|
||||
@@ -1336,7 +1323,7 @@ class nsZenWorkspaces {
|
||||
|
||||
propagateWorkspaces(aWorkspaces) {
|
||||
const previousWorkspaces = this._workspaceCache || [];
|
||||
this._workspaceCache = aWorkspaces;
|
||||
let promises = [];
|
||||
let hasChanged = false;
|
||||
// Remove any workspace elements here that no longer exist
|
||||
for (const previousWorkspace of previousWorkspaces) {
|
||||
@@ -1344,14 +1331,18 @@ class nsZenWorkspaces {
|
||||
this.workspaceElement(previousWorkspace.uuid) &&
|
||||
!aWorkspaces.find((w) => w.uuid === previousWorkspace.uuid)
|
||||
) {
|
||||
let promise = Promise.resolve();
|
||||
if (this.isWorkspaceActive(previousWorkspace)) {
|
||||
// If the removed workspace was active, switch to another one
|
||||
const newActiveWorkspace =
|
||||
aWorkspaces.find((w) => w.uuid !== previousWorkspace.uuid) || null;
|
||||
this.changeWorkspace(newActiveWorkspace);
|
||||
promise = this.changeWorkspace(newActiveWorkspace);
|
||||
}
|
||||
this.workspaceElement(previousWorkspace.uuid)?.remove();
|
||||
delete this.lastSelectedWorkspaceTabs[previousWorkspace.uuid];
|
||||
promise = promise.then(() => {
|
||||
this.workspaceElement(previousWorkspace.uuid)?.remove();
|
||||
delete this.lastSelectedWorkspaceTabs[previousWorkspace.uuid];
|
||||
});
|
||||
promises.push(promise);
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
@@ -1378,13 +1369,15 @@ class nsZenWorkspaces {
|
||||
previousElement = workspaceElement;
|
||||
}
|
||||
}
|
||||
if (hasChanged) {
|
||||
this.#fireSpaceUIUpdate();
|
||||
}
|
||||
this._organizeWorkspaceStripLocations(this.getActiveWorkspaceFromCache()).finally(() => {
|
||||
return Promise.all(promises).then(() => {
|
||||
this._workspaceCache = aWorkspaces;
|
||||
if (hasChanged) {
|
||||
this.#fireSpaceUIUpdate();
|
||||
}
|
||||
this._organizeWorkspaceStripLocations(this.getActiveWorkspaceFromCache());
|
||||
this.updateTabsContainers();
|
||||
this.updateWorkspacesChangeContextMenu();
|
||||
});
|
||||
this.updateWorkspacesChangeContextMenu();
|
||||
}
|
||||
|
||||
async reorderWorkspace(id, newPosition) {
|
||||
@@ -1616,13 +1609,15 @@ class nsZenWorkspaces {
|
||||
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
if (!whileScrolling) {
|
||||
await this._organizeWorkspaceStripLocations(previousWorkspace);
|
||||
this._organizeWorkspaceStripLocations(previousWorkspace);
|
||||
}
|
||||
|
||||
// Second pass: Handle tab selection
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
const tabToSelect = await this._handleTabSelection(workspace, onInit, previousWorkspace.uuid);
|
||||
gBrowser.warmupTab(tabToSelect);
|
||||
if (tabToSelect.linkedBrowser) {
|
||||
gBrowser.warmupTab(tabToSelect);
|
||||
}
|
||||
|
||||
// Update UI and state
|
||||
const previousWorkspaceIndex = workspaces.findIndex((w) => w.uuid === previousWorkspace.uuid);
|
||||
@@ -1675,7 +1670,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
|
||||
_updatePaddingTopOnTabs(
|
||||
#updatePaddingTopOnTabs(
|
||||
workspaceElement,
|
||||
essentialContainer,
|
||||
forAnimation = false,
|
||||
@@ -1707,7 +1702,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
|
||||
async _organizeWorkspaceStripLocations(workspace, justMove = false, offsetPixels = 0) {
|
||||
_organizeWorkspaceStripLocations(workspace, justMove = false, offsetPixels = 0) {
|
||||
if (document.documentElement.hasAttribute('zen-creating-workspace')) {
|
||||
// If we are creating a workspace, we don't want to animate the strip
|
||||
return;
|
||||
@@ -1769,24 +1764,19 @@ class nsZenWorkspaces {
|
||||
} = gZenThemePicker.getGradientForWorkspace(nextWorkspace);
|
||||
const existingGrain = gZenThemePicker.getGradientForWorkspace(workspace).grain;
|
||||
const percentage = Math.abs(offsetPixels) / 200;
|
||||
await new Promise((resolve) => {
|
||||
requestAnimationFrame(() => {
|
||||
document.documentElement.style.setProperty('--zen-background-opacity', 1 - percentage);
|
||||
if (!this._hasAnimatedBackgrounds) {
|
||||
this._hasAnimatedBackgrounds = true;
|
||||
document.documentElement.style.setProperty(
|
||||
'--zen-main-browser-background-old',
|
||||
nextGradient
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
'--zen-main-browser-background-toolbar-old',
|
||||
nextToolbarGradient
|
||||
);
|
||||
document.documentElement.setAttribute('animating-background', 'true');
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
document.documentElement.style.setProperty('--zen-background-opacity', 1 - percentage);
|
||||
if (!this._hasAnimatedBackgrounds) {
|
||||
this._hasAnimatedBackgrounds = true;
|
||||
document.documentElement.style.setProperty(
|
||||
'--zen-main-browser-background-old',
|
||||
nextGradient
|
||||
);
|
||||
document.documentElement.style.setProperty(
|
||||
'--zen-main-browser-background-toolbar-old',
|
||||
nextToolbarGradient
|
||||
);
|
||||
document.documentElement.setAttribute('animating-background', 'true');
|
||||
}
|
||||
// Fit the offsetPixels into the grain limits. Both ends may be nextGrain and existingGrain,
|
||||
// so we need to use the min and max of both. For example, existing may be 0.2 and next may be 0.5,
|
||||
// meaning we should convert the offset to a percentage between 0.2 and 0.5. BUT if existingGrain
|
||||
@@ -1894,28 +1884,23 @@ class nsZenWorkspaces {
|
||||
previousBackgroundOpacity = 1 - previousBackgroundOpacity;
|
||||
}
|
||||
gZenThemePicker.previousBackgroundOpacity = previousBackgroundOpacity;
|
||||
await new Promise((resolve) => {
|
||||
requestAnimationFrame(() => {
|
||||
document.documentElement.style.setProperty(
|
||||
'--zen-background-opacity',
|
||||
previousBackgroundOpacity
|
||||
);
|
||||
animations.push(
|
||||
gZenUIManager.motion.animate(
|
||||
document.documentElement,
|
||||
{
|
||||
'--zen-background-opacity': [previousBackgroundOpacity, 1],
|
||||
},
|
||||
{
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
duration: kGlobalAnimationDuration,
|
||||
}
|
||||
)
|
||||
);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
document.documentElement.style.setProperty(
|
||||
'--zen-background-opacity',
|
||||
previousBackgroundOpacity
|
||||
);
|
||||
animations.push(
|
||||
gZenUIManager.motion.animate(
|
||||
document.documentElement,
|
||||
{
|
||||
'--zen-background-opacity': [previousBackgroundOpacity, 1],
|
||||
},
|
||||
{
|
||||
type: 'spring',
|
||||
bounce: 0,
|
||||
duration: kGlobalAnimationDuration,
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
for (const element of document.querySelectorAll('zen-workspace')) {
|
||||
if (element.classList.contains('zen-essentials-container')) {
|
||||
@@ -2129,7 +2114,7 @@ class nsZenWorkspaces {
|
||||
cloned.container.remove();
|
||||
}
|
||||
this._alwaysAnimatePaddingTop = true;
|
||||
await this.updateTabsContainers();
|
||||
this.updateTabsContainers();
|
||||
}
|
||||
const essentialsContainer = this.getEssentialsSection(newWorkspace.containerTabId);
|
||||
essentialsContainer.removeAttribute('hidden');
|
||||
@@ -2266,7 +2251,9 @@ class nsZenWorkspaces {
|
||||
gBrowser.tabContainer.arrowScrollbox = this.activeScrollbox;
|
||||
|
||||
// Update workspace UI
|
||||
gZenThemePicker.onWorkspaceChange(workspace);
|
||||
requestAnimationFrame(() => {
|
||||
gZenThemePicker.onWorkspaceChange(workspace);
|
||||
});
|
||||
|
||||
gZenUIManager.tabsWrapper.scrollbarWidth = 'none';
|
||||
this.workspaceIcons.activeIndex = workspace.uuid;
|
||||
@@ -2275,7 +2262,7 @@ class nsZenWorkspaces {
|
||||
previousWorkspace,
|
||||
onInit,
|
||||
});
|
||||
await this._organizeWorkspaceStripLocations(workspace, true);
|
||||
this._organizeWorkspaceStripLocations(workspace, true);
|
||||
gZenUIManager.tabsWrapper.style.scrollbarWidth = '';
|
||||
|
||||
// Notify listeners
|
||||
@@ -2385,6 +2372,11 @@ class nsZenWorkspaces {
|
||||
}
|
||||
|
||||
#createWorkspaceData(name, icon, containerTabId = 0) {
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
containerTabId = parseInt(gBrowser.selectedTab.getAttribute('usercontextid')) || 0;
|
||||
let label = ContextualIdentityService.getUserContextLabel(containerTabId) || 'Default';
|
||||
name = this.isPrivateWindow ? 'Private ' + name : label;
|
||||
}
|
||||
let workspace = {
|
||||
uuid: gZenUIManager.generateUuidv4(),
|
||||
icon: icon,
|
||||
@@ -2405,11 +2397,6 @@ class nsZenWorkspaces {
|
||||
if (!this.workspaceEnabled) {
|
||||
return;
|
||||
}
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
containerTabId = parseInt(gBrowser.selectedTab.getAttribute('usercontextid')) || 0;
|
||||
let label = ContextualIdentityService.getUserContextLabel(containerTabId) || 'Default';
|
||||
name = this.isPrivateWindow ? 'Private ' + name : label;
|
||||
}
|
||||
// get extra tabs remaning (e.g. on new profiles) and just move them to the new workspace
|
||||
const extraTabs = Array.from(gBrowser.tabContainer.arrowScrollbox.children).filter(
|
||||
(child) =>
|
||||
@@ -2422,13 +2409,9 @@ class nsZenWorkspaces {
|
||||
if (!dontChange) {
|
||||
this.#prepareNewWorkspace(workspaceData);
|
||||
this.#createWorkspaceTabsSection(workspaceData, extraTabs);
|
||||
await this._organizeWorkspaceStripLocations(workspaceData);
|
||||
}
|
||||
if (!this.currentWindowIsSyncing) {
|
||||
this._tempWorkspace = workspaceData;
|
||||
} else {
|
||||
this.saveWorkspace(workspaceData);
|
||||
this._organizeWorkspaceStripLocations(workspaceData);
|
||||
}
|
||||
this.saveWorkspace(workspaceData);
|
||||
if (!dontChange) {
|
||||
if (beforeChangeCallback) {
|
||||
try {
|
||||
@@ -2438,7 +2421,7 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
this.registerPinnedResizeObserver();
|
||||
await this.updateTabsContainers({
|
||||
this.updateTabsContainers({
|
||||
target: this.workspaceElement(workspaceData.uuid).pinnedTabsContainer,
|
||||
});
|
||||
let changed = extraTabs.length > 0;
|
||||
@@ -2532,8 +2515,7 @@ class nsZenWorkspaces {
|
||||
const workspacesIds = [];
|
||||
if (entry.target.closest('#zen-essentials')) {
|
||||
// Get all workspaces that have the same userContextId
|
||||
const activeWorkspace = this.getActiveWorkspace();
|
||||
const userContextId = activeWorkspace.containerTabId;
|
||||
const userContextId = parseInt(entry.target.getAttribute('container') || '0');
|
||||
const workspaces = this.getWorkspaces().filter((w) => w.containerTabId === userContextId);
|
||||
workspacesIds.push(...workspaces.map((w) => w.uuid));
|
||||
} else {
|
||||
@@ -2563,7 +2545,7 @@ class nsZenWorkspaces {
|
||||
} else {
|
||||
essentialContainer.removeAttribute('data-hack-type');
|
||||
}
|
||||
this._updatePaddingTopOnTabs(
|
||||
this.#updatePaddingTopOnTabs(
|
||||
workspaceElement,
|
||||
essentialContainer,
|
||||
forAnimation,
|
||||
@@ -2727,7 +2709,7 @@ class nsZenWorkspaces {
|
||||
await this.changeWorkspace(nextWorkspace, { whileScrolling });
|
||||
}
|
||||
|
||||
_initializeWorkspaceTabContextMenus() {
|
||||
#initializeWorkspaceTabContextMenus() {
|
||||
if (this.privateWindowOrDisabled) {
|
||||
const commandsToDisable = [
|
||||
'cmd_zenOpenFolderCreation',
|
||||
|
||||
@@ -41,9 +41,12 @@ zen-workspace-creation {
|
||||
}
|
||||
|
||||
& xul|button {
|
||||
border: none;
|
||||
margin: 0;
|
||||
font-weight: 400 !important;
|
||||
|
||||
&:not(.footer-button.primary) {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
& .zen-workspace-creation-name-wrapper {
|
||||
|
||||
@@ -188,6 +188,10 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:root[zen-unsynced-window='true'][zen-sidebar-expanded='true'] & {
|
||||
padding: calc(-2px + var(--tab-inline-padding) + var(--zen-toolbox-padding));
|
||||
}
|
||||
|
||||
:root:not([zen-unsynced-window]) & {
|
||||
&:hover,
|
||||
&[open='true'] {
|
||||
@@ -243,7 +247,6 @@
|
||||
padding: 4px 8px;
|
||||
border-radius: 99px;
|
||||
font-size: 10px;
|
||||
margin-inline-start: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ fn is_twilight_build() -> bool {
|
||||
if let Ok(content) = fs::read_to_string(&dynamic_config_path) {
|
||||
return !content.contains("\"release\"");
|
||||
}
|
||||
false
|
||||
true
|
||||
}
|
||||
|
||||
fn get_env_values() -> HashMap<String, bool> {
|
||||
|
||||
Reference in New Issue
Block a user