From 696a2148f0faf5dafe2062c58f8419458a8ae175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristijan=20Ribari=C4=87?= Date: Thu, 7 Nov 2024 11:40:44 +0100 Subject: [PATCH 1/2] (fix) Migrate pinned tabs from older Zen versions If there are no pinned tabs in the database on startup, assume it's a migration from an older version and save all currently pinned tabs to the database. Previously, Zen would remove any pinned tabs that didn't have a `zen-pin-id` attribute, which would occur during migration. This change ensures that pinned tabs are preserved during upgrades. --- src/browser/base/zen-components/ZenPinnedTabManager.mjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 5238907c9..8d6aa83e8 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -96,10 +96,13 @@ _initializePinnedTabs() { const pins = this._pinsCache; if (!pins?.length) { - // If there are no pins, we should remove any existing pinned tabs + // If there are no pins in the database it's probably migration from an older version - save all pinned tabs to the database for (let tab of gBrowser.tabs) { - if (tab.pinned && !tab.getAttribute("zen-pin-id")) { - gBrowser.removeTab(tab); + if (tab.pinned) { + if(tab.hasAttribute("zen-pin-id")) { + tab.removeAttribute("zen-pin-id"); + } + this._setPinnedAttributes(tab); } } return; From 014602266beda817391dc04f4965cd0766bd95d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristijan=20Ribari=C4=87?= Date: Thu, 7 Nov 2024 16:20:46 +0100 Subject: [PATCH 2/2] Correctly set the base pinned url and title for migrating from previous version. --- .../zen-components/ZenPinnedTabManager.mjs | 25 ++++++++++-------- .../tabbrowser/content/tabbrowser-js.patch | 26 ++++++++++++------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/browser/base/zen-components/ZenPinnedTabManager.mjs b/src/browser/base/zen-components/ZenPinnedTabManager.mjs index 8d6aa83e8..7070ddd2b 100644 --- a/src/browser/base/zen-components/ZenPinnedTabManager.mjs +++ b/src/browser/base/zen-components/ZenPinnedTabManager.mjs @@ -96,15 +96,6 @@ _initializePinnedTabs() { const pins = this._pinsCache; if (!pins?.length) { - // If there are no pins in the database it's probably migration from an older version - save all pinned tabs to the database - for (let tab of gBrowser.tabs) { - if (tab.pinned) { - if(tab.hasAttribute("zen-pin-id")) { - tab.removeAttribute("zen-pin-id"); - } - this._setPinnedAttributes(tab); - } - } return; } @@ -250,10 +241,16 @@ const uuid = gZenUIManager.generateUuidv4(); const userContextId = tab.getAttribute("usercontextid"); + let entry = null; + + if(tab.getAttribute("zen-pinned-entry")) { + entry = JSON.parse(tab.getAttribute("zen-pinned-entry")); + } + await ZenPinnedTabsStorage.savePin({ uuid, - title: tab.label || browser.contentTitle, - url: browser.currentURI.spec, + title: entry?.title || tab.label || browser.contentTitle, + url: entry?.url || browser.currentURI.spec, containerTabId: userContextId ? parseInt(userContextId, 10) : 0, workspaceUuid: tab.getAttribute("zen-workspace-id"), isEssential: tab.getAttribute("zen-essential") === "true" @@ -261,6 +258,12 @@ tab.setAttribute("zen-pin-id", uuid); + // This is used while migrating old pins to new system - we don't want to refresh when migrating + if (tab.getAttribute("zen-pinned-entry")) { + tab.removeAttribute("zen-pinned-entry"); + return; + } + await this._refreshPinnedTabs(); } diff --git a/src/browser/components/tabbrowser/content/tabbrowser-js.patch b/src/browser/components/tabbrowser/content/tabbrowser-js.patch index 02fd040b9..6c33d9e97 100644 --- a/src/browser/components/tabbrowser/content/tabbrowser-js.patch +++ b/src/browser/components/tabbrowser/content/tabbrowser-js.patch @@ -1,5 +1,5 @@ diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js -index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee3ac9ee42 100644 +index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..af0f2a13e957331d48643fe4430408924c55b08c 100644 --- a/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js @@ -462,11 +462,26 @@ @@ -106,7 +106,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee if (insertTab) { // insert the tab into the tab container in the correct position this._insertTabAtIndex(t, { -@@ -3291,6 +3319,20 @@ +@@ -3291,6 +3319,23 @@ ) { tabWasReused = true; tab = this.selectedTab; @@ -123,11 +123,14 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee + if (tabData.zenDefaultUserContextId) { + tab.setAttribute("zenDefaultUserContextId", "true"); + } ++ if (tabData.zenPinnedEntry) { ++ tab.setAttribute("zen-pinned-entry", tabData.zenPinnedEntry); ++ } + if (!tabData.pinned) { this.unpinTab(tab); } else { -@@ -3304,6 +3346,9 @@ +@@ -3304,6 +3349,9 @@ restoreTabsLazily && !select && !tabData.pinned; let url = "about:blank"; @@ -137,7 +140,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee if (tabData.entries?.length) { let activeIndex = (tabData.index || tabData.entries.length) - 1; // Ensure the index is in bounds. -@@ -3340,6 +3385,18 @@ +@@ -3340,6 +3388,21 @@ preferredRemoteType, }); @@ -152,11 +155,14 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee + } + if (tabData.zenDefaultUserContextId) { + tab.setAttribute("zenDefaultUserContextId", "true"); ++ } ++ if (tabData.zenPinnedEntry) { ++ tab.setAttribute("zen-pinned-entry", tabData.zenPinnedEntry); + } if (select) { tabToSelect = tab; } -@@ -3374,7 +3431,6 @@ +@@ -3374,7 +3437,6 @@ this.tabContainer._invalidateCachedTabs(); } } @@ -164,7 +170,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee tab.initialize(); } -@@ -4148,6 +4204,13 @@ +@@ -4148,6 +4210,13 @@ TelemetryStopwatch.start("FX_TAB_CLOSE_TIME_NO_ANIM_MS", aTab); } @@ -178,7 +184,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee // Handle requests for synchronously removing an already // asynchronously closing tab. if (!animate && aTab.closing) { -@@ -4163,6 +4226,10 @@ +@@ -4163,6 +4232,10 @@ // state). let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; @@ -189,7 +195,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee if ( !this._beginRemoveTab(aTab, { closeWindowFastpath: true, -@@ -5123,10 +5190,10 @@ +@@ -5123,10 +5196,10 @@ SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); }, @@ -202,7 +208,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee aTab.selected || aTab.closing || // Tabs that are sharing the screen, microphone or camera cannot be hidden. -@@ -7042,6 +7109,7 @@ +@@ -7042,6 +7115,7 @@ aWebProgress.isTopLevel ) { this.mTab.setAttribute("busy", "true"); @@ -210,7 +216,7 @@ index 14de79b543cf07b04d06ef5a3f94d9aa988ea39a..5c373d088cfb59ac0c48035e8b9928ee gBrowser._tabAttrModified(this.mTab, ["busy"]); this.mTab._notselectedsinceload = !this.mTab.selected; gBrowser.syncThrobberAnimations(this.mTab); -@@ -7874,7 +7942,7 @@ var TabContextMenu = { +@@ -7874,7 +7948,7 @@ var TabContextMenu = { ); contextUnpinSelectedTabs.hidden = !this.contextTab.pinned || !multiselectionContext;