feat: Re-implemented workspace icons, b=(no-bug), c=common, tabs, workspaces

This commit is contained in:
Mr. M
2025-05-15 23:36:10 +02:00
parent 1d8e0fc3d7
commit bac3e38318
10 changed files with 141 additions and 109 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
index 00c8976d3e258c0875d7da2f3ec823d8907a84c9..191598ed701514ca7207cd64c3da46960a5d0e82 100644
index 00c8976d3e258c0875d7da2f3ec823d8907a84c9..cc61d5a845b5ce22a61f5a1aab8b280b2bcdf101 100644
--- a/browser/base/content/navigator-toolbox.inc.xhtml
+++ b/browser/base/content/navigator-toolbox.inc.xhtml
@@ -2,7 +2,7 @@
@@ -26,7 +26,7 @@ index 00c8976d3e258c0875d7da2f3ec823d8907a84c9..191598ed701514ca7207cd64c3da4696
tooltip="tabbrowser-tab-tooltip"
orient="horizontal"
stopwatchid="tabClick">
+<html:div id="zen-essentials-wrapper" skipintoolbarset="true"></html:div>
+<html:div id="zen-essentials" skipintoolbarset="true"></html:div>
+<html:div id="zen-tabs-wrapper">
<hbox class="tab-drop-indicator" hidden="true"/>
<html:span id="tab-drag-empty-feedback" role="presentation"/>

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/ZenThemeMarketplaceChild.sys.mjs (../../zen/mods/actors/ZenThemeMarketplaceChild.sys.mjs)
content/browser/zen-components/ZenWorkspaceIcons.mjs (../../zen/workspaces/ZenWorkspaceIcons.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/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)

View File

@@ -5,6 +5,7 @@
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/ZenKeyboardShortcuts.mjs", this);
Services.scriptloader.loadSubScript("chrome://browser/content/zen-components/ZenWorkspaceIcons.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/ZenWorkspacesSync.mjs", this);

View File

