feat: Revamped the sidebar for complete stability over future releases, b=(no-bug), c=common, tabs, workspaces

This commit is contained in:
Mr. M
2025-05-15 21:25:54 +02:00
parent 086d1633df
commit 1d8e0fc3d7
9 changed files with 221 additions and 246 deletions

View File

@@ -1,5 +1,5 @@
diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml diff --git a/browser/base/content/navigator-toolbox.inc.xhtml b/browser/base/content/navigator-toolbox.inc.xhtml
index 00c8976d3e258c0875d7da2f3ec823d8907a84c9..b5735712aaa7c2ae2baa4b858e735413b130ca94 100644 index 00c8976d3e258c0875d7da2f3ec823d8907a84c9..191598ed701514ca7207cd64c3da46960a5d0e82 100644
--- a/browser/base/content/navigator-toolbox.inc.xhtml --- a/browser/base/content/navigator-toolbox.inc.xhtml
+++ b/browser/base/content/navigator-toolbox.inc.xhtml +++ b/browser/base/content/navigator-toolbox.inc.xhtml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
@@ -22,27 +22,24 @@ index 00c8976d3e258c0875d7da2f3ec823d8907a84c9..b5735712aaa7c2ae2baa4b858e735413
<toolbar id="TabsToolbar" <toolbar id="TabsToolbar"
class="browser-toolbar browser-titlebar" class="browser-toolbar browser-titlebar"
fullscreentoolbar="true" fullscreentoolbar="true"
@@ -50,6 +50,10 @@ @@ -50,6 +50,8 @@
tooltip="tabbrowser-tab-tooltip" tooltip="tabbrowser-tab-tooltip"
orient="horizontal" orient="horizontal"
stopwatchid="tabClick"> stopwatchid="tabClick">
+<html:div id="zen-essentials-wrapper" skipintoolbarset="true"></html:div> +<html:div id="zen-essentials-wrapper" skipintoolbarset="true"></html:div>
+<hbox id="zen-current-workspace-indicator-container"></hbox>
+<html:div id="zen-tabs-wrapper"> +<html:div id="zen-tabs-wrapper">
+<html:div id="zen-browser-tabs-container">
<hbox class="tab-drop-indicator" hidden="true"/> <hbox class="tab-drop-indicator" hidden="true"/>
<html:span id="tab-drag-empty-feedback" role="presentation"/> <html:span id="tab-drag-empty-feedback" role="presentation"/>
# If the name (tabbrowser-arrowscrollbox) or structure of this changes # If the name (tabbrowser-arrowscrollbox) or structure of this changes
@@ -76,6 +80,8 @@ @@ -76,6 +78,7 @@
tooltip="dynamic-shortcut-tooltip" tooltip="dynamic-shortcut-tooltip"
data-l10n-id="tabs-toolbar-new-tab"/> data-l10n-id="tabs-toolbar-new-tab"/>
<html:span id="tabbrowser-tab-a11y-desc" hidden="true"/> <html:span id="tabbrowser-tab-a11y-desc" hidden="true"/>
+</html:div>
+</html:div> +</html:div>
</tabs> </tabs>
<toolbarbutton id="new-tab-button" <toolbarbutton id="new-tab-button"
@@ -101,9 +107,10 @@ @@ -101,9 +104,10 @@
#include private-browsing-indicator.inc.xhtml #include private-browsing-indicator.inc.xhtml
<toolbarbutton class="content-analysis-indicator toolbarbutton-1 content-analysis-indicator-icon"/> <toolbarbutton class="content-analysis-indicator toolbarbutton-1 content-analysis-indicator-icon"/>

View File

@@ -39,6 +39,7 @@
content/browser/zen-components/actors/ZenThemeMarketplaceParent.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceParent.sys.mjs) content/browser/zen-components/actors/ZenThemeMarketplaceParent.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceParent.sys.mjs)
content/browser/zen-components/actors/ZenThemeMarketplaceChild.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceChild.sys.mjs) content/browser/zen-components/actors/ZenThemeMarketplaceChild.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceChild.sys.mjs)
content/browser/zen-components/ZenWorkspace.mjs (../../zen/workspaces/ZenWorkspace.mjs)
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs) content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
content/browser/zen-components/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs) content/browser/zen-components/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs) content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)

View File

@@ -5,6 +5,7 @@
Services.scriptloader.loadSubScript("chrome://browser/content/zen-sets.js", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-sets.js", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenCommonUtils.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenCommonUtils.mjs", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenKeyboardShortcuts.mjs", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenWorkspace.mjs", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenWorkspaces.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenWorkspaces.mjs", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenWorkspacesSync.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenWorkspacesSync.mjs", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenActorsManager.mjs", this); Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenActorsManager.mjs", this);

View File

