feat(workspaces): Use preferences to manage active workspace

This commit updates the workspaces system to use preferences to manage the active workspace, instead of storing the active state in each workspace object.

The following changes were made:

- **ZenWorkspaces.mjs:**
    - Removed the `used` property from workspace objects and replaced it with a preference (`zen.workspaces.active`) to store the active workspace ID.
    - Modified the `getActiveWorkspace` and `changeWorkspace` methods to use preferences instead of the `used` property.
    - Added a new `isWorkspaceActive` method to check if a workspace is active.
- **ZenWorkspacesStorage.mjs:**
    - Removed the `is_active` column from the `zen_workspaces` table.
    - Removed the `setActiveWorkspace` method as the active workspace is now managed by preferences.

This change simplifies the code and makes it easier to manage the active workspace across multiple browser windows and doesn't write to the database on every workspace change. Additionaly, it enables local active workspace selection when workspace sync is implemented.
This commit is contained in:
Kristijan Ribarić 2024-10-03 10:19:18 +02:00
parent 511281c688
commit 9bcb66c768
2 changed files with 43 additions and 53 deletions

View file

@ -45,7 +45,8 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
getActiveWorkspaceFromCache() { getActiveWorkspaceFromCache() {
try { try {
return this._workspaceCache.workspaces.find((workspace) => workspace.used); const activeWorkspaceId = Services.prefs.getStringPref("zen.workspaces.active", "");
return this._workspaceCache.workspaces.find((workspace) => workspace.uuid === activeWorkspaceId);
} catch (e) { } catch (e) {
return null; return null;
} }
@ -54,6 +55,19 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
async _workspaces() { async _workspaces() {
if (!this._workspaceCache) { if (!this._workspaceCache) {
this._workspaceCache = { workspaces: await ZenWorkspacesStorage.getWorkspaces() }; this._workspaceCache = { workspaces: await ZenWorkspacesStorage.getWorkspaces() };
// Get the active workspace ID from preferences
const activeWorkspaceId = Services.prefs.getStringPref("zen.workspaces.active", "");
if (activeWorkspaceId) {
const activeWorkspace = this._workspaceCache.workspaces.find(w => w.uuid === activeWorkspaceId);
// Set the active workspace ID to the first one if the one with selected id doesn't exist
if (!activeWorkspace) {
Services.prefs.setStringPref("zen.workspaces.active", this._workspaceCache.workspaces[0].uuid);
}
} else {
// Set the active workspace ID to the first one if active workspace doesn't exist
Services.prefs.setStringPref("zen.workspaces.active", this._workspaceCache.workspaces[0].uuid);
}
} }
return this._workspaceCache; return this._workspaceCache;
} }
@ -84,16 +98,14 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
if (workspaces.workspaces.length === 0) { if (workspaces.workspaces.length === 0) {
await this.createAndSaveWorkspace('Default Workspace', true); await this.createAndSaveWorkspace('Default Workspace', true);
} else { } else {
let activeWorkspace = workspaces.workspaces.find((workspace) => workspace.used); let activeWorkspace = await this.getActiveWorkspace();
if (!activeWorkspace) { if (!activeWorkspace) {
activeWorkspace = workspaces.workspaces.find((workspace) => workspace.default); activeWorkspace = workspaces.workspaces.find((workspace) => workspace.default);
activeWorkspace.used = true; Services.prefs.setStringPref("zen.workspaces.active", activeWorkspace.uuid);
await this.saveWorkspaces();
} }
if (!activeWorkspace) { if (!activeWorkspace) {
activeWorkspace = workspaces.workspaces[0]; activeWorkspace = workspaces.workspaces[0];
activeWorkspace.used = true; Services.prefs.setStringPref("zen.workspaces.active", activeWorkspace.uuid);
await this.saveWorkspaces();
} }
this.changeWorkspace(activeWorkspace, true); this.changeWorkspace(activeWorkspace, true);
} }
@ -163,6 +175,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
async saveWorkspace(workspaceData) { async saveWorkspace(workspaceData) {
await ZenWorkspacesStorage.saveWorkspace(workspaceData); await ZenWorkspacesStorage.saveWorkspace(workspaceData);
this._workspaceCache = null; this._workspaceCache = null;
await this._propagateWorkspaceData();
await this._updateWorkspacesChangeContextMenu(); await this._updateWorkspacesChangeContextMenu();
} }
@ -178,21 +191,16 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
await this._updateWorkspacesChangeContextMenu(); await this._updateWorkspacesChangeContextMenu();
} }
async saveWorkspaces() { isWorkspaceActive(workspace) {
const activeWorkspaceId = Services.prefs.getStringPref("zen.workspaces.active", "");
return workspace.uuid === activeWorkspaceId;
}
async getActiveWorkspace() {
const workspaces = await this._workspaces(); const workspaces = await this._workspaces();
for (const workspace of workspaces.workspaces) { const activeWorkspaceId = Services.prefs.getStringPref("zen.workspaces.active", "");
await ZenWorkspacesStorage.saveWorkspace(workspace); return workspaces.workspaces.find(workspace => workspace.uuid === activeWorkspaceId);
}
this._workspaceCache = null;
} }
async unsafeSaveWorkspaces(workspaces) {
for (const workspace of workspaces.workspaces) {
await ZenWorkspacesStorage.saveWorkspace(workspace);
}
this._workspaceCache = workspaces;
}
// Workspaces dialog UI management // Workspaces dialog UI management
openSaveDialog() { openSaveDialog() {
@ -255,7 +263,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
element.className = 'subviewbutton'; element.className = 'subviewbutton';
element.setAttribute('tooltiptext', workspace.name); element.setAttribute('tooltiptext', workspace.name);
element.setAttribute('zen-workspace-id', workspace.uuid); element.setAttribute('zen-workspace-id', workspace.uuid);
if (workspace.used) { if (this.isWorkspaceActive(workspace)) {
element.setAttribute('active', 'true'); element.setAttribute('active', 'true');
} }
if (workspace.default) { if (workspace.default) {
@ -311,7 +319,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
}; };
browser.ZenWorkspaces._workspaceCache = null; browser.ZenWorkspaces._workspaceCache = null;
let workspaces = await browser.ZenWorkspaces._workspaces(); let workspaces = await browser.ZenWorkspaces._workspaces();
let activeWorkspace = workspaces.workspaces.find((workspace) => workspace.used); let activeWorkspace = await this.getActiveWorkspace();
currentContainer.innerHTML = ''; currentContainer.innerHTML = '';
workspaceList.innerHTML = ''; workspaceList.innerHTML = '';
workspaceList.parentNode.style.display = 'flex'; workspaceList.parentNode.style.display = 'flex';
@ -326,7 +334,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
currentContainer.appendChild(currentWorkspace); currentContainer.appendChild(currentWorkspace);
} }
for (let workspace of workspaces.workspaces) { for (let workspace of workspaces.workspaces) {
if (workspace.used) { if (this.isWorkspaceActive(workspace)) {
continue; continue;
} }
let workspaceElement = createWorkspaceElement(workspace); let workspaceElement = createWorkspaceElement(workspace);
@ -379,7 +387,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
button.className = 'subviewbutton'; button.className = 'subviewbutton';
button.setAttribute('tooltiptext', workspace.name); button.setAttribute('tooltiptext', workspace.name);
button.setAttribute('zen-workspace-id', workspace.uuid); button.setAttribute('zen-workspace-id', workspace.uuid);
if (workspace.used) { if (this.isWorkspaceActive(workspace)) {
button.setAttribute('active', 'true'); button.setAttribute('active', 'true');
} }
if (workspace.default) { if (workspace.default) {
@ -418,7 +426,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
if (!button) { if (!button) {
return; return;
} }
let activeWorkspace = (await browser.ZenWorkspaces._workspaces()).workspaces.find((workspace) => workspace.used); let activeWorkspace = await this.getActiveWorkspace();
if (activeWorkspace) { if (activeWorkspace) {
button.setAttribute('as-button', 'true'); button.setAttribute('as-button', 'true');
button.classList.add('toolbarbutton-1', 'zen-sidebar-action-button'); button.classList.add('toolbarbutton-1', 'zen-sidebar-action-button');
@ -562,11 +570,9 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
if (!this.workspaceEnabled) { if (!this.workspaceEnabled) {
return; return;
} }
let workspaces = await this._workspaces();
for (let workspace of workspaces.workspaces) { Services.prefs.setStringPref("zen.workspaces.active", window.uuid);
workspace.used = workspace.uuid === window.uuid;
}
await this.unsafeSaveWorkspaces(workspaces);
const shouldAllowPinnedTabs = this._shouldAllowPinTab; const shouldAllowPinnedTabs = this._shouldAllowPinTab;
await this.foreachWindowAsActive(async (browser) => { await this.foreachWindowAsActive(async (browser) => {
browser.ZenWorkspaces.tabContainer._invalidateCachedTabs(); browser.ZenWorkspaces.tabContainer._invalidateCachedTabs();
@ -608,8 +614,6 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
browser.document.getElementById('tabbrowser-tabs')._positionPinnedTabs(); browser.document.getElementById('tabbrowser-tabs')._positionPinnedTabs();
}); });
await ZenWorkspacesStorage.setActiveWorkspace(window.uuid);
await this.saveWorkspaces();
await this._propagateWorkspaceData(); await this._propagateWorkspaceData();
} }
@ -620,7 +624,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
menuPopup.innerHTML = ''; menuPopup.innerHTML = '';
const activeWorkspace = workspaces.workspaces.find((workspace) => workspace.used); const activeWorkspace = await this.getActiveWorkspace();
for (let workspace of workspaces.workspaces) { for (let workspace of workspaces.workspaces) {
const menuItem = document.createXULElement('menuitem'); const menuItem = document.createXULElement('menuitem');
@ -661,8 +665,8 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
if (tab.getAttribute('zen-workspace-id') || !this.workspaceEnabled) { if (tab.getAttribute('zen-workspace-id') || !this.workspaceEnabled) {
return; return;
} }
let workspaces = await this._workspaces();
let activeWorkspace = workspaces.workspaces.find((workspace) => workspace.used); let activeWorkspace = await this.getActiveWorkspace();
if (!activeWorkspace) { if (!activeWorkspace) {
return; return;
} }
@ -673,8 +677,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
let tab = gBrowser.getTabForBrowser(browser); let tab = gBrowser.getTabForBrowser(browser);
let workspaceID = tab.getAttribute('zen-workspace-id'); let workspaceID = tab.getAttribute('zen-workspace-id');
if (!workspaceID) { if (!workspaceID) {
let workspaces = await this._workspaces(); let activeWorkspace = await this.getActiveWorkspace();
let activeWorkspace = workspaces.workspaces.find((workspace) => workspace.used);
if (!activeWorkspace || tab.hasAttribute('hidden')) { if (!activeWorkspace || tab.hasAttribute('hidden')) {
return; return;
} }
@ -709,7 +712,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
defaultMenuItem.removeAttribute('disabled'); defaultMenuItem.removeAttribute('disabled');
} }
let openMenuItem = document.getElementById('context_zenOpenWorkspace'); let openMenuItem = document.getElementById('context_zenOpenWorkspace');
if (workspaces.workspaces.find((workspace) => workspace.uuid === this._contextMenuId).used) { if (workspaces.workspaces.find((workspace) => workspace.uuid === this._contextMenuId && this.isWorkspaceActive(workspace))) {
openMenuItem.setAttribute('disabled', 'true'); openMenuItem.setAttribute('disabled', 'true');
} else { } else {
openMenuItem.removeAttribute('disabled'); openMenuItem.removeAttribute('disabled');
@ -768,7 +771,7 @@ var ZenWorkspaces = new class extends ZenMultiWindowFeature {
async changeWorkspaceShortcut(offset = 1) { async changeWorkspaceShortcut(offset = 1) {
// Cycle through workspaces // Cycle through workspaces
let workspaces = await this._workspaces(); let workspaces = await this._workspaces();
let activeWorkspace = workspaces.workspaces.find((workspace) => workspace.used); let activeWorkspace = await this.getActiveWorkspace();
let workspaceIndex = workspaces.workspaces.indexOf(activeWorkspace); let workspaceIndex = workspaces.workspaces.indexOf(activeWorkspace);
// note: offset can be negative // note: offset can be negative
let nextWorkspace = workspaces.workspaces[(workspaceIndex + offset + workspaces.workspaces.length) % workspaces.workspaces.length]; let nextWorkspace = workspaces.workspaces[(workspaceIndex + offset + workspaces.workspaces.length) % workspaces.workspaces.length];

View file

@ -13,7 +13,6 @@ var ZenWorkspacesStorage = {
name TEXT NOT NULL, name TEXT NOT NULL,
icon TEXT, icon TEXT,
is_default INTEGER NOT NULL DEFAULT 0, is_default INTEGER NOT NULL DEFAULT 0,
is_active INTEGER NOT NULL DEFAULT 0,
container_id INTEGER, container_id INTEGER,
created_at INTEGER NOT NULL, created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL updated_at INTEGER NOT NULL
@ -27,9 +26,9 @@ var ZenWorkspacesStorage = {
const now = Date.now(); const now = Date.now();
await db.executeCached(` await db.executeCached(`
INSERT OR REPLACE INTO zen_workspaces ( INSERT OR REPLACE INTO zen_workspaces (
uuid, name, icon, is_default, is_active, container_id, created_at, updated_at uuid, name, icon, is_default, container_id, created_at, updated_at
) VALUES ( ) VALUES (
:uuid, :name, :icon, :is_default, :is_active, :container_id, :uuid, :name, :icon, :is_default, :container_id,
COALESCE((SELECT created_at FROM zen_workspaces WHERE uuid = :uuid), :now), COALESCE((SELECT created_at FROM zen_workspaces WHERE uuid = :uuid), :now),
:now :now
) )
@ -38,7 +37,6 @@ var ZenWorkspacesStorage = {
name: workspace.name, name: workspace.name,
icon: workspace.icon || null, icon: workspace.icon || null,
is_default: workspace.default ? 1 : 0, is_default: workspace.default ? 1 : 0,
is_active: workspace.used ? 1 : 0,
container_id: workspace.containerTabId || null, container_id: workspace.containerTabId || null,
now now
}); });
@ -50,13 +48,11 @@ var ZenWorkspacesStorage = {
const rows = await db.execute(` const rows = await db.execute(`
SELECT * FROM zen_workspaces ORDER BY created_at ASC SELECT * FROM zen_workspaces ORDER BY created_at ASC
`); `);
return rows.map(row => ({ return rows.map(row => ({
uuid: row.getResultByName("uuid"), uuid: row.getResultByName("uuid"),
name: row.getResultByName("name"), name: row.getResultByName("name"),
icon: row.getResultByName("icon"), icon: row.getResultByName("icon"),
default: !!row.getResultByName("is_default"), default: !!row.getResultByName("is_default"),
used: !!row.getResultByName("is_active"),
containerTabId: row.getResultByName("container_id") containerTabId: row.getResultByName("container_id")
})); }));
}, },
@ -69,15 +65,6 @@ var ZenWorkspacesStorage = {
}); });
}, },
async setActiveWorkspace(uuid) {
await PlacesUtils.withConnectionWrapper("ZenWorkspacesStorage.setActiveWorkspace", async db => {
await db.executeTransaction(async function() {
await db.execute(`UPDATE zen_workspaces SET is_active = 0`);
await db.execute(`UPDATE zen_workspaces SET is_active = 1 WHERE uuid = :uuid`, { uuid });
});
});
},
async setDefaultWorkspace(uuid) { async setDefaultWorkspace(uuid) {
await PlacesUtils.withConnectionWrapper("ZenWorkspacesStorage.setDefaultWorkspace", async db => { await PlacesUtils.withConnectionWrapper("ZenWorkspacesStorage.setDefaultWorkspace", async db => {
await db.executeTransaction(async function() { await db.executeTransaction(async function() {