@@ -9,5 +9,5 @@
context="toolbar-context-menu"
mode="icons">
<toolbarbutton removable="true" class="chromeclass-toolbar-additional toolbarbutton-1 zen-sidebar-action-button" id="zen-expand-sidebar-button" command="cmd_zenToggleSidebar" data-l10n-id="sidebar-zen-expand"></toolbarbutton>
<toolbarbutton id="zen-workspaces-button" class="chromeclass-toolbar-additional" overflows="false" removable="false"></toolbarbutton>
<zen-workspace-icons id="zen-workspaces-button" overflows="false" removable="false" />
</toolbar>

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/customizableui/CustomizeMode.sys.mjs b/browser/components/customizableui/CustomizeMode.sys.mjs
index 619bb2af5a3a0995fc93fa040696dd2854848ab5..bbc6bad906e9ccaf668ca99f4a0411f564ef1e56 100644
index 619bb2af5a3a0995fc93fa040696dd2854848ab5..14ad5f6122971a0a0dc20d22acdc073f84965dad 100644
--- a/browser/components/customizableui/CustomizeMode.sys.mjs
+++ b/browser/components/customizableui/CustomizeMode.sys.mjs
@@ -500,7 +500,7 @@ export class CustomizeMode {
@@ -20,7 +20,15 @@ index 619bb2af5a3a0995fc93fa040696dd2854848ab5..bbc6bad906e9ccaf668ca99f4a0411f5
customizer.hidden = true;
browser.hidden = false;
@@ -3125,6 +3125,20 @@ export class CustomizeMode {
@@ -1173,6 +1173,7 @@ export class CustomizeMode {
return (
aNode.localName == "toolbarbutton" ||
aNode.localName == "toolbaritem" ||
+ aNode.localName == "zen-workspace-icons" ||
aNode.localName == "toolbarseparator" ||
aNode.localName == "toolbarspring" ||
aNode.localName == "toolbarspacer"
@@ -3125,6 +3126,20 @@ export class CustomizeMode {
if (makeSpaceImmediately) {
aDraggedOverItem.setAttribute("notransition", "true");
}

View File

@@ -373,7 +373,7 @@ menuitem {
gap: 10px;
z-index: 1000;
padding: var(--zen-toast-padding);
border-radius: calc(var(--zen-native-inner-radius) + 6px);
border-radius: calc(var(--zen-native-inner-radius) + 8px);
background: linear-gradient(
170deg,
var(--zen-primary-color) -40%,
@@ -408,7 +408,7 @@ menuitem {
padding: 0 12px !important;
min-width: unset !important;
margin: 0px !important;
border-radius: var(--zen-native-inner-radius) !important;
border-radius: calc(var(--zen-native-inner-radius) + 4px) !important;
:root[zen-right-side='true'] & {
order: -1;

View File

@@ -552,7 +552,7 @@
}
/* Set min height for tabs in the essentials wrapper */
& #zen-essentials-wrapper {
& #zen-essentials {
--tab-min-height: 44px;
}
@@ -736,7 +736,7 @@
min-width: unset !important;
}
& #zen-essentials-wrapper {
& #zen-essentials {
margin-left: unset !important;
}
@@ -1225,12 +1225,16 @@
Mark: Essentials Toolbar / Section Styles
========================================================================== */
#zen-essentials-wrapper,
#zen-essentials,
#zen-current-workspace-indicator-container {
margin-left: calc(-1 * var(--zen-toolbox-padding));
min-width: calc(100% + var(--zen-toolbox-padding) * 2);
}
#zen-essentials {
z-index: 1;
}
/* Container for essential items (often pinned/favorite tabs) */
.zen-essentials-container {
will-change: transform;

View File

@@ -0,0 +1,82 @@
{
class ZenWorkspaceIcons extends MozXULElement {
constructor() {
super();
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
}
window.addEventListener('ZenWorkspacesUIUpdate', this, true);
}
#createWorkspaceIcon(workspace) {
const button = document.createXULElement('toolbarbutton');
button.setAttribute('class', 'subviewbutton');
button.setAttribute('tooltiptext', workspace.name);
button.setAttribute('zen-workspace-id', workspace.uuid);
const icon = document.createXULElement('div');
icon.setAttribute('class', 'zen-workspace-icon');
if (ZenWorkspaces.workspaceHasIcon(workspace)) {
icon.textContent = workspace.icon;
} else {
icon.setAttribute('no-icon', true);
}
button.appendChild(icon);
button.addEventListener('command', this);
return button;
}
async #updateIcons() {
const workspaces = await ZenWorkspaces._workspaces();
this.innerHTML = '';
for (const workspace of workspaces.workspaces) {
const button = this.#createWorkspaceIcon(workspace);
this.appendChild(button);
}
if (workspaces.workspaces.length <= 1) {
this.setAttribute('dont-show', 'true');
} else {
this.removeAttribute('dont-show');
}
}
on_command(event) {
const button = event.target;
const uuid = button.getAttribute('zen-workspace-id');
if (uuid) {
ZenWorkspaces.changeWorkspaceWithID(uuid);
}
}
on_ZenWorkspacesUIUpdate(event) {
this.#updateIcons();
this.activeIndex = event.detail.activeIndex;
}
set activeIndex(uuid) {
const buttons = this.querySelectorAll('toolbarbutton');
for (const button of buttons) {
if (button.getAttribute('zen-workspace-id') == uuid) {
button.setAttribute('active', 'true');
} else {
button.removeAttribute('active');
}
}
}
get activeIndex() {
const buttons = this.querySelectorAll('toolbarbutton');
for (const button of buttons) {
if (button.hasAttribute('active')) {
return button.getAttribute('zen-workspace-id');
}
}
return null;
}
}
customElements.define('zen-workspace-icons', ZenWorkspaceIcons);
}

View File

@@ -110,6 +110,9 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
ChromeUtils.defineLazyGetter(this, 'tabContainer', () =>
document.getElementById('tabbrowser-tabs')
);
ChromeUtils.defineLazyGetter(this, 'workspaceIcons', () =>
document.getElementById('zen-workspaces-button')
);
this._activeWorkspace = Services.prefs.getStringPref('zen.workspaces.active', '');
window.addEventListener('resize', this.onWindowResize.bind(this));
@@ -318,7 +321,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
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-wrapper').children) {
for (let element of document.getElementById('zen-essentials').children) {
if (element.classList.contains('tabbrowser-tab')) {
continue;
}
@@ -412,7 +415,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
essentialsContainer.className = 'zen-essentials-container zen-workspace-tabs-section';
essentialsContainer.setAttribute('flex', '1');
essentialsContainer.setAttribute('container', container);
document.getElementById('zen-essentials-wrapper').appendChild(essentialsContainer);
document.getElementById('zen-essentials').appendChild(essentialsContainer);
}
return essentialsContainer;
}
@@ -791,7 +794,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
}
async initializeWorkspaces() {
await this.initializeWorkspacesButton();
if (this.workspaceEnabled) {
this._initializeWorkspaceCreationIcons();
this._initializeWorkspaceTabContextMenus();
@@ -943,7 +945,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this.openWorkspacesDialog(event);
};
indicator.addEventListener('contextmenu', th);
indicator.addEventListener('click', th);
indicator.addEventListener('command', th);
}
shouldCloseWindow() {
@@ -1367,6 +1369,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (!browser.ZenWorkspaces.workspaceEnabled) {
return;
}
let workspaceList = browser.document.getElementById('PanelUI-zen-workspaces-list');
const createWorkspaceElement = (workspace) => {
let element = browser.document.createXULElement('toolbarbutton');
@@ -1526,7 +1529,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
await this.changeWorkspace(workspace);
let panel = this.ownerWindow.document.getElementById('PanelUI-zen-workspaces');
PanelMultiView.hidePopup(panel);
this.ownerWindow.document.getElementById('zen-workspaces-button').removeAttribute('open');
}).bind(browser.ZenWorkspaces);
return element;
};
@@ -1592,6 +1594,12 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
browser.ZenWorkspaces._workspaceBookmarksCache = null;
}
let workspaces = await browser.ZenWorkspaces._workspaces();
browser.dispatchEvent(
new CustomEvent('ZenWorkspacesUIUpdate', {
bubbles: true,
detail: { workspaces, activeIndex: browser.ZenWorkspaces.activeWorkspace },
})
);
await browser.ZenWorkspaces.workspaceBookmarks();
workspaceList.innerHTML = '';
workspaceList.parentNode.style.display = 'flex';
@@ -1610,7 +1618,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
workspaceList.appendChild(createLastPositionDropTarget());
if (!ignoreStrip) {
await browser.ZenWorkspaces._expandWorkspacesStrip(browser);
browser.ZenWorkspaces._fixIndicatorsNames(workspaces);
}
});
@@ -1685,8 +1692,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
return;
}
let target =
event.target.closest('.zen-current-workspace-indicator') ||
document.getElementById('zen-workspaces-button');
event.target.closest('.zen-current-workspace-indicator');
let panel = document.getElementById('PanelUI-zen-workspaces');
await this._propagateWorkspaceData({
ignoreStrip: true,
@@ -1698,87 +1704,6 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
}).catch(console.error);
}
async initializeWorkspacesButton() {
if (!this.workspaceEnabled) {
return;
} else if (document.getElementById('zen-workspaces-button')) {
let button = document.getElementById('zen-workspaces-button');
button.removeAttribute('hidden');
return;
}
await this._expandWorkspacesStrip();
}
async _expandWorkspacesStrip(browser = window) {
if (typeof browser.ZenWorkspaces === 'undefined') {
browser = window;
}
let button = browser.document.getElementById('zen-workspaces-button');
while (button.firstChild) {
button.firstChild.remove();
}
if (this._workspacesButtonClickListener) {
button.removeEventListener('click', this._workspacesButtonClickListener);
this._workspacesButtonClickListener = null;
}
if (this._workspaceButtonContextMenuListener) {
button.removeEventListener('contextmenu', this._workspaceButtonContextMenuListener);
this._workspaceButtonContextMenuListener = null;
}
button.setAttribute('showInPrivateBrowsing', 'false');
button.setAttribute('tooltiptext', 'Workspaces');
let workspaces = await this._workspaces();
for (let workspace of workspaces.workspaces) {
let workspaceButton = browser.document.createXULElement('toolbarbutton');
workspaceButton.className = 'subviewbutton';
workspaceButton.setAttribute('tooltiptext', workspace.name);
workspaceButton.setAttribute('zen-workspace-id', workspace.uuid);
if (this.isWorkspaceActive(workspace)) {
workspaceButton.setAttribute('active', 'true');
} else {
workspaceButton.removeAttribute('active');
}
workspaceButton.addEventListener('click', async (event) => {
if (event.button !== 0) {
return;
}
await this.changeWorkspace(workspace);
});
let icon = browser.document.createXULElement('div');
icon.className = 'zen-workspace-icon';
if (this.workspaceHasIcon(workspace)) {
icon.textContent = this.getWorkspaceIcon(workspace);
} else {
icon.setAttribute('no-icon', 'true');
}
workspaceButton.appendChild(icon);
button.appendChild(workspaceButton);
}
if (workspaces.workspaces.length <= 1) {
button.setAttribute('dont-show', true);
} else {
button.removeAttribute('dont-show');
}
this._workspaceButtonContextMenuListener = (event) => {
event.preventDefault();
event.stopPropagation();
this.openWorkspacesDialog(event);
};
button.addEventListener(
'contextmenu',
this._workspaceButtonContextMenuListener.bind(browser.ZenWorkspaces)
);
}
closeWorkspacesSubView() {
let parentPanel = document.getElementById('PanelUI-zen-workspaces-multiview');
parentPanel.goBack(parentPanel);
@@ -1925,14 +1850,19 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._changeListeners.push(func);
}
async changeWorkspace(window, ...args) {
async changeWorkspaceWithID(workspaceID, ...args) {
const workspace = this.getWorkspaceFromId(workspaceID);
return await this.changeWorkspace(workspace, ...args);
}
async changeWorkspace(workspace, ...args) {
if (!this.workspaceEnabled || this._inChangingWorkspace) {
return;
}
this._inChangingWorkspace = true;
try {
this.log('Changing workspace to', window?.uuid);
await this._performWorkspaceChange(window, ...args);
this.log('Changing workspace to', workspace?.uuid);
await this._performWorkspaceChange(workspace, ...args);
} catch (e) {
console.error('ZenWorkspaces: Error changing workspace', e);
}
@@ -2054,7 +1984,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._fixIndicatorsNames(workspaces);
}
const otherContainersEssentials = document.querySelectorAll(
`#zen-essentials-wrapper .zen-workspace-tabs-section`
`#zen-essentials .zen-workspace-tabs-section`
);
const workspaceContextId = workspace.containerTabId;
const nextWorkspaceContextId =
@@ -2479,6 +2409,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
previousWorkspace,
onInit,
});
this.workspaceIcons.activeIndex = workspace.uuid;
await this._organizeWorkspaceStripLocations(workspace, true);
gZenUIManager.tabsWrapper.style.scrollbarWidth = '';
@@ -2646,7 +2577,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
for (const entry of entries) {
const originalWorkspaceId = entry.target.getAttribute('zen-workspace-id');
const workspacesIds = [];
if (entry.target.closest('#zen-essentials-wrapper')) {
if (entry.target.closest('#zen-essentials')) {
// Get all workspaces that have the same userContextId
const activeWorkspace = await this.getActiveWorkspace();
const userContextId = activeWorkspace.containerTabId;
@@ -3066,7 +2997,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
const tabs = [];
// we need to go through each tab in each container
const essentialsContainer = document.querySelectorAll(
'#zen-essentials-wrapper .zen-workspace-tabs-section'
'#zen-essentials .zen-workspace-tabs-section'
);
let pinnedContainers = [];
let normalContainers = [];
@@ -3262,17 +3193,17 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
onWindowResize(event = undefined) {
if (!(!event || event.target === window)) return;
// Check if workspace icons overflow the parent container
const parent = document.getElementById('zen-workspaces-button');
const parent = this.workspaceIcons;
if (!parent || this._processingResize) {
return;
}
this._processingResize = true;
// Once we are overflowing, we align the buttons to always stay inside the container,
// meaning we need to remove the overflow attribute to reset the width
parent.removeAttribute('overflow');
parent.removeAttribute('icons-overflow');
requestAnimationFrame(() => {
const overflow = parent.scrollWidth > parent.clientWidth;
parent.toggleAttribute('overflow', overflow);
parent.toggleAttribute('icons-overflow', overflow);
// The maximum width a button has when it overflows based on the number of buttons
const numButtons = parent.children.length + 1; // +1 to exclude the active button
const maxWidth = 100 / numButtons;

View File

@@ -61,7 +61,7 @@
}
}
&[overflow] {
&[icons-overflow] {
gap: 0 !important;
& toolbarbutton {
@@ -527,3 +527,8 @@ zen-workspace {
}
}
}
/** Customiable UI, this is an auto generated ID */
#wrapper-zen-workspaces-button {
width: 100%;
}