@@ -178,7 +178,9 @@
--zen-urlbar-background-transparent, --zen-urlbar-background-transparent,
var(--zen-urlbar-background-base) var(--zen-urlbar-background-base)
) !important; ) !important;
box-shadow: 0px 0px 90px -10px rgba(0, 0, 0, 0.6) !important; box-shadow:
0 20px 25px -5px rgb(0 0 0 / 0.1),
0 8px 10px -6px rgb(0 0 0 / 0.1);
backdrop-filter: none !important; backdrop-filter: none !important;
border-radius: 12px !important; border-radius: 12px !important;
outline: 0.5px solid light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.15)) !important; outline: 0.5px solid light-dark(rgba(0, 0, 0, 0.15), rgba(255, 255, 255, 0.15)) !important;

View File

@@ -304,9 +304,9 @@
this.log(`Created new pinned tab for pin ${pin.uuid} (isEssential: ${pin.isEssential})`); this.log(`Created new pinned tab for pin ${pin.uuid} (isEssential: ${pin.isEssential})`);
gBrowser.pinTab(newTab); gBrowser.pinTab(newTab);
if (!pin.isEssential) { if (!pin.isEssential) {
const container = document.querySelector( const container = ZenWorkspaces.workspaceElement(
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${pin.workspaceUuid}"]` pin.workspaceUuid
); )?.pinnedTabsContainer;
if (container) { if (container) {
container.insertBefore(newTab, container.lastChild); container.insertBefore(newTab, container.lastChild);
} }
@@ -809,7 +809,7 @@
moveToAnotherTabContainerIfNecessary(event, movingTabs) { moveToAnotherTabContainerIfNecessary(event, movingTabs) {
try { try {
const pinnedTabsTarget = const pinnedTabsTarget =
event.target.closest('#vertical-pinned-tabs-container') || event.target.closest('.zen-workspace-pinned-tabs-section') ||
event.target.closest('.zen-current-workspace-indicator'); event.target.closest('.zen-current-workspace-indicator');
const essentialTabsTarget = event.target.closest('.zen-essentials-container'); const essentialTabsTarget = event.target.closest('.zen-essentials-container');
const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox'); const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox');

View File

@@ -93,6 +93,10 @@
/* ========================================================================== /* ==========================================================================
Toolbox Padding & Variables Toolbox Padding & Variables
========================================================================== */ ========================================================================== */
#tabbrowser-arrowscrollbox {
height: 100%;
}
#browser { #browser {
/* Define base padding with platform-specific overrides */ /* Define base padding with platform-specific overrides */
--zen-min-toolbox-padding: 0.4rem; --zen-min-toolbox-padding: 0.4rem;
@@ -169,7 +173,7 @@
max-height 0.2s ease-in-out; max-height 0.2s ease-in-out;
/* Hide separator when specified by parent container attribute */ /* Hide separator when specified by parent container attribute */
#vertical-pinned-tabs-container .zen-workspace-tabs-section[hide-separator] & { .zen-workspace-pinned-tabs-section[hide-separator] & {
max-height: 0; max-height: 0;
margin: 0 auto; /* Collapse margins */ margin: 0 auto; /* Collapse margins */
} }
@@ -452,40 +456,11 @@
} }
} }
/* Container for browser tabs within the sidebar */
#zen-browser-tabs-container {
overflow-x: clip !important; /* Force horizontal clipping */
position: relative; /* Positioning context */
}
/* ========================================================================== /* ==========================================================================
Pinned Tabs Container Specific Styles Pinned Tabs Container Specific Styles
========================================================================== */ ========================================================================== */
#vertical-pinned-tabs-container { :root[zen-workspace-id] #vertical-pinned-tabs-container {
padding-inline-end: 0 !important; /* Remove end padding */ display: none;
display: flex !important; /* Use flex layout */
flex-direction: column; /* Stack pinned tabs vertically */
min-height: fit-content !important;
overflow-x: clip; /* Clip horizontal overflow */
overflow-y: visible; /* Allow vertical overflow (for menus etc.) */
max-height: unset !important; /* Allow it to grow */
/* Make non-selected, non-hovered pinned tab backgrounds transparent */
& .tabbrowser-tab:not(:hover) .tab-background:not([selected]):not([multiselected]) {
background: transparent;
}
/* Center content within pinned tabs */
& .tabbrowser-tab .tab-content {
display: flex;
align-items: center;
justify-content: center;
}
/* Ensure glance tabs within pinned container fit their content */
.tabbrowser-tab[zen-glance-tab='true'] {
width: fit-content !important;
}
} }
/* Styling for the label shown when hovering the reset-pin button */ /* Styling for the label shown when hovering the reset-pin button */
@@ -567,16 +542,6 @@
} }
} }
/* Style pinned tabs container when it has visible tabs */
& #vertical-pinned-tabs-container:has(tab:not([hidden])) {
position: relative;
/* Make pinned tabs take full width */
& .tabbrowser-tab {
width: 100%;
}
}
/* Style bottom buttons area when expanded */ /* Style bottom buttons area when expanded */
& #zen-sidebar-bottom-buttons { & #zen-sidebar-bottom-buttons {
display: flex; display: flex;
@@ -831,15 +796,6 @@
display: none !important; display: none !important;
} }
/* Style pinned tabs container */
& #vertical-pinned-tabs-container:has(tab:not([hidden])) {
position: relative;
/* Constrain pinned tab width */
& .tabbrowser-tab {
max-width: var(--tab-min-width);
}
}
/* Adjust customization target padding and separator */ /* Adjust customization target padding and separator */
& #TabsToolbar-customization-target { & #TabsToolbar-customization-target {
padding-bottom: var(--zen-toolbox-padding); padding-bottom: var(--zen-toolbox-padding);
@@ -1305,12 +1261,23 @@
padding: 0 var(--zen-toolbox-padding); padding: 0 var(--zen-toolbox-padding);
display: grid; display: grid;
position: absolute;
&[hidden='true'] { &[hidden='true'] {
--hidden-essentials-width: var(--zen-sidebar-width); --hidden-essentials-width: var(--zen-sidebar-width);
max-width: var( max-width: var(
--hidden-essentials-width --hidden-essentials-width
) !important; /* To still allow essentials to grid the tabs */ ) !important; /* To still allow essentials to grid the tabs */
min-width: var(--hidden-essentials-width) !important; min-width: var(--hidden-essentials-width) !important;
/* Hide section visually and disable interaction when hidden attribute is present */
visibility: hidden;
pointer-events: none;
position: fixed; /* Fix position to prevent scrolling */
}
&[cloned] {
pointer-events: none;
} }
} }
@@ -1486,9 +1453,6 @@
========================================================================== */ ========================================================================== */
.zen-workspace-tabs-section { .zen-workspace-tabs-section {
position: absolute;
transform: translateX(-100%);
&:not(.zen-essentials-container) { &:not(.zen-essentials-container) {
display: flex; display: flex;
min-width: calc(100% - var(--zen-toolbox-padding) * 2); /* Set width based on padding */ min-width: calc(100% - var(--zen-toolbox-padding) * 2); /* Set width based on padding */
@@ -1498,13 +1462,6 @@
padding: 0 var(--zen-toolbox-padding); padding: 0 var(--zen-toolbox-padding);
width: 100%; width: 100%;
} }
/* Hide section visually and disable interaction when hidden attribute is present */
&[hidden='true'] {
visibility: hidden;
pointer-events: none;
position: fixed; /* Fix position to prevent scrolling */
}
} }
/* ========================================================================== /* ==========================================================================

View File

@@ -0,0 +1,69 @@
{
class ZenWorkspace extends MozXULElement {
static get markup() {
return `
<vbox class="zen-workspace-tabs-section zen-current-workspace-indicator" flex="1">
<hbox class="zen-current-workspace-indicator-icon"></hbox>
<hbox class="zen-current-workspace-indicator-name"></hbox>
</vbox>
<arrowscrollbox orient="vertical" tabindex="-1">
<vbox class="zen-workspace-tabs-section zen-workspace-pinned-tabs-section">
<html:div class="vertical-pinned-tabs-container-separator"></html:div>
</vbox>
<vbox class="zen-workspace-tabs-section zen-workspace-normal-tabs-section">
<!-- Let it me as an ID to mantain compatibility with firefox's tabbrowser -->
<hbox id="tabbrowser-arrowscrollbox-periphery">
<toolbartabstop/>
<toolbarbutton id="tabs-newtab-button"
class="toolbarbutton-1"
command="cmd_newNavigatorTab"
tooltip="dynamic-shortcut-tooltip"
data-l10n-id="tabs-toolbar-new-tab"/>
<spacer class="closing-tabs-spacer" style="width: 0;"/>
</hbox>
</vbox>
</arrowscrollbox>
`;
}
static get inheritedAttributes() {
return {
'.zen-workspace-tabs-section': 'zen-workspace-id=id',
};
}
constructor() {
super();
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
}
this.appendChild(this.constructor.fragment);
this.tabsContainer = this.querySelector('.zen-workspace-normal-tabs-section');
this.indicator = this.querySelector('.zen-current-workspace-indicator');
this.pinnedTabsContainer = this.querySelector('.zen-workspace-pinned-tabs-section');
this.initializeAttributeInheritance();
this.scrollbox = this.querySelector('arrowscrollbox');
// Add them manually since attribute inheritance doesn't work
// for multiple layers of shadow DOM.
this.tabsContainer.setAttribute('zen-workspace-id', this.id);
this.pinnedTabsContainer.setAttribute('zen-workspace-id', this.id);
this.dispatchEvent(
new CustomEvent('ZenWorkspaceAttached', {
bubbles: true,
composed: true,
detail: { workspace: this },
})
);
}
}
customElements.define('zen-workspace', ZenWorkspace);
}

View File

@@ -68,9 +68,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (!this.shouldHaveWorkspaces) { if (!this.shouldHaveWorkspaces) {
this._resolveInitialized(); this._resolveInitialized();
document
.getElementById('zen-current-workspace-indicator-container')
.setAttribute('hidden', 'true');
console.warn('ZenWorkspaces: !!! ZenWorkspaces is disabled in hidden windows !!!'); console.warn('ZenWorkspaces: !!! ZenWorkspaces is disabled in hidden windows !!!');
return; // We are in a hidden window, don't initialize ZenWorkspaces return; // We are in a hidden window, don't initialize ZenWorkspaces
} }
@@ -318,10 +315,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
return; return;
} }
this._pinnedTabsResizeObserver.disconnect(); this._pinnedTabsResizeObserver.disconnect();
for (let element of document.getElementById('vertical-pinned-tabs-container').children) { for (let element of document.querySelectorAll('.zen-workspace-pinned-tabs-section')) {
if (element.classList.contains('tabbrowser-tab')) {
continue;
}
this._pinnedTabsResizeObserver.observe(element, { box: 'border-box' }); this._pinnedTabsResizeObserver.observe(element, { box: 'border-box' });
} }
for (let element of document.getElementById('zen-essentials-wrapper').children) { for (let element of document.getElementById('zen-essentials-wrapper').children) {
@@ -336,16 +330,18 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (!this._hasInitializedTabsStrip) { if (!this._hasInitializedTabsStrip) {
return gBrowser.tabContainer.arrowScrollbox; return gBrowser.tabContainer.arrowScrollbox;
} }
const activeWorkspace = this.activeWorkspace; return document.querySelector(`zen-workspace[active]`)?.tabsContainer;
return document.querySelector( }
`#tabbrowser-arrowscrollbox .zen-workspace-tabs-section[zen-workspace-id="${activeWorkspace}"]`
); get pinnedTabsContainer() {
if (!this.workspaceEnabled || !this._hasInitializedTabsStrip) {
return document.getElementById('vertical-pinned-tabs-container');
}
return document.querySelector(`zen-workspace[active]`)?.pinnedTabsContainer;
} }
get activeWorkspaceIndicator() { get activeWorkspaceIndicator() {
return document.querySelector( return document.querySelector(`zen-workspace[active]`)?.indicator;
`#zen-current-workspace-indicator-container .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
);
} }
get tabboxChildren() { get tabboxChildren() {
@@ -356,31 +352,30 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
return this.tabboxChildren.filter((child) => !child.hasAttribute('zen-empty-tab')); return this.tabboxChildren.filter((child) => !child.hasAttribute('zen-empty-tab'));
} }
get pinnedTabsContainer() { workspaceElement(workspaceId) {
if (!this.workspaceEnabled || !this._hasInitializedTabsStrip) { if (typeof workspaceId !== 'string') {
return document.getElementById('vertical-pinned-tabs-container'); workspaceId = workspaceId?.uuid;
} }
return document.querySelector( return document.getElementById(workspaceId);
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
);
} }
async initializeTabsStripSections() { async initializeTabsStripSections() {
const perifery = document.getElementById('tabbrowser-arrowscrollbox-periphery'); const perifery = document.getElementById('tabbrowser-arrowscrollbox-periphery');
perifery.setAttribute('hidden', 'true');
const tabs = gBrowser.tabContainer.allTabs; const tabs = gBrowser.tabContainer.allTabs;
const workspaces = await this._workspaces(); const workspaces = await this._workspaces();
for (const workspace of workspaces.workspaces) { for (const workspace of workspaces.workspaces) {
await this._createWorkspaceTabsSection(workspace, tabs, perifery); await this._createWorkspaceTabsSection(workspace, tabs);
} }
if (tabs.length) { if (tabs.length) {
const defaultSelectedContainer = document.querySelector( const defaultSelectedContainer = this.workspaceElement(this.activeWorkspace).querySelector(
`#tabbrowser-arrowscrollbox .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]` '.zen-workspace-normal-tabs-section'
);
const pinnedContainer = this.workspaceElement(this.activeWorkspace).querySelector(
'.zen-workspace-pinned-tabs-section'
); );
// New profile with no workspaces does not have a default selected container // New profile with no workspaces does not have a default selected container
if (defaultSelectedContainer) { if (defaultSelectedContainer) {
const pinnedContainer = document.querySelector(
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${this.activeWorkspace}"]`
);
for (const tab of tabs) { for (const tab of tabs) {
if (tab.hasAttribute('zen-essential')) { if (tab.hasAttribute('zen-essential')) {
this.getEssentialsSection(tab).appendChild(tab); this.getEssentialsSection(tab).appendChild(tab);
@@ -427,41 +422,31 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
return this.getEssentialsSection(currentWorkspace?.containerTabId); return this.getEssentialsSection(currentWorkspace?.containerTabId);
} }
#createWorkspaceSection(workspace) { async _createWorkspaceTabsSection(workspace, tabs) {
const section = document.createXULElement('vbox'); const workspaceWrapper = document.createXULElement('zen-workspace');
section.className = 'zen-workspace-tabs-section';
section.setAttribute('flex', '1');
section.setAttribute('zen-workspace-id', workspace.uuid);
return section;
}
async _createWorkspaceTabsSection(workspace, tabs, perifery) {
const container = gBrowser.tabContainer.arrowScrollbox; const container = gBrowser.tabContainer.arrowScrollbox;
const section = this.#createWorkspaceSection(workspace); workspaceWrapper.id = workspace.uuid;
section.classList.add('zen-workspace-normal-tabs-section'); if (this.activeWorkspace === workspace.uuid) {
container.appendChild(section); workspaceWrapper.setAttribute('active', 'true');
}
const pinnedContainer = document.getElementById('vertical-pinned-tabs-container'); await new Promise((resolve) => {
const pinnedSection = this.#createWorkspaceSection(workspace); workspaceWrapper.addEventListener(
pinnedSection.classList.add('zen-workspace-pinned-tabs-section'); 'ZenWorkspaceAttached',
this._organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs); (event) => {
section.appendChild(perifery.cloneNode(true)); this._organizeTabsToWorkspaceSections(
pinnedSection.appendChild( workspace,
window.MozXULElement.parseXULToFragment(` workspaceWrapper.tabsContainer,
<html:div class="vertical-pinned-tabs-container-separator"></html:div> workspaceWrapper.pinnedTabsContainer,
`) tabs
); );
pinnedContainer.appendChild(pinnedSection); this.initIndicatorContextMenu(workspaceWrapper.indicator);
resolve();
const workspaceIndicator = this.#createWorkspaceSection(workspace); },
workspaceIndicator.classList.add('zen-current-workspace-indicator'); { once: true }
workspaceIndicator.appendChild( );
window.MozXULElement.parseXULToFragment(this.workspaceIndicatorXUL) container.appendChild(workspaceWrapper);
); });
document
.getElementById('zen-current-workspace-indicator-container')
.appendChild(workspaceIndicator);
this.initIndicatorContextMenu(workspaceIndicator);
} }
_organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs) { _organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs) {
@@ -477,7 +462,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
tabs.splice(tabs.indexOf(tab), 1); tabs.splice(tabs.indexOf(tab), 1);
tab = tab.group ?? tab; tab = tab.group ?? tab;
if (tab.pinned) { if (tab.pinned) {
pinnedSection.insertBefore(tab, pinnedSection.nextSibling); pinnedSection.nextSibling.before(tab);
} else { } else {
if (!firstNormalTab) { if (!firstNormalTab) {
firstNormalTab = tab; firstNormalTab = tab;
@@ -639,9 +624,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
_handleSwipeStart(event) { _handleSwipeStart(event) {
if (!this.workspaceEnabled) return; if (!this.workspaceEnabled) return;
gZenUIManager.tabsWrapper.style.scrollbarWidth = 'none';
gZenUIManager.tabsWrapper.scrollTop = 0;
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
this._swipeState = { this._swipeState = {
@@ -1840,13 +1822,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
moveTabsToWorkspace(tabs, workspaceID, justChangeId = false) { moveTabsToWorkspace(tabs, workspaceID, justChangeId = false) {
for (let tab of tabs) { for (let tab of tabs) {
const parent = tab.pinned const workspaceContainer = this.workspaceElement(workspaceID);
? '#vertical-pinned-tabs-container ' const container = tab.pinned
: '#tabbrowser-arrowscrollbox '; ? workspaceContainer?.pinnedTabsContainer
const container = document.querySelector( : workspaceContainer?.tabsContainer;
parent + `.zen-workspace-tabs-section[zen-workspace-id="${workspaceID}"]`
);
if (container?.contains(tab)) { if (container?.contains(tab)) {
continue; continue;
} }
@@ -1979,6 +1958,14 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const workspaces = await this._workspaces(); const workspaces = await this._workspaces();
// Refresh tab cache // Refresh tab cache
for (const otherWorkspace of workspaces.workspaces) {
const container = this.workspaceElement(otherWorkspace.uuid);
if (otherWorkspace.uuid === workspace.uuid) {
container.setAttribute('active', 'true');
} else {
container.removeAttribute('active');
}
}
gBrowser.verticalPinnedTabsContainer = gBrowser.verticalPinnedTabsContainer =
this.pinnedTabsContainer || gBrowser.verticalPinnedTabsContainer; this.pinnedTabsContainer || gBrowser.verticalPinnedTabsContainer;
gBrowser.tabContainer.verticalPinnedTabsContainer = gBrowser.tabContainer.verticalPinnedTabsContainer =
@@ -2029,39 +2016,23 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
} }
_updateMarginTopPinnedTabs( _updatePaddingTopOnTabs(
arrowscrollbox, workspaceElement,
pinnedContainer,
essentialContainer, essentialContainer,
workspaceIndicator,
forAnimation = false, forAnimation = false,
animateContainer = false animateContainer = false
) { ) {
if ( if (
arrowscrollbox && workspaceElement &&
!(this._inChangingWorkspace && !forAnimation && !this._alwaysAnimateMarginTop) !(this._inChangingWorkspace && !forAnimation && !this._alwaysAnimatePaddingTop)
) { ) {
delete this._alwaysAnimateMarginTop; delete this._alwaysAnimatePaddingTop;
const essentialsHeight = essentialContainer.getBoundingClientRect().height; const essentialsHeight = essentialContainer.getBoundingClientRect().height;
workspaceIndicator.style.marginTop = essentialsHeight + 'px';
let arrowMarginTop = pinnedContainer.getBoundingClientRect().height;
const isActive = arrowscrollbox.getAttribute('active') === 'true';
if ((isActive || !this.containerSpecificEssentials) && !forAnimation) {
document.getElementById('zen-tabs-wrapper').style.marginTop = essentialsHeight + 'px';
pinnedContainer.style.marginTop = '';
} else {
arrowMarginTop += essentialsHeight;
pinnedContainer.style.marginTop = essentialsHeight + 'px';
if (forAnimation) {
document.getElementById('zen-tabs-wrapper').style.marginTop = '';
gZenUIManager.tabsWrapper.scrollTop = 0;
}
}
if (!forAnimation && animateContainer) { if (!forAnimation && animateContainer) {
gZenUIManager.motion.animate( gZenUIManager.motion.animate(
arrowscrollbox, workspaceElement,
{ {
marginTop: [arrowscrollbox.style.marginTop, arrowMarginTop + 'px'], paddingTop: [workspaceElement.style.paddingTop, essentialsHeight + 'px'],
}, },
{ {
type: 'spring', type: 'spring',
@@ -2070,7 +2041,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} }
); );
} else { } else {
arrowscrollbox.style.marginTop = arrowMarginTop + 'px'; workspaceElement.style.paddingTop = essentialsHeight + 'px';
} }
} }
} }
@@ -2088,26 +2059,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const workspaceContextId = workspace.containerTabId; const workspaceContextId = workspace.containerTabId;
const nextWorkspaceContextId = const nextWorkspaceContextId =
workspaces.workspaces[workspaceIndex + (offsetPixels > 0 ? -1 : 1)]?.containerTabId; workspaces.workspaces[workspaceIndex + (offsetPixels > 0 ? -1 : 1)]?.containerTabId;
if (this.containerSpecificEssentials && justMove) {
const waitForContainers = [];
for (const element of document.querySelectorAll(
'.zen-workspace-tabs-section.zen-workspace-pinned-tabs-section'
)) {
waitForContainers.push(this.updateTabsContainers(element, true));
}
await Promise.all(waitForContainers);
}
for (const otherWorkspace of workspaces.workspaces) { for (const otherWorkspace of workspaces.workspaces) {
const selector = `.zen-workspace-tabs-section[zen-workspace-id="${otherWorkspace.uuid}"]`; const element = this.workspaceElement(otherWorkspace.uuid);
const newTransform = -(workspaceIndex - workspaces.workspaces.indexOf(otherWorkspace)) * 100; const newTransform = -(workspaceIndex - workspaces.workspaces.indexOf(otherWorkspace)) * 100;
for (const container of document.querySelectorAll(selector)) { element.style.transform = `translateX(${newTransform + offsetPixels / 2}%)`;
container.style.transform = `translateX(${newTransform + offsetPixels / 2}%)`;
if (!offsetPixels && !container.hasAttribute('active')) {
container.setAttribute('hidden', 'true');
} else {
container.removeAttribute('hidden');
}
}
} }
// Hide other essentials with different containerTabId // Hide other essentials with different containerTabId
for (const container of otherContainersEssentials) { for (const container of otherContainersEssentials) {
@@ -2159,9 +2114,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
_fixIndicatorsNames(workspaces) { _fixIndicatorsNames(workspaces) {
for (const workspace of workspaces.workspaces) { for (const workspace of workspaces.workspaces) {
const workspaceIndicator = document.querySelector( const workspaceIndicator = this.workspaceElement(workspace.uuid)?.indicator;
`#zen-current-workspace-indicator-container .zen-workspace-tabs-section[zen-workspace-id="${workspace.uuid}"]`
);
this.updateWorkspaceIndicator(workspace, workspaceIndicator); this.updateWorkspaceIndicator(workspace, workspaceIndicator);
} }
} }
@@ -2202,38 +2155,23 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
essentialsContainer.parentNode.appendChild(essentialsClone); essentialsContainer.parentNode.appendChild(essentialsClone);
} }
} }
if (shouldAnimate && this.containerSpecificEssentials) { for (const element of document.querySelectorAll('zen-workspace')) {
const waitForContainers = [];
for (const element of document.querySelectorAll(
'.zen-workspace-tabs-section.zen-workspace-pinned-tabs-section'
)) {
waitForContainers.push(this.updateTabsContainers(element, true));
}
await Promise.all(waitForContainers);
}
for (const element of document.querySelectorAll('.zen-workspace-tabs-section')) {
if (element.classList.contains('zen-essentials-container')) { if (element.classList.contains('zen-essentials-container')) {
continue; continue;
} }
const existingTransform = element.style.transform; const existingTransform = element.style.transform;
const elementWorkspaceId = element.getAttribute('zen-workspace-id'); const elementWorkspaceId = element.id;
const elementWorkspaceIndex = workspaces.workspaces.findIndex( const elementWorkspaceIndex = workspaces.workspaces.findIndex(
(w) => w.uuid === elementWorkspaceId (w) => w.uuid === elementWorkspaceId
); );
const offset = -(newWorkspaceIndex - elementWorkspaceIndex) * 100; const offset = -(newWorkspaceIndex - elementWorkspaceIndex) * 100;
const newTransform = `translateX(${offset}%)`; const newTransform = `translateX(${offset}%)`;
if (shouldAnimate) { if (shouldAnimate) {
element.removeAttribute('hidden');
// For some reason, motion seems to reset the margin top randomly
// so we explicitly set it to the current value
const marginTop = element.style.marginTop;
animations.push( animations.push(
gZenUIManager.motion.animate( gZenUIManager.motion.animate(
element, element,
{ {
transform: existingTransform ? [existingTransform, newTransform] : newTransform, transform: existingTransform ? [existingTransform, newTransform] : newTransform,
marginTop: existingTransform ? [marginTop, marginTop] : marginTop,
}, },
{ {
type: 'spring', type: 'spring',
@@ -2395,7 +2333,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
for (const cloned of clonedEssentials) { for (const cloned of clonedEssentials) {
cloned.container.remove(); cloned.container.remove();
} }
this._alwaysAnimateMarginTop = true; this._alwaysAnimatePaddingTop = true;
await this.updateTabsContainers(); await this.updateTabsContainers();
} }
const essentialsContainer = this.getEssentialsSection(newWorkspace.containerTabId); const essentialsContainer = this.getEssentialsSection(newWorkspace.containerTabId);
@@ -2627,10 +2565,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
}; };
if (moveTabs) { if (moveTabs) {
this._prepareNewWorkspace(window); this._prepareNewWorkspace(window);
const perifery = document.querySelector('#tabbrowser-arrowscrollbox-periphery[hidden]'); this._createWorkspaceTabsSection(window, tabs);
perifery?.removeAttribute('hidden');
this._createWorkspaceTabsSection(window, tabs, perifery);
perifery.setAttribute('hidden', 'true');
} }
return window; return window;
} }
@@ -2723,15 +2658,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
workspacesIds.push(originalWorkspaceId); workspacesIds.push(originalWorkspaceId);
} }
for (const workspaceId of workspacesIds) { for (const workspaceId of workspacesIds) {
const arrowScrollbox = document.querySelector( const workspaceElement = this.workspaceElement(workspaceId);
`#tabbrowser-arrowscrollbox .zen-workspace-tabs-section[zen-workspace-id="${workspaceId}"]` const arrowScrollbox = workspaceElement.tabsContainer;
); const pinnedContainer = workspaceElement.pinnedTabsContainer;
const pinnedContainer = document.querySelector(
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${workspaceId}"]`
);
const workspaceIndicator = document.querySelector(
`#zen-current-workspace-indicator-container .zen-workspace-tabs-section[zen-workspace-id="${workspaceId}"]`
);
const workspaceObject = this.getWorkspaceFromId(workspaceId); const workspaceObject = this.getWorkspaceFromId(workspaceId);
const essentialContainer = this.getEssentialsSection(workspaceObject.containerTabId); const essentialContainer = this.getEssentialsSection(workspaceObject.containerTabId);
const essentialNumChildren = essentialContainer.children.length; const essentialNumChildren = essentialContainer.children.length;
@@ -2748,11 +2677,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
} else { } else {
essentialContainer.removeAttribute('data-hack-type'); essentialContainer.removeAttribute('data-hack-type');
} }
this._updateMarginTopPinnedTabs( this._updatePaddingTopOnTabs(
arrowScrollbox, workspaceElement,
pinnedContainer,
essentialContainer, essentialContainer,
workspaceIndicator,
forAnimation, forAnimation,
animateContainer animateContainer
); );
@@ -2853,9 +2780,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (!workspaceId) { if (!workspaceId) {
continue; continue;
} }
const contaienr = document.querySelector( const contaienr = this.workspaceElement(workspaceId).pinnedTabsContainer;
`#vertical-pinned-tabs-container .zen-workspace-tabs-section[zen-workspace-id="${workspaceId}"]`
);
contaienr.insertBefore(tab, contaienr.lastChild); contaienr.insertBefore(tab, contaienr.lastChild);
changed = true; changed = true;
} }
@@ -3143,15 +3068,19 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const essentialsContainer = document.querySelectorAll( const essentialsContainer = document.querySelectorAll(
'#zen-essentials-wrapper .zen-workspace-tabs-section' '#zen-essentials-wrapper .zen-workspace-tabs-section'
); );
let pinnedContainers = document.querySelectorAll( let pinnedContainers = [];
'#vertical-pinned-tabs-container .zen-workspace-tabs-section' let normalContainers = [];
);
let normalContainers = document.querySelectorAll(
'#tabbrowser-arrowscrollbox .zen-workspace-tabs-section'
);
if (!this._hasInitializedTabsStrip) { if (!this._hasInitializedTabsStrip) {
pinnedContainers = [document.getElementById('vertical-pinned-tabs-container')]; pinnedContainers = [document.getElementById('vertical-pinned-tabs-container')];
normalContainers = [this.activeWorkspaceStrip]; normalContainers = [this.activeWorkspaceStrip];
} else {
for (const workspace of this._workspaceCache.workspaces) {
const container = this.workspaceElement(workspace.uuid);
if (container) {
pinnedContainers.push(container.pinnedTabsContainer);
normalContainers.push(container.tabsContainer);
}
}
} }
const containers = [...essentialsContainer, ...pinnedContainers, ...normalContainers]; const containers = [...essentialsContainer, ...pinnedContainers, ...normalContainers];
for (const container of containers) { for (const container of containers) {
@@ -3185,12 +3114,15 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
let children = this.tabboxChildren; let children = this.tabboxChildren;
return children.filter((node) => node.tagName == 'tab-group'); return children.filter((node) => node.tagName == 'tab-group');
} }
const pinnedContainers = document.querySelectorAll( const pinnedContainers = [];
'#vertical-pinned-tabs-container .zen-workspace-tabs-section' const normalContainers = [];
); for (const workspace of this._workspaceCache.workspaces) {
const normalContainers = document.querySelectorAll( const container = this.workspaceElement(workspace.uuid);
'#tabbrowser-arrowscrollbox .zen-workspace-tabs-section' if (container) {
); pinnedContainers.push(container.pinnedTabsContainer);
normalContainers.push(container.tabsContainer);
}
}
const containers = [...pinnedContainers, ...normalContainers]; const containers = [...pinnedContainers, ...normalContainers];
const tabGroups = []; const tabGroups = [];
for (const container of containers) { for (const container of containers) {

View File

@@ -454,16 +454,11 @@
} }
/* Mark workspaces indicator */ /* Mark workspaces indicator */
#zen-current-workspace-indicator-container {
position: relative;
margin-bottom: var(--zen-workspace-indicator-height);
}
.zen-current-workspace-indicator { .zen-current-workspace-indicator {
padding: calc(15px + var(--zen-toolbox-padding)) padding: calc(15px + var(--zen-toolbox-padding))
calc(4px + var(--tab-inline-padding) + var(--zen-toolbox-padding)); calc(4px + var(--tab-inline-padding) + var(--zen-toolbox-padding));
font-weight: 600; font-weight: 600;
position: absolute; position: relative;
max-height: var(--zen-workspace-indicator-height); max-height: var(--zen-workspace-indicator-height);
min-height: var(--zen-workspace-indicator-height); min-height: var(--zen-workspace-indicator-height);
gap: var(--tab-icon-end-margin); gap: var(--tab-icon-end-margin);
@@ -508,6 +503,27 @@
} }
} }
#zen-current-workspace-indicator-container[hidden='true'] { /* mark: workspace element */
display: none !important; zen-workspace {
flex-direction: column;
width: calc(100% + var(--zen-toolbox-padding) * 2);
position: absolute;
height: 100%;
overflow: hidden;
& > arrowscrollbox {
max-height: 100%;
overflow: hidden;
&::part(scrollbutton-up),
&::part(scrollbutton-down) {
display: none;
}
&::part(scrollbox) {
scrollbar-width: thin;
scrollbar-color: var(--vertical-tabs-scrollbar-color);
overflow-y: auto;
}
}
} }