fix: Fixed essentials reordering on every restart, b=bug #10309, c=tabs, workspaces

This commit is contained in:
mr. m
2025-09-27 13:14:03 +02:00
parent 528f3d6a0b
commit 8c6c13573b
3 changed files with 80 additions and 43 deletions

View File

@@ -1,8 +1,26 @@
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f79bdefd9e 100644 index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..cf13724d147c8b8fc35c76d7f77601eb1077ea5c 100644
--- a/browser/components/sessionstore/SessionStore.sys.mjs --- a/browser/components/sessionstore/SessionStore.sys.mjs
+++ b/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs
@@ -2133,7 +2133,6 @@ var SessionStoreInternal = { @@ -126,6 +126,8 @@ const TAB_EVENTS = [
"TabUngrouped",
"TabGroupCollapse",
"TabGroupExpand",
+ "TabAddedToEssentials",
+ "TabRemovedFromEssentials",
];
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -1898,6 +1900,8 @@ var SessionStoreInternal = {
case "TabPinned":
case "TabUnpinned":
case "SwapDocShells":
+ case "TabRemovedFromEssentials":
+ case "TabAddedToEssentials":
this.saveStateDelayed(win);
break;
case "TabGroupCreate":
@@ -2133,7 +2137,6 @@ var SessionStoreInternal = {
if (closedWindowState) { if (closedWindowState) {
let newWindowState; let newWindowState;
if ( if (
@@ -10,7 +28,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
!lazy.SessionStartup.willRestore() !lazy.SessionStartup.willRestore()
) { ) {
// We want to split the window up into pinned tabs and unpinned tabs. // We want to split the window up into pinned tabs and unpinned tabs.
@@ -2366,11 +2365,9 @@ var SessionStoreInternal = { @@ -2366,11 +2369,9 @@ var SessionStoreInternal = {
tabbrowser.selectedTab.label; tabbrowser.selectedTab.label;
} }
@@ -22,7 +40,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
// Store the window's close date to figure out when each individual tab // Store the window's close date to figure out when each individual tab
// was closed. This timestamp should allow re-arranging data based on how // was closed. This timestamp should allow re-arranging data based on how
@@ -3355,7 +3352,7 @@ var SessionStoreInternal = { @@ -3355,7 +3356,7 @@ var SessionStoreInternal = {
if (!isPrivateWindow && tabState.isPrivate) { if (!isPrivateWindow && tabState.isPrivate) {
return; return;
} }
@@ -31,7 +49,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
return; return;
} }
@@ -4067,6 +4064,11 @@ var SessionStoreInternal = { @@ -4067,6 +4068,11 @@ var SessionStoreInternal = {
Math.min(tabState.index, tabState.entries.length) Math.min(tabState.index, tabState.entries.length)
); );
tabState.pinned = false; tabState.pinned = false;
@@ -43,7 +61,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
if (inBackground === false) { if (inBackground === false) {
aWindow.gBrowser.selectedTab = newTab; aWindow.gBrowser.selectedTab = newTab;
@@ -4503,6 +4505,7 @@ var SessionStoreInternal = { @@ -4503,6 +4509,7 @@ var SessionStoreInternal = {
// Append the tab if we're opening into a different window, // Append the tab if we're opening into a different window,
tabIndex: aSource == aTargetWindow ? pos : Infinity, tabIndex: aSource == aTargetWindow ? pos : Infinity,
pinned: state.pinned, pinned: state.pinned,
@@ -51,7 +69,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
userContextId: state.userContextId, userContextId: state.userContextId,
skipLoad: true, skipLoad: true,
preferredRemoteType, preferredRemoteType,
@@ -5358,7 +5361,7 @@ var SessionStoreInternal = { @@ -5358,7 +5365,7 @@ var SessionStoreInternal = {
for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) { for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) {
let tab = tabbrowser.tabs[i]; let tab = tabbrowser.tabs[i];
@@ -60,7 +78,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
removableTabs.push(tab); removableTabs.push(tab);
} }
} }
@@ -5418,7 +5421,7 @@ var SessionStoreInternal = { @@ -5418,7 +5425,7 @@ var SessionStoreInternal = {
} }
let workspaceID = aWindow.getWorkspaceID(); let workspaceID = aWindow.getWorkspaceID();
@@ -69,7 +87,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
winData.workspaceID = workspaceID; winData.workspaceID = workspaceID;
} }
}, },
@@ -5609,11 +5612,12 @@ var SessionStoreInternal = { @@ -5609,11 +5616,12 @@ var SessionStoreInternal = {
} }
let tabbrowser = aWindow.gBrowser; let tabbrowser = aWindow.gBrowser;
@@ -83,7 +101,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
// update the internal state data for this window // update the internal state data for this window
for (let tab of tabs) { for (let tab of tabs) {
if (tab == aWindow.FirefoxViewHandler.tab) { if (tab == aWindow.FirefoxViewHandler.tab) {
@@ -5624,6 +5628,7 @@ var SessionStoreInternal = { @@ -5624,6 +5632,7 @@ var SessionStoreInternal = {
tabsData.push(tabData); tabsData.push(tabData);
} }
@@ -91,7 +109,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
// update tab group state for this window // update tab group state for this window
winData.groups = []; winData.groups = [];
for (let tabGroup of aWindow.gBrowser.tabGroups) { for (let tabGroup of aWindow.gBrowser.tabGroups) {
@@ -5636,7 +5641,7 @@ var SessionStoreInternal = { @@ -5636,7 +5645,7 @@ var SessionStoreInternal = {
// a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab, // a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab,
// since it's only inserted into the tab strip after it's selected). // since it's only inserted into the tab strip after it's selected).
if (aWindow.FirefoxViewHandler.tab?.selected) { if (aWindow.FirefoxViewHandler.tab?.selected) {
@@ -100,7 +118,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
winData.title = tabbrowser.tabs[0].label; winData.title = tabbrowser.tabs[0].label;
} }
winData.selected = selectedIndex; winData.selected = selectedIndex;
@@ -5748,8 +5753,8 @@ var SessionStoreInternal = { @@ -5748,8 +5757,8 @@ var SessionStoreInternal = {
// selectTab represents. // selectTab represents.
let selectTab = 0; let selectTab = 0;
if (overwriteTabs) { if (overwriteTabs) {
@@ -111,7 +129,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
selectTab = Math.min(selectTab, winData.tabs.length); selectTab = Math.min(selectTab, winData.tabs.length);
} }
@@ -5792,6 +5797,8 @@ var SessionStoreInternal = { @@ -5792,6 +5801,8 @@ var SessionStoreInternal = {
winData.tabs, winData.tabs,
winData.groups ?? [] winData.groups ?? []
); );
@@ -120,7 +138,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
this._log.debug( this._log.debug(
`restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs` `restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs`
); );
@@ -6349,6 +6356,25 @@ var SessionStoreInternal = { @@ -6349,6 +6360,25 @@ var SessionStoreInternal = {
// Most of tabData has been restored, now continue with restoring // Most of tabData has been restored, now continue with restoring
// attributes that may trigger external events. // attributes that may trigger external events.
@@ -146,7 +164,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
if (tabData.pinned) { if (tabData.pinned) {
tabbrowser.pinTab(tab); tabbrowser.pinTab(tab);
@@ -7264,7 +7290,7 @@ var SessionStoreInternal = { @@ -7264,7 +7294,7 @@ var SessionStoreInternal = {
let groupsToSave = new Map(); let groupsToSave = new Map();
for (let tIndex = 0; tIndex < window.tabs.length; ) { for (let tIndex = 0; tIndex < window.tabs.length; ) {

View File

@@ -19,6 +19,8 @@
'TabGrouped', 'TabGrouped',
'TabUngrouped', 'TabUngrouped',
'ZenFolderChangedWorkspace', 'ZenFolderChangedWorkspace',
'TabAddedToEssentials',
'TabRemovedFromEssentials',
]; ];
#listeners = []; #listeners = [];
@@ -396,12 +398,23 @@
_onPinnedTabEvent(action, event) { _onPinnedTabEvent(action, event) {
if (!this.enabled) return; if (!this.enabled) return;
const tab = event.target; const tab = event.target;
if (this._ignoreNextTabPinnedEvent) {
delete this._ignoreNextTabPinnedEvent;
return;
}
switch (action) { switch (action) {
case 'TabPinned': case 'TabPinned':
case 'TabAddedToEssentials':
tab._zenClickEventListener = this._zenClickEventListener; tab._zenClickEventListener = this._zenClickEventListener;
tab.addEventListener('click', tab._zenClickEventListener); tab.addEventListener('click', tab._zenClickEventListener);
this._setPinnedAttributes(tab); this._setPinnedAttributes(tab);
break; break;
case 'TabRemovedFromEssentials':
if (tab.pinned) {
this.#onTabMove(tab);
break;
}
// [Fall through]
case 'TabUnpinned': case 'TabUnpinned':
this._removePinnedAttributes(tab); this._removePinnedAttributes(tab);
if (tab._zenClickEventListener) { if (tab._zenClickEventListener) {
@@ -957,30 +970,33 @@
const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id')); const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if (pin) { if (pin) {
pin.isEssential = true; pin.isEssential = true;
pin.workspaceUuid = null;
this.savePin(pin); this.savePin(pin);
} }
if (tab.ownerGlobal !== window) { gBrowser.zenHandleTabMove(tab, () => {
tab = gBrowser.adoptTab(tab, { if (tab.ownerGlobal !== window) {
selectTab: tab.selected, tab = gBrowser.adoptTab(tab, {
}); selectTab: tab.selected,
tab.setAttribute('zen-essential', 'true'); });
} else { tab.setAttribute('zen-essential', 'true');
section.appendChild(tab); } else {
} section.appendChild(tab);
gBrowser.tabContainer._invalidateCachedTabs(); }
});
} else { } else {
gBrowser.pinTab(tab); gBrowser.pinTab(tab);
this._ignoreNextTabPinnedEvent = true;
} }
tab.setAttribute('zenDefaultUserContextId', true); tab.setAttribute('zenDefaultUserContextId', true);
if (tab.selected) { if (tab.selected) {
gZenWorkspaces.switchTabIfNeeded(tab); gZenWorkspaces.switchTabIfNeeded(tab);
} }
this.#onTabMove(tab);
this.onTabIconChanged(tab); this.onTabIconChanged(tab);
// Dispatch the event to update the UI // Dispatch the event to update the UI
const event = new CustomEvent('TabAddedToEssentials', { const event = new CustomEvent('TabAddedToEssentials', {
detail: { tab }, detail: { tab },
bubbles: true,
cancelable: false,
}); });
tab.dispatchEvent(event); tab.dispatchEvent(event);
} }
@@ -1003,15 +1019,16 @@
if (unpin) { if (unpin) {
gBrowser.unpinTab(tab); gBrowser.unpinTab(tab);
} else { } else {
const pinContainer = gZenWorkspaces.pinnedTabsContainer; gBrowser.zenHandleTabMove(tab, () => {
pinContainer.prepend(tab); const pinContainer = gZenWorkspaces.pinnedTabsContainer;
gBrowser.tabContainer._invalidateCachedTabs(); pinContainer.prepend(tab);
this.#onTabMove(tab); });
} }
// Dispatch the event to update the UI // Dispatch the event to update the UI
const event = new CustomEvent('TabRemovedFromEssentials', { const event = new CustomEvent('TabRemovedFromEssentials', {
detail: { tab }, detail: { tab },
bubbles: true,
cancelable: false,
}); });
tab.dispatchEvent(event); tab.dispatchEvent(event);
} }
@@ -1068,6 +1085,7 @@
document document
.getElementById('cmd_contextZenAddToEssentials') .getElementById('cmd_contextZenAddToEssentials')
.setAttribute('disabled', !this.canEssentialBeAdded(contextTab)); .setAttribute('disabled', !this.canEssentialBeAdded(contextTab));
document.getElementById('context_closeTab').hidden = contextTab.hasAttribute('zen-essential');
document.getElementById('context_zen-remove-essential').hidden = document.getElementById('context_zen-remove-essential').hidden =
!contextTab.getAttribute('zen-essential'); !contextTab.getAttribute('zen-essential');
document.getElementById('zen-context-menu-new-folder').hidden = document.getElementById('zen-context-menu-new-folder').hidden =

View File

@@ -510,7 +510,9 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
#organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs) { #organizeTabsToWorkspaceSections(workspace, section, pinnedSection, tabs) {
const workspaceTabs = Array.from(tabs).filter( const workspaceTabs = Array.from(tabs).filter(
(tab) => tab.getAttribute('zen-workspace-id') === workspace.uuid (tab) =>
tab.getAttribute('zen-workspace-id') === workspace.uuid &&
!tab.hasAttribute('zen-essential')
); );
let folders = new Set(); let folders = new Set();
const getFolderRoot = (tab) => { const getFolderRoot = (tab) => {
@@ -2387,7 +2389,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
// get extra tabs remaning (e.g. on new profiles) and just move them to the new workspace // 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( const extraTabs = Array.from(gBrowser.tabContainer.arrowScrollbox.children).filter(
(child) => (child) =>
child.tagName === 'tab' && gBrowser.isTab(child) &&
!child.hasAttribute('zen-workspace-id') && !child.hasAttribute('zen-workspace-id') &&
!child.hasAttribute('zen-empty-tab') && !child.hasAttribute('zen-empty-tab') &&
!child.hasAttribute('zen-essential') !child.hasAttribute('zen-essential')
@@ -2812,7 +2814,12 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
pinnedContainers = [document.getElementById('pinned-tabs-container')]; pinnedContainers = [document.getElementById('pinned-tabs-container')];
normalContainers = [this.activeWorkspaceStrip]; normalContainers = [this.activeWorkspaceStrip];
} else { } else {
for (const workspace of this._workspaceCache.workspaces) { let workspaces = Array.from(this._workspaceCache?.workspaces || []);
// Make the active workspace first
workspaces = workspaces.sort((a, b) =>
a.uuid === this.activeWorkspace ? -1 : b.uuid === this.activeWorkspace ? 1 : 0
);
for (const workspace of workspaces) {
const container = this.workspaceElement(workspace.uuid); const container = this.workspaceElement(workspace.uuid);
if (container) { if (container) {
pinnedContainers.push(container.pinnedTabsContainer); pinnedContainers.push(container.pinnedTabsContainer);
@@ -2826,7 +2833,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
continue; continue;
} }
for (const tab of container.children) { for (const tab of container.children) {
if (tab.tagName === 'tab') { if (gBrowser.isTab(tab)) {
tabs.push(tab); tabs.push(tab);
const glance = tab.querySelector('.tabbrowser-tab[glance-id]'); const glance = tab.querySelector('.tabbrowser-tab[glance-id]');
if (glance) { if (glance) {
@@ -2843,13 +2850,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
} }
} }
} }
const currentWorkspace = this.activeWorkspace; return (this._allStoredTabs = tabs);
this._allStoredTabs = tabs.sort((a, b) => {
const aWorkspaceId = a.getAttribute('zen-workspace-id');
const bWorkspaceId = b.getAttribute('zen-workspace-id');
return aWorkspaceId === currentWorkspace ? -1 : bWorkspaceId === currentWorkspace ? 1 : 0;
});
return this._allStoredTabs;
} }
get allTabGroups() { get allTabGroups() {
@@ -2908,7 +2909,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
reorganizeTabsAfterWelcome() { reorganizeTabsAfterWelcome() {
const children = gBrowser.tabContainer.arrowScrollbox.children; const children = gBrowser.tabContainer.arrowScrollbox.children;
const remainingTabs = Array.from(children).filter((child) => child.tagName === 'tab'); const remainingTabs = Array.from(children).filter((child) => gBrowser.isTab(child));
for (const tab of remainingTabs) { for (const tab of remainingTabs) {
this.moveTabToWorkspace(tab, this.activeWorkspace); this.moveTabToWorkspace(tab, this.activeWorkspace);
} }