mirror of
https://github.com/zen-browser/desktop.git
synced 2026-09-02 03:33:34 +00:00
gh-15089: Prevent folder expansion on sync (gh-15197)
This commit is contained in:
@@ -64,6 +64,10 @@ zen-tabs-select-recently-used-on-close =
|
||||
zen-tabs-close-on-back-with-no-history =
|
||||
.label = Close tab and switch to its owner tab (or most recently used tab) when going back with no history
|
||||
|
||||
zen-settings-workspaces-sync =
|
||||
.label = Sync your sidebar across devices
|
||||
.description = Keep your workspaces, pinned tabs and folders in sync on all your devices through your Mozilla account.
|
||||
|
||||
zen-settings-workspaces-sync-unpinned-tabs =
|
||||
.label = Sync only pinned tabs in workspaces
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
diff --git a/browser/components/contextualidentity/content/ContainerCreationPanel.mjs b/browser/components/contextualidentity/content/ContainerCreationPanel.mjs
|
||||
index e04d7a4738192703e8f7f8555f50aaf0a619a5bd..b86e4853c421856f84ad8e017062f0d611b88aad 100644
|
||||
--- a/browser/components/contextualidentity/content/ContainerCreationPanel.mjs
|
||||
+++ b/browser/components/contextualidentity/content/ContainerCreationPanel.mjs
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { ContainerEditor } from "chrome://browser/content/usercontext/ContainerEditor.mjs";
|
||||
|
||||
-const ANCHOR_ID = "userContext-icons";
|
||||
+const ANCHOR_ID = "navigator-toolbox";
|
||||
const ANCHOR_PINNED_CLASS = "container-anchor-pinned";
|
||||
|
||||
const lazy = {};
|
||||
@@ -95,6 +95,6 @@ export const ContainerCreationPanel = {
|
||||
anchor.hidden = false;
|
||||
}
|
||||
|
||||
- panel.openPopup(anchor, "bottomright topright");
|
||||
+ panel.openPopup(anchor, win.gZenUIManager.panelUIPosition());
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/customizableui/CustomizableUI.sys.mjs b/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd8869254d59 100644
|
||||
index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..3d6e092e7ed126cdee8c32229df2cfa13303d3a3 100644
|
||||
--- a/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
+++ b/browser/components/customizableui/CustomizableUI.sys.mjs
|
||||
@@ -13,6 +13,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
@@ -163,16 +163,27 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
webExtList.insertBefore(child, webExtList.firstElementChild);
|
||||
} else {
|
||||
child.setAttribute("cui-anchorid", this.#defaultListButton.id);
|
||||
@@ -8006,7 +8009,7 @@ class OverflowableToolbar {
|
||||
@@ -7995,6 +7998,7 @@ class OverflowableToolbar {
|
||||
return aElement.getBoundingClientRect().width;
|
||||
}
|
||||
|
||||
+ let toolbar = this.#toolbar;
|
||||
function sumChildrenInlineSize(aParent, aExceptChild = null) {
|
||||
let sum = 0;
|
||||
for (let child of aParent.children) {
|
||||
@@ -8006,7 +8010,10 @@ class OverflowableToolbar {
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
- sum += parseFloat(style.marginLeft) + parseFloat(style.marginRight);
|
||||
+ sum += parseFloat(style.marginLeft) + (win.gZenVerticalTabsManager._hasSetSingleToolbar ? Math.max(0, parseFloat(style.marginRight)) : parseFloat(style.marginRight));
|
||||
+ if (toolbar.id == 'zen-sidebar-top-buttons' && toolbar.hasAttribute("overflowing")) {
|
||||
+ sum += 2; // Add extra padding that we remove from the CSS
|
||||
+ }
|
||||
if (child != aExceptChild) {
|
||||
sum += getInlineSize(child);
|
||||
}
|
||||
@@ -8030,11 +8033,11 @@ class OverflowableToolbar {
|
||||
@@ -8030,11 +8037,11 @@ class OverflowableToolbar {
|
||||
parseFloat(style.paddingLeft) -
|
||||
parseFloat(style.paddingRight) -
|
||||
toolbarChildrenWidth;
|
||||
@@ -186,7 +197,7 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
});
|
||||
|
||||
lazy.log.debug(
|
||||
@@ -8049,7 +8052,39 @@ class OverflowableToolbar {
|
||||
@@ -8049,7 +8056,39 @@ class OverflowableToolbar {
|
||||
Math.max(targetWidth, targetChildrenWidth)
|
||||
);
|
||||
totalAvailWidth = Math.ceil(totalAvailWidth);
|
||||
@@ -227,7 +238,7 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
return { isOverflowing, targetContentWidth, totalAvailWidth };
|
||||
}
|
||||
|
||||
@@ -8110,7 +8145,11 @@ class OverflowableToolbar {
|
||||
@@ -8110,7 +8149,11 @@ class OverflowableToolbar {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -240,7 +251,7 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
lazy.log.debug(
|
||||
`Need ${minSize} but width is ${totalAvailWidth} so bailing`
|
||||
);
|
||||
@@ -8143,7 +8182,7 @@ class OverflowableToolbar {
|
||||
@@ -8143,7 +8186,7 @@ class OverflowableToolbar {
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
@@ -249,7 +260,7 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
}
|
||||
child.removeAttribute("cui-anchorid");
|
||||
child.removeAttribute("overflowedItem");
|
||||
@@ -8269,6 +8308,9 @@ class OverflowableToolbar {
|
||||
@@ -8269,6 +8312,9 @@ class OverflowableToolbar {
|
||||
* if no such list exists.
|
||||
*/
|
||||
get #webExtList() {
|
||||
@@ -259,7 +270,7 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
if (!this.#webExtListRef) {
|
||||
let targetID = this.#toolbar.getAttribute("addon-webext-overflowtarget");
|
||||
if (!targetID) {
|
||||
@@ -8280,6 +8322,9 @@ class OverflowableToolbar {
|
||||
@@ -8280,6 +8326,9 @@ class OverflowableToolbar {
|
||||
let win = this.#toolbar.documentGlobal;
|
||||
let { panel } = win.gUnifiedExtensions;
|
||||
this.#webExtListRef = panel.querySelector(`#${targetID}`);
|
||||
@@ -269,7 +280,7 @@ index 6d1885a54815d10b3a4e79f7e5acd61ab3abb159..97e07d85c69ec97baeab05aedd57bd88
|
||||
}
|
||||
return this.#webExtListRef;
|
||||
}
|
||||
@@ -8488,7 +8533,7 @@ class OverflowableToolbar {
|
||||
@@ -8488,7 +8537,7 @@ class OverflowableToolbar {
|
||||
break;
|
||||
}
|
||||
case "mousedown": {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/browser/components/preferences/config/account-sync.mjs b/browser/components/preferences/config/account-sync.mjs
|
||||
index b503987a08e2ce64bfc01c4e3a21e5e19ef834f0..b1c03a0b219fd3eddd93c1deaeb18ab79c85f168 100644
|
||||
index b01fd4bb163ad53139fcbd8e79e12ef994d1fa13..dd60be4fe268618d6596cd5cfac3342975bd241a 100644
|
||||
--- a/browser/components/preferences/config/account-sync.mjs
|
||||
+++ b/browser/components/preferences/config/account-sync.mjs
|
||||
@@ -42,6 +42,7 @@ Preferences.addAll([
|
||||
@@ -46,6 +46,7 @@ Preferences.addAll([
|
||||
{ id: "services.sync.engine.creditcards", type: "bool" },
|
||||
{ id: "services.sync.engine.addons", type: "bool" },
|
||||
{ id: "services.sync.engine.prefs", type: "bool" },
|
||||
@@ -10,7 +10,7 @@ index b503987a08e2ce64bfc01c4e3a21e5e19ef834f0..b1c03a0b219fd3eddd93c1deaeb18ab7
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -546,6 +547,7 @@ const SYNC_ENGINE_SETTINGS = [
|
||||
@@ -557,6 +558,7 @@ const SYNC_ENGINE_SETTINGS = [
|
||||
type: "payments",
|
||||
},
|
||||
{ id: "syncAddons", pref: "services.sync.engine.addons", type: "addons" },
|
||||
@@ -18,3 +18,37 @@ index b503987a08e2ce64bfc01c4e3a21e5e19ef834f0..b1c03a0b219fd3eddd93c1deaeb18ab7
|
||||
{ id: "syncSettings", pref: "services.sync.engine.prefs", type: "settings" },
|
||||
];
|
||||
|
||||
@@ -564,6 +566,12 @@ SYNC_ENGINE_SETTINGS.forEach(({ id, pref }) => {
|
||||
Preferences.addSetting({ id, pref });
|
||||
});
|
||||
|
||||
+Preferences.addSetting({ id: "zenSyncWorkspacesGroup" });
|
||||
+Preferences.addSetting({
|
||||
+ id: "zenSyncWorkspaces",
|
||||
+ pref: "services.sync.engine.spaces",
|
||||
+});
|
||||
+
|
||||
Preferences.addSetting({
|
||||
id: "syncEngines",
|
||||
deps: SYNC_ENGINE_SETTINGS.map(({ id }) => id),
|
||||
@@ -995,6 +1003,20 @@ SettingGroupManager.registerGroups({
|
||||
id: "syncEnginesList",
|
||||
control: "sync-engines-list",
|
||||
},
|
||||
+ {
|
||||
+ id: "zenSyncWorkspacesGroup",
|
||||
+ control: "moz-box-item",
|
||||
+ items: [
|
||||
+ {
|
||||
+ id: "zenSyncWorkspaces",
|
||||
+ l10nId: "zen-settings-workspaces-sync",
|
||||
+ control: "moz-toggle",
|
||||
+ controlAttrs: {
|
||||
+ inputlayout: "inline-end",
|
||||
+ },
|
||||
+ },
|
||||
+ ],
|
||||
+ },
|
||||
{
|
||||
id: "syncChangeOptions",
|
||||
control: "moz-box-button",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js
|
||||
index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e356c9f8c6f 100644
|
||||
index 237950fb2c449ce088c204d33a70b1d95dae549b..635f9dbc5c79b6bb869b4ab4ec2d4b4e226b4672 100644
|
||||
--- a/browser/components/tabbrowser/content/tabgroup.js
|
||||
+++ b/browser/components/tabbrowser/content/tabgroup.js
|
||||
@@ -14,11 +14,11 @@
|
||||
@@ -101,7 +101,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
|
||||
resetDefaultGroupName = () => {
|
||||
this.#defaultGroupName = "";
|
||||
@@ -175,10 +198,15 @@
|
||||
@@ -175,10 +198,18 @@
|
||||
if (!this.#tabChangeObserver) {
|
||||
this.#tabChangeObserver = new window.MutationObserver(mutations => {
|
||||
if (!this.tabs.length) {
|
||||
@@ -112,12 +112,15 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
new CustomEvent("TabGroupRemoved", { bubbles: true })
|
||||
);
|
||||
+ gZenVerticalTabsManager.animateItemClose(this).then(() => {
|
||||
+ this.dispatchEvent(
|
||||
+ new CustomEvent("TabGroupRemovedFromDOM", { bubbles: true })
|
||||
+ );
|
||||
this.remove();
|
||||
+ });
|
||||
Services.obs.notifyObservers(
|
||||
this,
|
||||
"browser-tabgroup-removed-from-dom"
|
||||
@@ -223,7 +251,10 @@
|
||||
@@ -223,7 +254,10 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -129,7 +132,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
}
|
||||
|
||||
get color() {
|
||||
@@ -330,6 +361,9 @@
|
||||
@@ -330,6 +364,9 @@
|
||||
}
|
||||
|
||||
set collapsed(val) {
|
||||
@@ -139,7 +142,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
if (!!val == this.collapsed) {
|
||||
return;
|
||||
}
|
||||
@@ -416,7 +450,6 @@
|
||||
@@ -416,7 +453,6 @@
|
||||
tabGroupName,
|
||||
})
|
||||
.then(result => {
|
||||
@@ -147,7 +150,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
});
|
||||
}
|
||||
|
||||
@@ -491,13 +524,68 @@
|
||||
@@ -491,13 +527,68 @@
|
||||
* @returns {MozTabbrowserTab[]}
|
||||
*/
|
||||
get tabs() {
|
||||
@@ -162,9 +165,8 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
+ tabsCollect.push(item);
|
||||
+ if (gBrowser.isTabGroup(item)) {
|
||||
+ tabsCollect.push(...item.tabs);
|
||||
}
|
||||
}
|
||||
- return childrenArray.filter(node => node.matches("tab"));
|
||||
+ }
|
||||
+ }
|
||||
+ return tabsCollect.filter(node => node.matches("tab"));
|
||||
+ }
|
||||
+
|
||||
@@ -208,8 +210,9 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
+ currentGroup = currentGroup?.group;
|
||||
+ if (currentGroup.collapsed) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
- return childrenArray.filter(node => node.matches("tab"));
|
||||
+ if (this.pinned && gZenWorkspaces.activeWorkspaceElement?.hasCollapsedPinnedTabs) {
|
||||
+ return false;
|
||||
+ }
|
||||
@@ -221,7 +224,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -617,9 +705,6 @@
|
||||
@@ -617,9 +708,6 @@
|
||||
});
|
||||
} else {
|
||||
if (tabOrSplitView.pinned) {
|
||||
@@ -231,7 +234,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
}
|
||||
let tabToMove =
|
||||
this.documentGlobal === tabOrSplitView.documentGlobal
|
||||
@@ -682,7 +767,7 @@
|
||||
@@ -682,7 +770,7 @@
|
||||
*/
|
||||
on_click(event) {
|
||||
let isToggleElement =
|
||||
@@ -240,7 +243,7 @@ index 237950fb2c449ce088c204d33a70b1d95dae549b..af200a043dcd2e24393fcefe32493e35
|
||||
event.target === this.#overflowCountLabel;
|
||||
if (isToggleElement && event.button === 0) {
|
||||
event.preventDefault();
|
||||
@@ -761,5 +846,6 @@
|
||||
@@ -761,5 +849,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
border-radius: var(--tab-border-radius);
|
||||
|
||||
&:hover {
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
background: var(--toolbarbutton-background-color-hover);
|
||||
}
|
||||
|
||||
& image {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/toolkit/themes/shared/design-system/dist/tokens-shared.css b/toolkit/themes/shared/design-system/dist/tokens-shared.css
|
||||
index 15c0d98a18b4f19e7f2e03d2b78066b0353f416a..b32f6244c7a07e93894bab422691a605456034a1 100644
|
||||
index 63c641f560d4c0ce06b40a652ca99d1c48cd6941..39c81e773a442870763396e68fb57bd336e3625a 100644
|
||||
--- a/toolkit/themes/shared/design-system/dist/tokens-shared.css
|
||||
+++ b/toolkit/themes/shared/design-system/dist/tokens-shared.css
|
||||
@@ -7,6 +7,8 @@
|
||||
@@ -11,7 +11,22 @@ index 15c0d98a18b4f19e7f2e03d2b78066b0353f416a..b32f6244c7a07e93894bab422691a605
|
||||
@layer tokens-foundation {
|
||||
:root,
|
||||
:host(.anonymous-content-host) {
|
||||
@@ -424,8 +426,8 @@
|
||||
@@ -28,10 +30,10 @@
|
||||
--border-color-selected: var(--color-accent-primary);
|
||||
--border-color-transparent: transparent;
|
||||
--border-radius-circle: 9999px;
|
||||
- --border-radius-xsmall: 2px;
|
||||
- --border-radius-small: 4px;
|
||||
- --border-radius-medium: 8px;
|
||||
- --border-radius-large: 16px;
|
||||
+ --border-radius-xsmall: calc(2px * var(--zen-squircle-value));
|
||||
+ --border-radius-small: calc(4px * var(--zen-squircle-value));
|
||||
+ --border-radius-medium: calc(8px * var(--zen-squircle-value));
|
||||
+ --border-radius-large: calc(16px * var(--zen-squircle-value));
|
||||
--border-width: 1px;
|
||||
|
||||
/** box-shadow **/
|
||||
@@ -477,8 +479,8 @@
|
||||
--panel-background-color-dimmed-further: var(--background-color-dimmed-further);
|
||||
--panel-border-color: light-dark(rgb(240, 240, 244), rgb(82, 82, 94));
|
||||
--panel-border-radius: var(--border-radius-medium);
|
||||
|
||||
@@ -868,7 +868,6 @@ window.gZenUIManager = {
|
||||
},
|
||||
|
||||
panelUIPosition(panel, anchor) {
|
||||
void panel;
|
||||
// The alignment position of the panel is determined during the "popuppositioned" event
|
||||
// when the panel opens. The alignment positions help us determine in which orientation
|
||||
// the panel is anchored to the screen space.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
.urlbar {
|
||||
--urlbarview-separator-color: light-dark(hsl(0, 0%, 80%), hsl(0, 0%, 20%));
|
||||
--urlbarview-background-color-hover: var(--toolbarbutton-hover-background);
|
||||
--urlbarview-background-color-hover: var(--toolbarbutton-background-color-hover);
|
||||
border-radius: calc(var(--toolbarbutton-border-radius) - 2px);
|
||||
--urlbarView-results-padding: 10px !important;
|
||||
--urlbar-container-height: 48px !important;
|
||||
@@ -351,7 +351,7 @@
|
||||
padding: 4px !important;
|
||||
|
||||
&:hover {
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
background: var(--toolbarbutton-background-color-hover);
|
||||
border-radius: var(--toolbarbutton-border-radius);
|
||||
overflow: visible;
|
||||
}
|
||||
@@ -495,7 +495,7 @@
|
||||
/* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */
|
||||
#urlbar-container:has(&) {
|
||||
border-radius: var(--border-radius-medium);
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
background: var(--toolbarbutton-background-color-hover);
|
||||
height: var(--urlbar-height) !important;
|
||||
margin-inline: 0.15rem !important;
|
||||
:root:not([zen-single-toolbar="true"]) & {
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
--zen-toolbar-height-with-bookmarks: calc(var(--zen-toolbar-height) + 30px);
|
||||
}
|
||||
|
||||
--toolbarbutton-hover-background: var(--zen-toolbar-element-bg-hover) !important;
|
||||
--toolbarbutton-background-color-hover: var(--zen-toolbar-element-bg-hover) !important;
|
||||
--zen-toolbar-button-size: 16px;
|
||||
@media (-moz-platform: macos) {
|
||||
--zen-toolbar-button-size: 17px;
|
||||
@@ -181,7 +181,7 @@
|
||||
* background on the native theme. */
|
||||
--toolbar-background-color: light-dark(rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0.15));
|
||||
|
||||
--toolbarbutton-active-background: color-mix(
|
||||
--toolbarbutton-background-color-active: color-mix(
|
||||
in srgb,
|
||||
var(--zen-branding-bg-reverse) 7%,
|
||||
transparent 93%
|
||||
@@ -191,9 +191,9 @@
|
||||
--toolbox-textcolor-inactive: var(--toolbox-textcolor) !important;
|
||||
|
||||
/* Other colors */
|
||||
--urlbar-box-active-bgcolor: var(--toolbarbutton-hover-background) !important;
|
||||
--urlbar-box-active-bgcolor: var(--toolbarbutton-background-color-hover) !important;
|
||||
--zen-input-border-color: light-dark(rgb(204, 204, 204), rgb(66, 65, 77));
|
||||
--urlbar-box-hover-bgcolor: var(--toolbarbutton-hover-background) !important;
|
||||
--urlbar-box-hover-bgcolor: var(--toolbarbutton-background-color-hover) !important;
|
||||
--input-text-background-color: light-dark(rgba(255, 255, 255, 0.2), rgba(0, 0, 0, 0.2)) !important;
|
||||
--toolbar-field-focus-background-color: light-dark(
|
||||
rgba(255, 255, 255, 0.25),
|
||||
@@ -267,7 +267,7 @@
|
||||
--zen-active-tab-scale: 0.985;
|
||||
|
||||
/* Define tab hover background color */
|
||||
--tab-background-color-hover: var(--toolbarbutton-hover-background);
|
||||
--tab-background-color-hover: var(--toolbarbutton-background-color-hover);
|
||||
|
||||
/* Sidebar Notifications */
|
||||
--zen-sidebar-notification-bg: color-mix(
|
||||
|
||||
@@ -41,7 +41,7 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
</vbox>
|
||||
<vbox class="zen-workspace-creation-form">
|
||||
<hbox class="zen-workspace-creation-name-wrapper">
|
||||
<toolbarbutton class="zen-workspace-creation-icon-label" />
|
||||
<toolbarbutton class="zen-workspace-creation-icon-label zen-squircle-before" />
|
||||
<html:input
|
||||
class="zen-workspace-creation-name"
|
||||
type="text"
|
||||
@@ -78,6 +78,18 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
return this.getAttribute("previous-workspace-id");
|
||||
}
|
||||
|
||||
get elementsToAnimate() {
|
||||
return [
|
||||
this.querySelector(".zen-workspace-creation-title"),
|
||||
this.querySelector(".zen-workspace-creation-label").parentElement,
|
||||
this.querySelector(".zen-workspace-creation-name-wrapper"),
|
||||
this.querySelector(".zen-workspace-creation-profile-wrapper"),
|
||||
this.querySelector(".zen-workspace-creation-edit-theme-button"),
|
||||
this.createButton.parentNode,
|
||||
this.cancelButton,
|
||||
];
|
||||
}
|
||||
|
||||
get #spaceSwitchDuration() {
|
||||
return (
|
||||
Services.prefs.getIntPref("zen.workspaces.switch-animation-duration") /
|
||||
@@ -161,6 +173,10 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
.getInterface(Ci.nsIAppWindow)
|
||||
.rollupAllPopups();
|
||||
|
||||
gURLBar.view.close();
|
||||
gURLBar.handleRevert();
|
||||
gURLBar.blur();
|
||||
|
||||
this.handleZenWorkspacesChangeBind =
|
||||
this.handleZenWorkspacesChange.bind(this);
|
||||
|
||||
@@ -262,7 +278,7 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
workspace.containerTabId = this.currentProfile;
|
||||
await gZenWorkspaces.saveWorkspace(workspace);
|
||||
|
||||
this.#cleanup();
|
||||
await this.#cleanup();
|
||||
|
||||
gZenWorkspaces._organizeWorkspaceStripLocations(workspace, true);
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
@@ -344,11 +360,30 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
}
|
||||
|
||||
async handleZenWorkspacesChange() {
|
||||
this.#cleanup();
|
||||
// The space we were living in has already slid away, no need to animate
|
||||
// ourselves out of it.
|
||||
await this.#cleanup({ animateOut: false });
|
||||
await gZenWorkspaces.removeWorkspace(this.workspaceId);
|
||||
}
|
||||
|
||||
#cleanup() {
|
||||
async #cleanup({ animateOut = true } = {}) {
|
||||
if (animateOut && !gReduceMotion && this.isConnected) {
|
||||
await gZenUIManager.motion.animate(
|
||||
this.elementsToAnimate.reverse(),
|
||||
{
|
||||
y: [0, 20],
|
||||
opacity: [1, 0],
|
||||
filter: ["blur(0)", "blur(2px)"],
|
||||
},
|
||||
{
|
||||
duration: 0.3,
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
delay: gZenUIManager.motion.stagger(0.03),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
document.getElementById("zen-sidebar-splitter").style.pointerEvents = "";
|
||||
|
||||
gZenWorkspaces.removeChangeListeners(this.handleZenWorkspacesChangeBind);
|
||||
@@ -376,12 +411,38 @@ class nsZenWorkspaceCreation extends MozXULElement {
|
||||
element.hidden = false;
|
||||
}
|
||||
|
||||
// Now that the form is gone the space owns its essentials again.
|
||||
// Now that the form is gone the space owns its essentials again, so let
|
||||
// it lay itself out before we fade everything back in.
|
||||
const workspace = gZenWorkspaces.getActiveWorkspace();
|
||||
gZenWorkspaces._organizeWorkspaceStripLocations(workspace);
|
||||
gZenWorkspaces.updateTabsContainers();
|
||||
// The essentials slid away when we arrived, slide them back in.
|
||||
gZenWorkspaces.restoreEssentialsPosition();
|
||||
// The essentials were parked off screen while we were up, put them back.
|
||||
gZenWorkspaces.resetEssentialsPosition();
|
||||
|
||||
if (animateOut && !gReduceMotion) {
|
||||
const elementsToReveal = revealedElements.filter(
|
||||
element => element?.isConnected
|
||||
);
|
||||
if (elementsToReveal.length) {
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
elementsToReveal,
|
||||
{
|
||||
opacity: [0, 1],
|
||||
},
|
||||
{
|
||||
duration: 0.3,
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
for (const element of elementsToReveal) {
|
||||
element.style.removeProperty("opacity");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
gZenUIManager.updateTabsToolbar();
|
||||
}
|
||||
|
||||
@@ -1939,36 +1939,13 @@ class nsZenWorkspaces {
|
||||
}
|
||||
|
||||
/**
|
||||
* Slide the essentials back from wherever a creation form parked them.
|
||||
* Drop the offset a creation form parked the essentials at.
|
||||
*/
|
||||
restoreEssentialsPosition() {
|
||||
const duration =
|
||||
Services.prefs.getIntPref("zen.workspaces.switch-animation-duration") /
|
||||
1000;
|
||||
resetEssentialsPosition() {
|
||||
for (const container of document.querySelectorAll(
|
||||
"#zen-essentials .zen-essentials-container"
|
||||
)) {
|
||||
const existingTransform = container.style.transform;
|
||||
const parkedOffset = parseFloat(existingTransform.split("(")[1]) || 0;
|
||||
if (!parkedOffset || gReduceMotion) {
|
||||
container.style.removeProperty("transform");
|
||||
continue;
|
||||
}
|
||||
gZenUIManager.motion
|
||||
.animate(
|
||||
container,
|
||||
{
|
||||
transform: [existingTransform, "translateX(0%)"],
|
||||
},
|
||||
{
|
||||
type: "spring",
|
||||
bounce: 0,
|
||||
duration,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
container.style.removeProperty("transform");
|
||||
});
|
||||
container.style.removeProperty("transform");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ zen-workspace-creation {
|
||||
|
||||
&::before {
|
||||
border: 1px dashed light-dark(rgba(0, 0, 0, 0.5), rgba(255, 255, 255, 0.5));
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
width: calc(100% + 2px);
|
||||
height: calc(100% + 2px);
|
||||
content: "";
|
||||
|
||||
@@ -143,16 +143,23 @@ class nsZenSpacesSyncApplier {
|
||||
} else {
|
||||
await win.gZenWorkspaces.promiseInitialized;
|
||||
this.#maybePlayFirstSyncAnimation(win);
|
||||
const removals = this.#routeTombstones(win, deletions);
|
||||
this.#deleteTabs(win, removals.tabs, fail);
|
||||
this.#deleteSplits(win, removals.splits, fail);
|
||||
await this.#applySpaces(win, incoming.spaces, fail);
|
||||
await this.#applyFolders(win, incoming.folders, fail);
|
||||
this.#applyTabs(win, incoming.tabs, fail);
|
||||
this.#applySplits(win, incoming.splits, fail);
|
||||
await this.#deleteFolders(win, removals.folders, fail);
|
||||
await this.#deleteSpaces(win, removals.spaces, fail);
|
||||
this.#applyOrdering(win, incoming, fail);
|
||||
// A sync apply is a materialization just like session restore,
|
||||
// so it must stay visually silent (gh-15089).
|
||||
win.gZenFolders._sessionRestoring = true;
|
||||
try {
|
||||
const removals = this.#routeTombstones(win, deletions);
|
||||
this.#deleteTabs(win, removals.tabs, fail);
|
||||
this.#deleteSplits(win, removals.splits, fail);
|
||||
await this.#applySpaces(win, incoming.spaces, fail);
|
||||
await this.#applyFolders(win, incoming.folders, fail);
|
||||
this.#applyTabs(win, incoming.tabs, fail);
|
||||
this.#applySplits(win, incoming.splits, fail);
|
||||
await this.#deleteFolders(win, removals.folders, fail);
|
||||
await this.#deleteSpaces(win, removals.spaces, fail);
|
||||
this.#applyOrdering(win, incoming, fail);
|
||||
} finally {
|
||||
delete win.gZenFolders._sessionRestoring;
|
||||
}
|
||||
// Collect the session soon so the stored sidebar (and with it the
|
||||
// sync projections) reflects the applied state instead of re-uploading
|
||||
// the pre-apply one.
|
||||
@@ -401,9 +408,12 @@ class nsZenSpacesSyncApplier {
|
||||
// Parents before children so nesting targets exist.
|
||||
const depths = new Map(folders.map(f => [f.key, f.data.parentFolderId]));
|
||||
const depthOf = key => {
|
||||
// The seen set only guards against a corrupt parentId cycle.
|
||||
const seen = new Set([key]);
|
||||
let depth = 0;
|
||||
let parent = depths.get(key);
|
||||
while (parent && depths.has(parent) && depth < 10) {
|
||||
while (parent && depths.has(parent) && !seen.has(parent)) {
|
||||
seen.add(parent);
|
||||
depth++;
|
||||
parent = depths.get(parent);
|
||||
}
|
||||
@@ -423,6 +433,7 @@ class nsZenSpacesSyncApplier {
|
||||
workspaceId:
|
||||
data.workspaceUuid || win.gZenWorkspaces.activeWorkspace,
|
||||
isLiveFolder: !!data.live,
|
||||
collapsed: true,
|
||||
});
|
||||
} else if (data.name && folder.label !== data.name) {
|
||||
folder.label = data.name;
|
||||
|
||||
@@ -300,66 +300,95 @@ class nsZenSpacesSyncModel {
|
||||
|
||||
/**
|
||||
* Builds the ordered child id list for one parent (a space's pinned
|
||||
* section or a folder). Tabs and splits are ordered by their position in
|
||||
* the collected tab list; folders are spliced in next to their recorded
|
||||
* previous sibling.
|
||||
* section or a folder) from the collected tab list, which is in strip
|
||||
* order.
|
||||
*
|
||||
* @param {object} root0
|
||||
* @param {Array<object>} root0.tabs
|
||||
* @param {Array<object>} root0.folders
|
||||
* @param {Set<string>} root0.splitIds
|
||||
* @param {Map<string, ?string>} root0.splitParents
|
||||
* @param {Map<string, ?string>} root0.splitWs
|
||||
* @param {object} root0.scope
|
||||
* @param {object} ctx - The projection context.
|
||||
* @param {{space?: string, folder?: string}} scope
|
||||
*/
|
||||
#childSequence({ tabs, folders, splitIds, splitParents, splitWs, scope }) {
|
||||
#childSequence(ctx, scope) {
|
||||
const seq = [];
|
||||
const seenSplits = new Set();
|
||||
for (const tab of tabs) {
|
||||
const seen = new Set();
|
||||
const push = id => {
|
||||
if (!seen.has(id)) {
|
||||
seen.add(id);
|
||||
seq.push(id);
|
||||
}
|
||||
};
|
||||
for (const tab of ctx.allTabs) {
|
||||
const groupId = tab.groupId || null;
|
||||
if (groupId && splitIds.has(groupId)) {
|
||||
if (!groupId) {
|
||||
if (
|
||||
!seenSplits.has(groupId) &&
|
||||
scope.matchSplit(
|
||||
splitParents.get(groupId) ?? null,
|
||||
splitWs.get(groupId) ?? null
|
||||
)
|
||||
scope.space &&
|
||||
!tab.zenEssential &&
|
||||
(tab.zenWorkspace || null) === scope.space &&
|
||||
ctx.syncableTabIds.has(tab.zenSyncId)
|
||||
) {
|
||||
seenSplits.add(groupId);
|
||||
seq.push(groupId);
|
||||
push(tab.zenSyncId);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (scope.matchTab(tab, groupId)) {
|
||||
seq.push(tab.zenSyncId);
|
||||
}
|
||||
}
|
||||
for (const folder of folders) {
|
||||
if (!scope.matchFolder(folder)) {
|
||||
if (scope.folder && groupId === scope.folder) {
|
||||
if (ctx.syncableTabIds.has(tab.zenSyncId)) {
|
||||
push(tab.zenSyncId);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let index = seq.length;
|
||||
const prev = folder.prevSiblingInfo;
|
||||
if (!prev || prev.type === "start") {
|
||||
// No stored sibling means the folder is the first child of its
|
||||
// container (the section rebuild on startup places content before
|
||||
// the fake start element, so the first item has no sibling at all).
|
||||
index = 0;
|
||||
} else if (prev.id) {
|
||||
const at = seq.indexOf(prev.id);
|
||||
if (at !== -1) {
|
||||
index = at + 1;
|
||||
} else if (prev.type === "tab") {
|
||||
// An unsynced tab sibling (empty placeholders, live folder items)
|
||||
// always sits at the start of its container.
|
||||
index = 0;
|
||||
if (ctx.splitIds.has(groupId) || ctx.splitParents.has(groupId)) {
|
||||
const parent = ctx.splitParents.get(groupId) ?? null;
|
||||
const isDirect = scope.folder ? parent === scope.folder : !parent;
|
||||
if (isDirect) {
|
||||
if (
|
||||
ctx.splitIds.has(groupId) &&
|
||||
(!scope.space || (ctx.splitWs.get(groupId) ?? null) === scope.space)
|
||||
) {
|
||||
push(groupId);
|
||||
}
|
||||
} else if (parent) {
|
||||
const child = this.#scopeChildFolder(ctx, scope, parent);
|
||||
if (child) {
|
||||
push(child);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ctx.folderById.has(groupId)) {
|
||||
const child = this.#scopeChildFolder(ctx, scope, groupId);
|
||||
if (child) {
|
||||
push(child);
|
||||
}
|
||||
}
|
||||
seq.splice(index, 0, folder.id);
|
||||
}
|
||||
return seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks a folder's parent chain up to the direct child of the given
|
||||
* scope, or null when the chain leads somewhere else.
|
||||
*
|
||||
* @param {object} ctx - The projection context.
|
||||
* @param {{space?: string, folder?: string}} scope
|
||||
* @param {string} folderId
|
||||
* @returns {?string}
|
||||
*/
|
||||
#scopeChildFolder(ctx, scope, folderId) {
|
||||
// The seen set only guards against a corrupt parentId cycle.
|
||||
const seen = new Set();
|
||||
let current = ctx.folderById.get(folderId);
|
||||
while (current && !seen.has(current.id)) {
|
||||
seen.add(current.id);
|
||||
const parentId = current.parentId || null;
|
||||
if (scope.folder ? parentId === scope.folder : !parentId) {
|
||||
if (scope.space && (current.workspaceId || null) !== scope.space) {
|
||||
return null;
|
||||
}
|
||||
return current.id;
|
||||
}
|
||||
current = parentId ? ctx.folderById.get(parentId) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the shared projection context from one sidebar collection.
|
||||
* Syncable tabs, folders, the syncable splits and their parents and
|
||||
@@ -368,11 +397,13 @@ class nsZenSpacesSyncModel {
|
||||
* @param {object} sidebar
|
||||
*/
|
||||
#projectionContext(sidebar) {
|
||||
const tabs = (sidebar.tabs || []).filter(t => this.#isSyncableTab(t));
|
||||
const allTabs = sidebar.tabs || [];
|
||||
const tabs = allTabs.filter(t => this.#isSyncableTab(t));
|
||||
const folders = (sidebar.folders || []).filter(
|
||||
f => f?.id && !f.splitViewGroup
|
||||
);
|
||||
const folderIds = new Set(folders.map(f => f.id));
|
||||
const folderById = new Map(folders.map(f => [f.id, f]));
|
||||
const allSplits = (sidebar.splitViewData || []).filter(g => g?.groupId);
|
||||
const splitParents = new Map();
|
||||
for (const entry of sidebar.folders || []) {
|
||||
@@ -406,7 +437,18 @@ class nsZenSpacesSyncModel {
|
||||
}
|
||||
return folderIds.has(groupId) ? groupId : null;
|
||||
};
|
||||
return { tabs, folders, splits, splitIds, splitParents, splitWs, folderOf };
|
||||
return {
|
||||
allTabs,
|
||||
tabs,
|
||||
folders,
|
||||
folderById,
|
||||
syncableTabIds,
|
||||
splits,
|
||||
splitIds,
|
||||
splitParents,
|
||||
splitWs,
|
||||
folderOf,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,7 +494,7 @@ class nsZenSpacesSyncModel {
|
||||
const map = new Map();
|
||||
const pending = new Set();
|
||||
const ctx = this.#projectionContext(sidebar);
|
||||
const { tabs, folders, splits, splitIds, splitParents, splitWs } = ctx;
|
||||
const { tabs, folders, splits, splitParents, splitWs } = ctx;
|
||||
|
||||
for (const identity of lazy.ContextualIdentityService.getPublicIdentities()) {
|
||||
if (!identity.name) {
|
||||
@@ -491,21 +533,7 @@ class nsZenSpacesSyncModel {
|
||||
containerGuid: this.guidForContextId(space.containerTabId, {
|
||||
create: true,
|
||||
}),
|
||||
children: this.#childSequence({
|
||||
tabs,
|
||||
folders,
|
||||
splitIds,
|
||||
splitParents,
|
||||
splitWs,
|
||||
scope: {
|
||||
matchTab: (t, groupId) =>
|
||||
!groupId &&
|
||||
!t.zenEssential &&
|
||||
(t.zenWorkspace || null) === uuid,
|
||||
matchSplit: (parent, ws) => !parent && ws === uuid,
|
||||
matchFolder: f => !f.parentId && (f.workspaceId || null) === uuid,
|
||||
},
|
||||
}),
|
||||
children: this.#childSequence(ctx, { space: uuid }),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -533,18 +561,7 @@ class nsZenSpacesSyncModel {
|
||||
workspaceUuid: folder.workspaceId || null,
|
||||
parentFolderId: folder.parentId || null,
|
||||
live,
|
||||
children: this.#childSequence({
|
||||
tabs,
|
||||
folders,
|
||||
splitIds,
|
||||
splitParents,
|
||||
splitWs,
|
||||
scope: {
|
||||
matchTab: (t, groupId) => groupId === fid,
|
||||
matchSplit: parent => parent === fid,
|
||||
matchFolder: f => f.parentId === fid,
|
||||
},
|
||||
}),
|
||||
children: this.#childSequence(ctx, { folder: fid }),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
/* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */
|
||||
& #urlbar-container[breakout="true"]:has(#urlbar[zen-floating-urlbar="true"]) {
|
||||
--urlbar-container-height: 36px !important;
|
||||
--urlbar-height: 38px !important;
|
||||
--urlbar-height: 36px !important;
|
||||
}
|
||||
|
||||
& #nav-bar {
|
||||
@@ -114,6 +114,11 @@
|
||||
|
||||
& #zen-sidebar-top-buttons {
|
||||
margin: calc(var(--zen-toolbox-padding) / 2) 0;
|
||||
|
||||
&[overflowing] .toolbarbutton-1 {
|
||||
--toolbarbutton-padding-outer: 0px;
|
||||
}
|
||||
|
||||
:root[zen-right-side="true"]:not([zen-window-buttons-reversed="true"]) & {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -598,7 +603,7 @@
|
||||
}
|
||||
|
||||
&:is([open], [checked]) {
|
||||
background: var(--toolbarbutton-active-background) !important;
|
||||
background: var(--toolbarbutton-background-color-hover) !important;
|
||||
& image,
|
||||
label {
|
||||
background: transparent !important;
|
||||
@@ -606,7 +611,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--toolbarbutton-hover-background);
|
||||
background: var(--toolbarbutton-background-color-hover);
|
||||
& image,
|
||||
label {
|
||||
background: transparent !important;
|
||||
|
||||
Reference in New Issue
Block a user