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
index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f79bdefd9e 100644
index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..cf13724d147c8b8fc35c76d7f77601eb1077ea5c 100644
--- a/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) {
let newWindowState;
if (
@@ -10,7 +28,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
!lazy.SessionStartup.willRestore()
) {
// 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;
}
@@ -22,7 +40,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
// 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
@@ -3355,7 +3352,7 @@ var SessionStoreInternal = {
@@ -3355,7 +3356,7 @@ var SessionStoreInternal = {
if (!isPrivateWindow && tabState.isPrivate) {
return;
}
@@ -31,7 +49,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
return;
}
@@ -4067,6 +4064,11 @@ var SessionStoreInternal = {
@@ -4067,6 +4068,11 @@ var SessionStoreInternal = {
Math.min(tabState.index, tabState.entries.length)
);
tabState.pinned = false;
@@ -43,7 +61,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
if (inBackground === false) {
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,
tabIndex: aSource == aTargetWindow ? pos : Infinity,
pinned: state.pinned,
@@ -51,7 +69,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
userContextId: state.userContextId,
skipLoad: true,
preferredRemoteType,
@@ -5358,7 +5361,7 @@ var SessionStoreInternal = {
@@ -5358,7 +5365,7 @@ var SessionStoreInternal = {
for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) {
let tab = tabbrowser.tabs[i];
@@ -60,7 +78,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
removableTabs.push(tab);
}
}
@@ -5418,7 +5421,7 @@ var SessionStoreInternal = {
@@ -5418,7 +5425,7 @@ var SessionStoreInternal = {
}
let workspaceID = aWindow.getWorkspaceID();
@@ -69,7 +87,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
winData.workspaceID = workspaceID;
}
},
@@ -5609,11 +5612,12 @@ var SessionStoreInternal = {
@@ -5609,11 +5616,12 @@ var SessionStoreInternal = {
}
let tabbrowser = aWindow.gBrowser;
@@ -83,7 +101,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
// update the internal state data for this window
for (let tab of tabs) {
if (tab == aWindow.FirefoxViewHandler.tab) {
@@ -5624,6 +5628,7 @@ var SessionStoreInternal = {
@@ -5624,6 +5632,7 @@ var SessionStoreInternal = {
tabsData.push(tabData);
}
@@ -91,7 +109,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
// update tab group state for this window
winData.groups = [];
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,
// since it's only inserted into the tab strip after it's selected).
if (aWindow.FirefoxViewHandler.tab?.selected) {
@@ -100,7 +118,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
winData.title = tabbrowser.tabs[0].label;
}
winData.selected = selectedIndex;
@@ -5748,8 +5753,8 @@ var SessionStoreInternal = {
@@ -5748,8 +5757,8 @@ var SessionStoreInternal = {
// selectTab represents.
let selectTab = 0;
if (overwriteTabs) {
@@ -111,7 +129,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
selectTab = Math.min(selectTab, winData.tabs.length);
}
@@ -5792,6 +5797,8 @@ var SessionStoreInternal = {
@@ -5792,6 +5801,8 @@ var SessionStoreInternal = {
winData.tabs,
winData.groups ?? []
);
@@ -120,7 +138,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
this._log.debug(
`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
// attributes that may trigger external events.
@@ -146,7 +164,7 @@ index e8192ea9d8d35165fbfbb8c4fc4a96641a80cc86..fcd331a25a34e406e8f74d15db8567f7
if (tabData.pinned) {
tabbrowser.pinTab(tab);
@@ -7264,7 +7290,7 @@ var SessionStoreInternal = {
@@ -7264,7 +7294,7 @@ var SessionStoreInternal = {
let groupsToSave = new Map();
for (let tIndex = 0; tIndex < window.tabs.length; ) {

View File

@@ -19,6 +19,8 @@
'TabGrouped',
'TabUngrouped',
'ZenFolderChangedWorkspace',
'TabAddedToEssentials',
'TabRemovedFromEssentials',
];
#listeners = [];
@@ -396,12 +398,23 @@
_onPinnedTabEvent(action, event) {
if (!this.enabled) return;
const tab = event.target;
if (this._ignoreNextTabPinnedEvent) {
delete this._ignoreNextTabPinnedEvent;
return;
}
switch (action) {
case 'TabPinned':
case 'TabAddedToEssentials':
tab._zenClickEventListener = this._zenClickEventListener;
tab.addEventListener('click', tab._zenClickEventListener);
this._setPinnedAttributes(tab);
break;
case 'TabRemovedFromEssentials':
if (tab.pinned) {
this.#onTabMove(tab);
break;
}
// [Fall through]
case 'TabUnpinned':
this._removePinnedAttributes(tab);
if (tab._zenClickEventListener) {
@@ -957,30 +970,33 @@
const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if (pin) {
pin.isEssential = true;
pin.workspaceUuid = null;
this.savePin(pin);
}
if (tab.ownerGlobal !== window) {
tab = gBrowser.adoptTab(tab, {
selectTab: tab.selected,
});
tab.setAttribute('zen-essential', 'true');
} else {
section.appendChild(tab);
}
gBrowser.tabContainer._invalidateCachedTabs();
gBrowser.zenHandleTabMove(tab, () => {
if (tab.ownerGlobal !== window) {
tab = gBrowser.adoptTab(tab, {
selectTab: tab.selected,
});
tab.setAttribute('zen-essential', 'true');
} else {
section.appendChild(tab);
}
});
} else {
gBrowser.pinTab(tab);
this._ignoreNextTabPinnedEvent = true;
}
tab.setAttribute('zenDefaultUserContextId', true);
if (tab.selected) {
gZenWorkspaces.switchTabIfNeeded(tab);
}
this.#onTabMove(tab);
this.onTabIconChanged(tab);
// Dispatch the event to update the UI
const event = new CustomEvent('TabAddedToEssentials', {
detail: { tab },
bubbles: true,
cancelable: false,
});
tab.dispatchEvent(event);
}
@@ -1003,15 +1019,16 @@
if (unpin) {
gBrowser.unpinTab(tab);
} else {
const pinContainer = gZenWorkspaces.pinnedTabsContainer;
pinContainer.prepend(tab);
gBrowser.tabContainer._invalidateCachedTabs();
this.#onTabMove(tab);
gBrowser.zenHandleTabMove(tab, () => {
const pinContainer = gZenWorkspaces.pinnedTabsContainer;
pinContainer.prepend(tab);
});
}
// Dispatch the event to update the UI
const event = new CustomEvent('TabRemovedFromEssentials', {
detail: { tab },
bubbles: true,
cancelable: false,
});
tab.dispatchEvent(event);
}
@@ -1068,6 +1085,7 @@
document
.getElementById('cmd_contextZenAddToEssentials')
.setAttribute('disabled', !this.canEssentialBeAdded(contextTab));
document.getElementById('context_closeTab').hidden = contextTab.hasAttribute('zen-essential');
document.getElementById('context_zen-remove-essential').hidden =
!contextTab.getAttribute('zen-essential');
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) {
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();
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
const extraTabs = Array.from(gBrowser.tabContainer.arrowScrollbox.children).filter(
(child) =>
child.tagName === 'tab' &&
gBrowser.isTab(child) &&
!child.hasAttribute('zen-workspace-id') &&
!child.hasAttribute('zen-empty-tab') &&
!child.hasAttribute('zen-essential')
@@ -2812,7 +2814,12 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
pinnedContainers = [document.getElementById('pinned-tabs-container')];
normalContainers = [this.activeWorkspaceStrip];
} 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);
if (container) {
pinnedContainers.push(container.pinnedTabsContainer);
@@ -2826,7 +2833,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
continue;
}
for (const tab of container.children) {
if (tab.tagName === 'tab') {
if (gBrowser.isTab(tab)) {
tabs.push(tab);
const glance = tab.querySelector('.tabbrowser-tab[glance-id]');
if (glance) {
@@ -2843,13 +2850,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
}
}
}
const currentWorkspace = this.activeWorkspace;
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;
return (this._allStoredTabs = tabs);
}
get allTabGroups() {
@@ -2908,7 +2909,7 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
reorganizeTabsAfterWelcome() {
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) {
this.moveTabToWorkspace(tab, this.activeWorkspace);
}