mirror of
https://github.com/zen-browser/desktop.git
synced 2026-07-27 10:36:21 +00:00
Added workspace selector on bookmarks create/edit modal, added table for storing relationships between workspaces and bookmarks.
This commit is contained in:
@@ -13,6 +13,13 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
};
|
||||
_hoveringSidebar = false;
|
||||
_lastScrollTime = 0;
|
||||
bookmarkMenus = [
|
||||
"PlacesToolbar",
|
||||
"bookmarks-menu-button",
|
||||
"BMB_bookmarksToolbar",
|
||||
"BMB_unsortedBookmarks",
|
||||
"BMB_mobileBookmarks"
|
||||
];
|
||||
|
||||
async init() {
|
||||
if (!this.shouldHaveWorkspaces) {
|
||||
@@ -61,6 +68,11 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
Services.obs.addObserver(this, 'weave:engine:sync:finish');
|
||||
Services.obs.addObserver(async function observe(subject) {
|
||||
this._workspaceBookmarksCache = null;
|
||||
await this.workspaceBookmarks();
|
||||
this._invalidateBookmarkContainers();
|
||||
}.bind(this), "workspace-bookmarks-updated");
|
||||
}
|
||||
|
||||
initializeWorkspaceNavigation() {
|
||||
@@ -128,7 +140,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
// Change workspace based on scroll direction
|
||||
const direction = event.deltaX > 0 ? -1 : 1;
|
||||
const direction = event.deltaX > 0 ? 1 : -1;
|
||||
await this.changeWorkspaceShortcut(direction);
|
||||
this._lastScrollTime = currentTime;
|
||||
}, { passive: true });
|
||||
@@ -320,6 +332,21 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
return this._workspaceCache;
|
||||
}
|
||||
|
||||
async workspaceBookmarks() {
|
||||
if (this._workspaceBookmarksCache) {
|
||||
return this._workspaceBookmarksCache;
|
||||
}
|
||||
|
||||
const [bookmarks, lastChangeTimestamp] = await Promise.all([
|
||||
ZenWorkspaceBookmarksStorage.getBookmarkGuidsByWorkspace(),
|
||||
ZenWorkspaceBookmarksStorage.getLastChangeTimestamp(),
|
||||
]);
|
||||
|
||||
this._workspaceBookmarksCache = { bookmarks, lastChangeTimestamp };
|
||||
|
||||
return this._workspaceCache;
|
||||
}
|
||||
|
||||
async onWorkspacesEnabledChanged() {
|
||||
if (this.workspaceEnabled) {
|
||||
throw Error("Shoud've had reloaded the window");
|
||||
@@ -339,6 +366,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
if (this.workspaceEnabled) {
|
||||
this._initializeWorkspaceCreationIcons();
|
||||
this._initializeWorkspaceTabContextMenus();
|
||||
await this.workspaceBookmarks();
|
||||
window.addEventListener('TabBrowserInserted', this.onTabBrowserInserted.bind(this));
|
||||
await SessionStore.promiseInitialized;
|
||||
let workspaces = await this._workspaces();
|
||||
@@ -754,8 +782,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
|
||||
if(clearCache) {
|
||||
browser.ZenWorkspaces._workspaceCache = null;
|
||||
browser.ZenWorkspaces._bookmarkWorkspaceCache = null;
|
||||
}
|
||||
let workspaces = await browser.ZenWorkspaces._workspaces();
|
||||
await browser.ZenWorkspaces.workspaceBookmarks();
|
||||
workspaceList.innerHTML = '';
|
||||
workspaceList.parentNode.style.display = 'flex';
|
||||
if (workspaces.workspaces.length <= 0) {
|
||||
@@ -1252,16 +1282,23 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
}
|
||||
|
||||
// Reset bookmarks toolbar
|
||||
const placesToolbar = document.getElementById("PlacesToolbar");
|
||||
if (placesToolbar?._placesView) {
|
||||
placesToolbar._placesView.invalidateContainer(placesToolbar._placesView._resultNode);
|
||||
}
|
||||
// Reset bookmarks
|
||||
this._invalidateBookmarkContainers();
|
||||
|
||||
// Update workspace indicator
|
||||
await this.updateWorkspaceIndicator();
|
||||
}
|
||||
|
||||
_invalidateBookmarkContainers() {
|
||||
for (let i = 0, len = this.bookmarkMenus.length; i < len; i++) {
|
||||
const element = document.getElementById(this.bookmarkMenus[i]);
|
||||
if (element && element._placesView) {
|
||||
const placesView = element._placesView;
|
||||
placesView.invalidateContainer(placesView._resultNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async updateWorkspaceIndicator() {
|
||||
// Update current workspace indicator
|
||||
const currentWorkspace = await this.getActiveWorkspace();
|
||||
@@ -1534,12 +1571,24 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
|
||||
}
|
||||
|
||||
isBookmarkInAnotherWorkspace(bookmark) {
|
||||
let tags = bookmark.tags;
|
||||
// if any tag starts with "_workspace_id" and the workspace id doesnt match the active workspace id, return null
|
||||
if (tags) {
|
||||
for (let tag of tags.split(",")) {
|
||||
return !!(tag.startsWith("zen_workspace_") && this.getActiveWorkspaceFromCache()?.uuid !== tag.split("_")[2]);
|
||||
if (!this._workspaceBookmarksCache?.bookmarks) return false;
|
||||
const bookmarkGuid = bookmark.bookmarkGuid;
|
||||
const activeWorkspaceUuid = this.activeWorkspace;
|
||||
let isInActiveWorkspace = false;
|
||||
let isInOtherWorkspace = false;
|
||||
|
||||
for (const [workspaceUuid, bookmarkGuids] of Object.entries(this._workspaceBookmarksCache.bookmarks)) {
|
||||
if (bookmarkGuids.includes(bookmarkGuid)) {
|
||||
if (workspaceUuid === activeWorkspaceUuid) {
|
||||
isInActiveWorkspace = true;
|
||||
} else {
|
||||
isInOtherWorkspace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return true only if the bookmark is in another workspace and not in the active one
|
||||
return isInOtherWorkspace && !isInActiveWorkspace;
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -2,6 +2,8 @@ var ZenWorkspacesStorage = {
|
||||
async init() {
|
||||
console.log('ZenWorkspacesStorage: Initializing...');
|
||||
await this._ensureTable();
|
||||
await ZenWorkspaceBookmarksStorage.init();
|
||||
ZenWorkspaces._delayedStartup();
|
||||
},
|
||||
|
||||
async _ensureTable() {
|
||||
@@ -64,7 +66,6 @@ var ZenWorkspacesStorage = {
|
||||
await ZenWorkspacesStorage.migrateWorkspacesFromJSON();
|
||||
}
|
||||
|
||||
ZenWorkspaces._delayedStartup();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -405,3 +406,152 @@ var ZenWorkspacesStorage = {
|
||||
this._notifyWorkspacesChanged("zen-workspace-updated", Array.from(changedUUIDs));
|
||||
},
|
||||
};
|
||||
|
||||
// Integration of workspace-specific bookmarks into Places
|
||||
var ZenWorkspaceBookmarksStorage = {
|
||||
async init() {
|
||||
await this._ensureTable();
|
||||
},
|
||||
|
||||
async _ensureTable() {
|
||||
await PlacesUtils.withConnectionWrapper('ZenWorkspaceBookmarksStorage.init', async (db) => {
|
||||
// Create table using GUIDs instead of IDs
|
||||
await db.execute(`
|
||||
CREATE TABLE IF NOT EXISTS zen_bookmarks_workspaces (
|
||||
id INTEGER PRIMARY KEY,
|
||||
bookmark_guid TEXT NOT NULL,
|
||||
workspace_uuid TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
updated_at INTEGER NOT NULL,
|
||||
UNIQUE(bookmark_guid, workspace_uuid),
|
||||
FOREIGN KEY(workspace_uuid) REFERENCES zen_workspaces(uuid) ON DELETE CASCADE,
|
||||
FOREIGN KEY(bookmark_guid) REFERENCES moz_bookmarks(guid) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// Create index for fast lookups
|
||||
await db.execute(`
|
||||
CREATE INDEX IF NOT EXISTS idx_bookmarks_workspaces_lookup
|
||||
ON zen_bookmarks_workspaces(workspace_uuid, bookmark_guid)
|
||||
`);
|
||||
|
||||
// Add changes tracking table
|
||||
await db.execute(`
|
||||
CREATE TABLE IF NOT EXISTS zen_bookmarks_workspaces_changes (
|
||||
id INTEGER PRIMARY KEY,
|
||||
bookmark_guid TEXT NOT NULL,
|
||||
workspace_uuid TEXT NOT NULL,
|
||||
change_type TEXT NOT NULL,
|
||||
timestamp INTEGER NOT NULL,
|
||||
UNIQUE(bookmark_guid, workspace_uuid),
|
||||
FOREIGN KEY(workspace_uuid) REFERENCES zen_workspaces(uuid) ON DELETE CASCADE,
|
||||
FOREIGN KEY(bookmark_guid) REFERENCES moz_bookmarks(guid) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// Create index for changes tracking
|
||||
await db.execute(`
|
||||
CREATE INDEX IF NOT EXISTS idx_bookmarks_workspaces_changes
|
||||
ON zen_bookmarks_workspaces_changes(bookmark_guid, workspace_uuid)
|
||||
`);
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the last change timestamp in the metadata table.
|
||||
* @param {Object} db - The database connection.
|
||||
*/
|
||||
async updateLastChangeTimestamp(db) {
|
||||
const now = Date.now();
|
||||
await db.execute(`
|
||||
INSERT OR REPLACE INTO moz_meta (key, value)
|
||||
VALUES ('zen_bookmarks_workspaces_last_change', :now)
|
||||
`, { now });
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the timestamp of the last change.
|
||||
* @returns {Promise<number>} The timestamp of the last change.
|
||||
*/
|
||||
async getLastChangeTimestamp() {
|
||||
const db = await PlacesUtils.promiseDBConnection();
|
||||
const result = await db.executeCached(`
|
||||
SELECT value FROM moz_meta WHERE key = 'zen_bookmarks_workspaces_last_change'
|
||||
`);
|
||||
return result.length ? parseInt(result[0].getResultByName('value'), 10) : 0;
|
||||
},
|
||||
|
||||
async getBookmarkWorkspaces(bookmarkGuid) {
|
||||
const db = await PlacesUtils.promiseDBConnection();
|
||||
|
||||
const rows = await db.execute(`
|
||||
SELECT workspace_uuid
|
||||
FROM zen_bookmarks_workspaces
|
||||
WHERE bookmark_guid = :bookmark_guid
|
||||
`, { bookmark_guid: bookmarkGuid });
|
||||
|
||||
return rows.map(row => row.getResultByName("workspace_uuid"));
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all bookmark GUIDs organized by workspace UUID.
|
||||
* @returns {Promise<Object>} A dictionary with workspace UUIDs as keys and arrays of bookmark GUIDs as values.
|
||||
* @example
|
||||
* // Returns:
|
||||
* {
|
||||
* "workspace-uuid-1": ["bookmark-guid-1", "bookmark-guid-2"],
|
||||
* "workspace-uuid-2": ["bookmark-guid-3"]
|
||||
* }
|
||||
*/
|
||||
async getBookmarkGuidsByWorkspace() {
|
||||
const db = await PlacesUtils.promiseDBConnection();
|
||||
|
||||
const rows = await db.execute(`
|
||||
SELECT workspace_uuid, GROUP_CONCAT(bookmark_guid) as bookmark_guids
|
||||
FROM zen_bookmarks_workspaces
|
||||
GROUP BY workspace_uuid
|
||||
`);
|
||||
|
||||
const result = {};
|
||||
for (const row of rows) {
|
||||
const workspaceUuid = row.getResultByName("workspace_uuid");
|
||||
const bookmarkGuids = row.getResultByName("bookmark_guids");
|
||||
result[workspaceUuid] = bookmarkGuids ? bookmarkGuids.split(',') : [];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all changed bookmarks with their change types.
|
||||
* @returns {Promise<Object>} An object mapping bookmark+workspace pairs to their change data.
|
||||
*/
|
||||
async getChangedIDs() {
|
||||
const db = await PlacesUtils.promiseDBConnection();
|
||||
const rows = await db.execute(`
|
||||
SELECT bookmark_guid, workspace_uuid, change_type, timestamp
|
||||
FROM zen_bookmarks_workspaces_changes
|
||||
`);
|
||||
|
||||
const changes = {};
|
||||
for (const row of rows) {
|
||||
const key = `${row.getResultByName('bookmark_guid')}:${row.getResultByName('workspace_uuid')}`;
|
||||
changes[key] = {
|
||||
type: row.getResultByName('change_type'),
|
||||
timestamp: row.getResultByName('timestamp')
|
||||
};
|
||||
}
|
||||
return changes;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all recorded changes.
|
||||
*/
|
||||
async clearChangedIDs() {
|
||||
await PlacesUtils.withConnectionWrapper('ZenWorkspaceBookmarksStorage.clearChangedIDs', async (db) => {
|
||||
await db.execute(`DELETE FROM zen_bookmarks_workspaces_changes`);
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user