refactor bookmarks.js

This commit is contained in:
eyedeekay
2025-01-14 15:30:04 -05:00
parent 81db1dde4f
commit 0c9f5fefda
2 changed files with 227 additions and 158 deletions

View File

@ -1,142 +1,210 @@
async function createI2PToolbar(bookmarkToolbar) {
const ibbt = await browser.bookmarks.search("I2P Toolbar");
/**
* @fileoverview I2P Bookmark Manager
* Handles bookmark creation and management for I2P extension toolbar
*/
async function onToolbarCreated(node) {
const ibt = await browser.bookmarks.search("I2P Toolbar");
await bookmarks(ibt[0]);
}
async function setupDir(ibbt) {
if (!ibbt.length) {
const createBookmark = await browser.bookmarks.create({
title: "I2P Toolbar",
parentId: bookmarkToolbar.id,
});
await onToolbarCreated(createBookmark);
}
}
await setupDir(ibbt);
}
async function bookmarks(bookmarkToolbar) {
const controlHost = control_host();
const controlPort = control_port();
async function createBookmark({ url, title, parentId }) {
const createRhizomeBookmark = await browser.bookmarks.create({
url,
title,
parentId,
});
console.log("Bookmarked", createRhizomeBookmark);
}
async function createHomeBookmark() {
const bookmarkItems = await browser.bookmarks.search({
// Constants for bookmark configuration
const BOOKMARK_CONFIG = {
TOOLBAR_NAME: "I2P Toolbar",
DEFAULT_BOOKMARKS: [
{
title: "I2P Extension Home Page",
});
if (!bookmarkItems.length) {
await createBookmark({
url: browser.runtime.getURL("home.html"),
title: "I2P Extension Home Page",
parentId: bookmarkToolbar.id,
});
}
}
async function createTorrentBookmark() {
const bookmarkItems = await browser.bookmarks.search({
getUrl: () => browser.runtime.getURL("home.html"),
},
{
title: "Bittorrent",
});
if (!bookmarkItems.length) {
await createBookmark({
url: `http://${controlHost}:${controlPort}/i2psnark`,
title: "Bittorrent",
parentId: bookmarkToolbar.id,
});
}
}
async function createConsoleBookmark() {
const bookmarkItems = await browser.bookmarks.search({
title: "I2P Console",
});
if (!bookmarkItems.length) {
await createBookmark({
url: `http://${controlHost}:${controlPort}/home`,
title: "I2P Console",
parentId: bookmarkToolbar.id,
});
}
}
async function createMailBookmark() {
const bookmarkItems = await browser.bookmarks.search({
title: "Web Mail",
});
if (!bookmarkItems.length) {
await createBookmark({
url: `http://${controlHost}:${controlPort}/webmail`,
title: "Web Mail",
parentId: bookmarkToolbar.id,
});
}
}
async function createI2PTunnelBookmark() {
const bookmarkItems = await browser.bookmarks.search({
getUrl: (host, port) => `http://${host}:${port}/i2psnark`,
},
{
title: "Hidden Services Manager",
});
if (!bookmarkItems.length) {
await createBookmark({
url: `http://${controlHost}:${controlPort}/i2ptunnel`,
title: "Hidden Services Manager",
parentId: bookmarkToolbar.id,
});
getUrl: (host, port) => `http://${host}:${port}/i2ptunnel`,
},
{
title: "Web Mail",
getUrl: (host, port) => `http://${host}:${port}/webmail`,
},
{
title: "I2P Console",
getUrl: (host, port) => `http://${host}:${port}/home`,
},
],
};
/**
* Bookmark Manager class for handling I2P bookmarks
*/
class I2PBookmarkManager {
constructor() {
this.controlHost = control_host();
this.controlPort = control_port();
}
/**
* Creates a bookmark with error handling
* @param {Object} params Bookmark parameters
* @return {Promise<browser.bookmarks.BookmarkTreeNode>}
*/
async createBookmark({ url, title, parentId }) {
try {
const bookmark = await browser.bookmarks.create({ url, title, parentId });
console.info("Created bookmark:", title);
return bookmark;
} catch (error) {
console.error(`Failed to create bookmark ${title} :`, error);
throw error;
}
}
await createHomeBookmark();
await createTorrentBookmark();
await createI2PTunnelBookmark();
await createMailBookmark();
await createConsoleBookmark();
/**
* Creates the I2P toolbar folder
* @param {browser.bookmarks.BookmarkTreeNode} toolbar Parent toolbar node
* @return {Promise<browser.bookmarks.BookmarkTreeNode>}
*/
async createToolbarFolder(toolbar) {
try {
const existing = await browser.bookmarks.search(
BOOKMARK_CONFIG.TOOLBAR_NAME
);
if (existing.length) {
return existing[0];
}
defaultSettings.bookmarks_state = true;
const folder = await this.createBookmark({
title: BOOKMARK_CONFIG.TOOLBAR_NAME,
parentId: toolbar.id,
});
await this.populateToolbar(folder);
return folder;
} catch (error) {
console.error("Failed to create toolbar folder:", error);
throw error;
}
}
/**
* Creates a single default bookmark if it doesn't exist
* @param {Object} bookmark Bookmark configuration
* @param {string} parentId Parent folder ID
*/
async createDefaultBookmark(bookmark, parentId) {
try {
const existing = await browser.bookmarks.search({
title: bookmark.title,
});
if (!existing.length) {
await this.createBookmark({
url: bookmark.getUrl(this.controlHost, this.controlPort),
title: bookmark.title,
parentId,
});
}
} catch (error) {
console.error(
`Failed to create default bookmark ${bookmark.title}:`,
error
);
}
}
/**
* Populates toolbar with default bookmarks
* @param {browser.bookmarks.BookmarkTreeNode} toolbar Toolbar folder node
*/
async populateToolbar(toolbar) {
try {
await Promise.all(
BOOKMARK_CONFIG.DEFAULT_BOOKMARKS.map((bookmark) =>
this.createDefaultBookmark(bookmark, toolbar.id)
)
);
await this.updateBookmarkState(true);
} catch (error) {
console.error("Failed to populate toolbar:", error);
}
}
/**
* Updates bookmark state in storage
* @param {boolean} state New bookmark state
*/
async updateBookmarkState(state) {
try {
await browser.storage.local.set({ bookmarks_state: state });
if (typeof defaultSettings !== "undefined") {
defaultSettings.bookmarks_state = state;
}
} catch (error) {
console.error("Failed to update bookmark state:", error);
}
}
/**
* Initializes bookmark setup
* @returns {Promise<void>}
*/
async initialize() {
try {
const platform = await browser.runtime.getPlatformInfo();
if (platform.os === "android") {
console.info("Skipping bookmark setup on Android");
return;
}
const toolbars = await browser.bookmarks.search({ query: "Toolbar" });
if (!toolbars.length) {
throw new Error("Browser toolbar not found");
}
await this.createToolbarFolder(toolbars[0]);
} catch (error) {
console.error("Bookmark initialization failed:", error);
}
}
/**
* Checks if bookmarks need to be initialized
* @param {Object} state Current bookmark state
*/
async checkInitialization(state = {}) {
if (!state.bookmarks_state) {
await this.initialize();
}
}
}
async function bookmarksSetup() {
const gettingInfo = await browser.runtime.getPlatformInfo();
if (gettingInfo.os === "android") {
// Singleton instance
const bookmarkManager = new I2PBookmarkManager();
/**
* Initialize bookmarks system
*/
async function initializeBookmarks() {
if (!browser?.windows) {
console.warn("Browser windows API not available");
return;
}
const bookmarkToolbar = await browser.bookmarks.search({
query: "Toolbar",
});
await createI2PToolbar(bookmarkToolbar[0]);
}
function conditionalBookmarksSetup(obj) {
console.log("(bookmarks) state", obj.bookmarks_state);
if (obj.bookmarks_state == false) {
bookmarksSetup();
}
if (obj.bookmarks_state == undefined) {
bookmarksSetup();
try {
const state = await browser.storage.local.get("bookmarks_state");
await bookmarkManager.checkInitialization(state);
} catch (error) {
console.error("Failed to initialize bookmarks:", error);
await bookmarkManager.initialize();
}
}
if (browser != null) {
if (browser.windows != undefined) {
let gettingStorage = browser.storage.local.get("bookmarks_state");
gettingStorage.then(conditionalBookmarksSetup, bookmarksSetup);
// Setup event listeners
document.addEventListener("DOMContentLoaded", () => {
const bookmarksButton = document.getElementById("bookmarksButton");
if (bookmarksButton) {
bookmarksButton.addEventListener("click", () =>
bookmarkManager.initialize()
);
}
}
});
const bookmarksButton = document.getElementById("bookmarksButton");
if (bookmarksButton != null) {
bookmarksButton.addEventListener("click", bookmarksSetup);
// Initialize if browser API is available
if (browser) {
initializeBookmarks();
}

View File

@ -5,25 +5,26 @@
// Constants
const UI_STRINGS = {
TITLE_PREFACE: chrome.i18n.getMessage('titlePreface'),
API_ERROR_MESSAGE: 'browser.contextualIdentities not available. Check that the privacy.userContext.enabled pref is set to true, and reload the add-on.',
NO_IDENTITIES_MESSAGE: 'No identities returned from the API.'
TITLE_PREFACE: chrome.i18n.getMessage("titlePreface"),
API_ERROR_MESSAGE:
"browser.contextualIdentities not available. Check that the privacy.userContext.enabled pref is set to true, and reload the add-on.",
NO_IDENTITIES_MESSAGE: "No identities returned from the API.",
};
const TAB_ACTIONS = {
NEW_TAB: 'new-i2p browser tab',
CLOSE_ALL: 'close-all i2p browser tabs'
NEW_TAB: "new-i2p browser tab",
CLOSE_ALL: "close-all i2p browser tabs",
};
const TAB_OPTIONS = [
{
text: 'New I2P Browser Tab',
action: TAB_ACTIONS.NEW_TAB
text: "New I2P Browser Tab",
action: TAB_ACTIONS.NEW_TAB,
},
{
text: 'Close All I2P Browser Tabs',
action: TAB_ACTIONS.CLOSE_ALL
}
text: "Close All I2P Browser Tabs",
action: TAB_ACTIONS.CLOSE_ALL,
},
];
/**
@ -31,7 +32,7 @@ const TAB_OPTIONS = [
* @param {Error} error - Browser operation error
*/
function handleError(error) {
console.error('Container operation failed:', error);
console.error("Container operation failed:", error);
}
/**
@ -43,10 +44,10 @@ async function createContainerTab(windowInfo, cookieStoreId) {
try {
await browser.tabs.create({
windowId: windowInfo.id,
url: 'about:blank',
cookieStoreId: cookieStoreId
url: "about:blank",
cookieStoreId: cookieStoreId,
});
console.info(`Created container tab in window: ${windowInfo.id}`);
console.info(`Created container tab in window : ${windowInfo.id}`);
} catch (error) {
handleError(error);
}
@ -69,11 +70,11 @@ async function handleContainerAction(event) {
case TAB_ACTIONS.CLOSE_ALL:
const tabs = await browser.tabs.query({ cookieStoreId: identity });
await browser.tabs.remove(tabs.map(tab => tab.id));
await browser.tabs.remove(tabs.map((tab) => tab.id));
break;
default:
console.warn('Unknown container action:', action);
console.warn("Unknown container action:", action);
}
} catch (error) {
handleError(error);
@ -86,18 +87,18 @@ async function handleContainerAction(event) {
* @param {Object} identity - Container identity
*/
function createContainerOptions(parentNode, identity) {
TAB_OPTIONS.forEach(option => {
const link = document.createElement('a');
TAB_OPTIONS.forEach((option) => {
const link = document.createElement("a");
Object.assign(link, {
href: '#',
href: "#",
innerText: option.text,
dataset: {
action: option.action,
identity: identity.cookieStoreId
}
identity: identity.cookieStoreId,
},
});
link.addEventListener('click', handleContainerAction);
link.addEventListener("click", handleContainerAction);
parentNode.appendChild(link);
});
}
@ -108,15 +109,15 @@ function createContainerOptions(parentNode, identity) {
* @returns {HTMLElement}
*/
function createIdentityElement(identity) {
const row = document.createElement('div');
const span = document.createElement('div');
span.className = 'identity';
const row = document.createElement("div");
const span = document.createElement("div");
span.className = "identity";
span.innerText = identity.name;
row.appendChild(span);
createContainerOptions(row, identity);
return row;
}
@ -132,7 +133,7 @@ async function initializeContainerUI(containerList) {
try {
const identities = await browser.contextualIdentities.query({
name: UI_STRINGS.TITLE_PREFACE
name: UI_STRINGS.TITLE_PREFACE,
});
if (!identities.length) {
@ -140,10 +141,10 @@ async function initializeContainerUI(containerList) {
return;
}
identities.forEach(identity => {
identities.forEach((identity) => {
const element = createIdentityElement(identity);
containerList.appendChild(element);
console.debug('Added container identity:', identity.name);
console.debug("Added container identity:", identity.name);
});
} catch (error) {
handleError(error);
@ -152,9 +153,9 @@ async function initializeContainerUI(containerList) {
}
// Initialize container management
const identityList = document.getElementById('identity-list');
const identityList = document.getElementById("identity-list");
if (identityList) {
initializeContainerUI(identityList);
} else {
console.error('Identity list container not found');
}
console.error("Identity list container not found");
}