feat: Add migration logic for zen_pins database to window sync, b=no-bug, c=common, tabs

This commit is contained in:
mr. m
2025-12-27 18:52:09 +01:00
parent ec8b14e8f1
commit 1338b43e10
6 changed files with 85 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..4f8553b7b20c0456929b572ca1522627a689b482 100644
index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..4439fe5fb3c7002b173415b615892ef356b22959 100644
--- a/browser/components/sessionstore/SessionStore.sys.mjs
+++ b/browser/components/sessionstore/SessionStore.sys.mjs
@@ -127,6 +127,8 @@ const TAB_EVENTS = [
@@ -233,7 +233,7 @@ index 2c2f43bf743ef458b378e85e9ed44a971711e1d9..4f8553b7b20c0456929b572ca1522627
+ if (tabData.zenStaticLabel) {
+ tab.zenStaticLabel = tabData.zenStaticLabel;
+ }
+ if (tabData.zenHasStaticIcon) {
+ if (tabData.zenHasStaticIcon && tabData.image) {
+ tab.zenStaticIcon = tabData.image;
+ }
+ if (tabData.zenDefaultUserContextId) {

View File

@@ -1,8 +1,8 @@
diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs
index 82721356d191055bec0d4b0ca49e481221988801..fc117fc8e0f5eb3d0a2fed70558773afb9afce9a 100644
index 82721356d191055bec0d4b0ca49e481221988801..ffa95005b96ea384433f18dace63faa35d2d21bf 100644
--- a/browser/components/sessionstore/TabState.sys.mjs
+++ b/browser/components/sessionstore/TabState.sys.mjs
@@ -85,7 +85,25 @@ class _TabState {
@@ -85,7 +85,24 @@ class _TabState {
tabData.groupId = tab.group.id;
}
@@ -11,7 +11,6 @@ index 82721356d191055bec0d4b0ca49e481221988801..fc117fc8e0f5eb3d0a2fed70558773af
+ tabData.zenEssential = tab.getAttribute("zen-essential");
+ tabData.pinned = tabData.pinned || tabData.zenEssential;
+ tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId");
+ tabData.zenPinnedEntry = tab.getAttribute("zen-pinned-entry");
+ tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon");
+ tabData.zenIsEmpty = tab.hasAttribute("zen-empty-tab");
+ tabData.zenStaticLabel = tab.zenStaticLabel;
@@ -28,7 +27,7 @@ index 82721356d191055bec0d4b0ca49e481221988801..fc117fc8e0f5eb3d0a2fed70558773af
tabData.userContextId = tab.userContextId || 0;
@@ -98,7 +116,7 @@ class _TabState {
@@ -98,7 +115,7 @@ class _TabState {
// Copy data from the tab state cache only if the tab has fully finished
// restoring. We don't want to overwrite data contained in __SS_data.

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..28a42ceb86f2b0f0747062e4881ce703ca0991da 100644
index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..b01c89f2e0d3b44dddaa01a20b4da13d797de7be 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -386,6 +386,7 @@
@@ -901,16 +901,17 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..28a42ceb86f2b0f0747062e4881ce703
// Clear tabs cache after moving nodes because the order of tabs may have
// changed.
this.tabContainer._invalidateCachedTabs();
@@ -6815,6 +7014,8 @@
@@ -6815,6 +7014,9 @@
params.userContextId = aTab.getAttribute("usercontextid");
}
let newTab = this.addWebTab("about:blank", params);
+ newTab._zenContentsVisible = true;
+ newTab.zenStaticLabel = aTab.zenStaticLabel;
+ newTab.zenStaticIcon = aTab.zenStaticIcon;
let newBrowser = this.getBrowserForTab(newTab);
aTab.container.tabDragAndDrop.finishAnimateTabMove();
@@ -7623,7 +7824,7 @@
@@ -7623,7 +7825,7 @@
// preventDefault(). It will still raise the window if appropriate.
break;
}
@@ -919,7 +920,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..28a42ceb86f2b0f0747062e4881ce703
window.focus();
aEvent.preventDefault();
break;
@@ -7640,7 +7841,6 @@
@@ -7640,7 +7842,6 @@
}
case "TabGroupCollapse":
aEvent.target.tabs.forEach(tab => {
@@ -927,7 +928,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..28a42ceb86f2b0f0747062e4881ce703
});
break;
case "TabGroupCreateByUser":
@@ -8589,6 +8789,7 @@
@@ -8589,6 +8790,7 @@
aWebProgress.isTopLevel
) {
this.mTab.setAttribute("busy", "true");
@@ -935,7 +936,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..28a42ceb86f2b0f0747062e4881ce703
gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected;
}
@@ -8670,6 +8871,7 @@
@@ -8670,6 +8872,7 @@
// known defaults. Note we use the original URL since about:newtab
// redirects to a prerendered page.
const shouldRemoveFavicon =
@@ -943,7 +944,7 @@ index 42027bfa55eab8ea9298a7d425f2ded45188f7f3..28a42ceb86f2b0f0747062e4881ce703
!this.mBrowser.mIconURL &&
!ignoreBlank &&
!(originalLocation.spec in FAVICON_DEFAULTS);
@@ -9623,7 +9825,7 @@ var TabContextMenu = {
@@ -9623,7 +9826,7 @@ var TabContextMenu = {
);
contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected;

View File

@@ -33,9 +33,6 @@ class ZenSessionStore extends nsZenPreloadedFeature {
if (tabData.zenDefaultUserContextId) {
tab.setAttribute('zenDefaultUserContextId', 'true');
}
if (tabData.zenPinnedEntry) {
tab.setAttribute('zen-pinned-entry', tabData.zenPinnedEntry);
}
if (tabData._zenPinnedInitialState) {
tab._zenPinnedInitialState = tabData._zenPinnedInitialState;
}

View File

@@ -73,7 +73,7 @@ export class nsZenSessionManager {
});
lazy.SessionStore.promiseAllWindowsRestored.then(() => {
delete this._migrationSpaceData;
delete this._migrationData;
});
}
@@ -88,14 +88,15 @@ export class nsZenSessionManager {
* This is only called once during the first run after updating
* to a version that uses the new session manager.
*/
async #getSpacesFromDBForMigration() {
async #getDataFromDBForMigration() {
try {
const { PlacesUtils } = ChromeUtils.importESModule(
'resource://gre/modules/PlacesUtils.sys.mjs'
);
const db = await PlacesUtils.promiseDBConnection();
const rows = await db.executeCached('SELECT * FROM zen_workspaces ORDER BY created_at ASC');
this._migrationSpaceData = rows.map((row) => ({
let data = {};
let rows = await db.execute('SELECT * FROM zen_workspaces ORDER BY created_at ASC');
data.spaces = rows.map((row) => ({
uuid: row.getResultByName('uuid'),
name: row.getResultByName('name'),
icon: row.getResultByName('icon'),
@@ -111,6 +112,22 @@ export class nsZenSessionManager {
}
: null,
}));
rows = await db.execute('SELECT * FROM zen_pins ORDER BY position ASC');
data.pins = rows.map((row) => ({
uuid: row.getResultByName('uuid'),
title: row.getResultByName('title'),
url: row.getResultByName('url'),
containerTabId: row.getResultByName('container_id'),
workspaceUuid: row.getResultByName('workspace_uuid'),
position: row.getResultByName('position'),
isEssential: Boolean(row.getResultByName('is_essential')),
isGroup: Boolean(row.getResultByName('is_group')),
parentUuid: row.getResultByName('folder_parent_uuid'),
editedTitle: Boolean(row.getResultByName('edited_title')),
folderIcon: row.getResultByName('folder_icon'),
isFolderCollapsed: Boolean(row.getResultByName('is_folder_collapsed')),
}));
this._migrationData = data;
} catch {
/* ignore errors during migration */
}
@@ -126,7 +143,7 @@ export class nsZenSessionManager {
let promises = [];
promises.push(this.#file.load());
if (!Services.prefs.getBoolPref(MIGRATION_PREF, false)) {
promises.push(this.#getSpacesFromDBForMigration());
promises.push(this.#getDataFromDBForMigration());
}
await Promise.all(promises);
} catch (e) {
@@ -149,12 +166,58 @@ export class nsZenSessionManager {
// gotten the opportunity to save the session yet.
if (!Services.prefs.getBoolPref(MIGRATION_PREF, false)) {
Services.prefs.setBoolPref(MIGRATION_PREF, true);
const pins = this._migrationData?.pins || [];
const applyTabsToObject = (obj) => {
// Lets add pins that don't exist yet in the sidebar object.
obj.tabs = obj.tabs || [];
obj.folders = obj.folders || [];
for (const pin of pins) {
let isGroup = pin.isGroup;
let object = {
pinned: true,
...(isGroup
? {
workspaceId: pin.workspaceUuid,
userIcon: pin.folderIcon,
name: pin.title,
parentId: pin.parentUuid,
collapsed: pin.isFolderCollapsed,
id: pin.uuid,
emptyTabIds: [],
}
: {
zenSyncId: pin.uuid,
groupId: pin.parentUuid,
entries: [{ url: pin.url, title: pin.title }],
zenStaticLabel: pin.editedTitle,
zenEssential: pin.isEssential,
userContextId: pin.containerTabId || 0,
zenWorkspace: pin.workspaceUuid,
title: pin.title,
}),
};
let items = isGroup ? obj.folders : obj.tabs;
let index = items.findIndex(
(tab) =>
tab.zenSyncId === pin.uuid || tab.zenPinnedId === pin.uuid || tab.id === pin.uuid
);
if (index === -1) {
// Add to the start of the tabs array to keep the order
items.unshift(object);
} else {
// Update existing tab data
items[index] = { ...object, ...items[index] };
}
}
};
this.#sidebar = {
...this.#sidebar,
spaces: this._migrationSpaceData || [],
spaces: this._migrationData?.spaces || [],
};
applyTabsToObject(this.#sidebar);
for (const winData of initialState?.windows || []) {
winData.spaces = this._migrationSpaceData || [];
winData.spaces = this._migrationData?.spaces || [];
applyTabsToObject(winData);
}
return;
}

View File

@@ -475,12 +475,13 @@ class nsZenPinnedTabManager extends nsZenDOMOperatedFeature {
});
document.getElementById('context_zen-edit-tab-icon').addEventListener('command', () => {
const tab = TabContextMenu.contextTab;
delete tab.zenStaticIcon;
gZenEmojiPicker
.open(tab.iconImage, { emojiAsSVG: true })
.then((icon) => {
if (icon) {
tab.zenStaticIcon = icon;
} else {
delete tab.zenStaticIcon;
}
gBrowser.setIcon(tab, icon);
lazy.TabStateCache.update(tab.permanentKey, {