theseus/settings-preload.js

61 lines
4.1 KiB
JavaScript
Raw Normal View History

const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("cfg", {
get: () => ipcRenderer.invoke("settings-get"),
set: (key, value) => ipcRenderer.invoke("settings-set", key, value),
engines: () => ipcRenderer.invoke("search-engines"),
addEngine: (eng) => ipcRenderer.invoke("add-engine", eng),
removeEngine: (id) => ipcRenderer.invoke("remove-engine", id),
setEngineEnabled: (id, on) => ipcRenderer.invoke("set-engine-enabled", id, on),
setEngineOrder: (ids) => ipcRenderer.invoke("set-engine-order", ids),
Theseus: shield green polish, picker→Search section, toggle-vs-remove Three follow-up asks from the previous ship: 1. Shield "secure" colour bumped from #4fd1a5 (mint) to #3fb950 — the GitHub-style saturated green, matches the +N/-N diff colour the user pointed at as reference. 2. Engine-picker "Search settings…" now opens the Search section directly instead of General. New IPC channel `focus-section` fires from main after picker-open-settings, carried through settings-preload as `onFocusSection`, and the settings.html sidebar handler exposes showSection(sec) so any section can be focused programmatically. Works for both a fresh settings tab (fires on did-finish-load) and an already-open one (fires immediately). 3. Toggle no longer removes an engine from the list. Two-tier state: INSTALLED (visible in the Settings list) and ENABLED (toggled on in the toolbar dropdown). Toggling off keeps the row visible with an .off class (dimmed 55%). Right-click any row → new context menu with "Remove from list" is what actually removes an engine (built-ins go back to the catalog, customs are dropped entirely). Model changes: - New settings.installedEngines persistent array (defaults to DEFAULT_ENABLED). enabledEngines becomes a subset of installedEngines. - isInstalled(id) helper; allEngines() carries `installed: bool` alongside `enabled`. - New IPC `remove-from-list` (right-click action); exposed as removeFromList in settings-preload. - set-engine-enabled now also INSTALLS when enabling (the catalog "+ Add" flow), preserves installed state when disabling. - add-engine (custom URL) auto-adds the new id to enabledEngines too. - remove-engine (custom delete) prunes from enabledEngines as well. - Never-empty invariant kept: enabledEngines falls back to ["duckduckgo"] if everything gets removed. Settings UI: - Enabled list shows all INSTALLED engines (was: only enabled), rendered with toggle reflecting enabled state; rows carry data-builtin so the context menu picks the right remove IPC. - Catalog panel and Discover-more pane filter on !installed instead of !enabled — a toggled-off engine stays in the enabled list, not here. - Ctxmenu is a floating .ctxmenu div; closes on outside click / Escape. - .eng.off dims the row and mutes the name colour. Preview harness stubs updated to include the `installed` field on every engine + `removeFromList` and `onFocusSection` no-op stubs so _settings-preview.html renders the new UI accurately.
2026-08-06 01:41:31 +02:00
removeFromList: (id) => ipcRenderer.invoke("remove-from-list", id),
// Storage: wipe browsing data on demand. Pass any subset of
// { cookies, cache, storage, history }.
clearBrowsingData: (opts) => ipcRenderer.invoke("clear-browsing-data", opts),
// Password vault. All calls return { ok, ... } | { ok: false, err }.
// Renderers never see the seed / vault key / master password past setup/
// unlock; get() returns plaintext only in explicit response to a user click.
pwStatus: () => ipcRenderer.invoke("password-status"),
pwSetup: (masterPassword, seedSource) => ipcRenderer.invoke("password-setup", { masterPassword, seedSource }),
pwUnlock: (masterPassword) => ipcRenderer.invoke("password-unlock", masterPassword),
pwLock: () => ipcRenderer.invoke("password-lock"),
pwList: () => ipcRenderer.invoke("password-list"),
pwGet: (id) => ipcRenderer.invoke("password-get", id),
pwAdd: (entry) => ipcRenderer.invoke("password-add", entry),
pwUpdate: (id, patch) => ipcRenderer.invoke("password-update", id, patch),
pwRemove: (id) => ipcRenderer.invoke("password-remove", id),
pwGenerate: (spec) => ipcRenderer.invoke("password-generate", spec),
Theseus: shield green polish, picker→Search section, toggle-vs-remove Three follow-up asks from the previous ship: 1. Shield "secure" colour bumped from #4fd1a5 (mint) to #3fb950 — the GitHub-style saturated green, matches the +N/-N diff colour the user pointed at as reference. 2. Engine-picker "Search settings…" now opens the Search section directly instead of General. New IPC channel `focus-section` fires from main after picker-open-settings, carried through settings-preload as `onFocusSection`, and the settings.html sidebar handler exposes showSection(sec) so any section can be focused programmatically. Works for both a fresh settings tab (fires on did-finish-load) and an already-open one (fires immediately). 3. Toggle no longer removes an engine from the list. Two-tier state: INSTALLED (visible in the Settings list) and ENABLED (toggled on in the toolbar dropdown). Toggling off keeps the row visible with an .off class (dimmed 55%). Right-click any row → new context menu with "Remove from list" is what actually removes an engine (built-ins go back to the catalog, customs are dropped entirely). Model changes: - New settings.installedEngines persistent array (defaults to DEFAULT_ENABLED). enabledEngines becomes a subset of installedEngines. - isInstalled(id) helper; allEngines() carries `installed: bool` alongside `enabled`. - New IPC `remove-from-list` (right-click action); exposed as removeFromList in settings-preload. - set-engine-enabled now also INSTALLS when enabling (the catalog "+ Add" flow), preserves installed state when disabling. - add-engine (custom URL) auto-adds the new id to enabledEngines too. - remove-engine (custom delete) prunes from enabledEngines as well. - Never-empty invariant kept: enabledEngines falls back to ["duckduckgo"] if everything gets removed. Settings UI: - Enabled list shows all INSTALLED engines (was: only enabled), rendered with toggle reflecting enabled state; rows carry data-builtin so the context menu picks the right remove IPC. - Catalog panel and Discover-more pane filter on !installed instead of !enabled — a toggled-off engine stays in the enabled list, not here. - Ctxmenu is a floating .ctxmenu div; closes on outside click / Escape. - .eng.off dims the row and mutes the name colour. Preview harness stubs updated to include the `installed` field on every engine + `removeFromList` and `onFocusSection` no-op stubs so _settings-preview.html renders the new UI accurately.
2026-08-06 01:41:31 +02:00
// Main asks settings to jump to a specific sidebar section (e.g. from the
// engine picker's "Search settings…" click). Emits the section id string.
onFocusSection: (cb) => ipcRenderer.on("focus-section", (_e, section) => cb(section)),
// Collision-mode: BCNR/ICANN policy + per-name/per-TLD overrides
collisionState: () => ipcRenderer.invoke("collision-state"),
setCollisionPolicy: (p) => ipcRenderer.invoke("collision-set-policy", p),
resetCollisions: () => ipcRenderer.invoke("collision-reset"),
ariadneState: () => ipcRenderer.invoke("ariadne-state"),
ariadneToggle: (on) => ipcRenderer.invoke("ariadne-toggle", !!on),
ariadneInstall: () => ipcRenderer.invoke("ariadne-install"),
ariadneUpdate: () => ipcRenderer.invoke("ariadne-update"),
ariadneUninstall: () => ipcRenderer.invoke("ariadne-uninstall"),
// Manual "Check for updates" — un-dismisses any existing chip and re-
// fetches the release manifest. Returns { updateAvailable, currentVersion }.
recheckUpdate: () => ipcRenderer.invoke("recheck-update"),
appVersion: () => ipcRenderer.invoke("app-version"),
restartApp: () => ipcRenderer.invoke("app-restart"),
Theseus: add-on framework MVP + Notepad reference add-on New subsystem for extending Theseus with folders on disk. Each add-on lives at <userData>/addons/<id>/ with an addon.json manifest and a CommonJS entry that exports activate(api). Nothing about a private add-on ships in the public installer - drop the folder, restart, it's live. Bundled reference add-ons ride in the packaged app under resources/bundled-addons/ and are seeded into <userData>/addons/ on first boot; the framework treats seeded and drop-in add-ons the same. Files: - addons-host.js Loader + api.registerSidebarPanel() + per- addon storage on <userData>/addons-data/. Kept at the CommonJS-scoped top level (lib/ is ESM-scoped via its own package.json). - sidebar-preload.js Runs in every sidebar panel. Exposes window.silentmode.storage.{get,set,all} + onVisibility. Main-side handlers derive the add-on id from the sender file:// URL, so a panel can only touch its own store. - bundled-addons/notepad/ Reference add-on: addon.json, index.js, note.html. Autosaving textarea with char / word count. main.js: - Extension point: sidebar-panel. One right-anchored WebContentsView (SIDEBAR_W=340) hosts the current panel; layout() shrinks the tab views by the sidebar width when visible. First registered panel wins for MVP; picker for multiple panels lands later. - initAddons() at app.whenReady(): seedBundledAddons, then AddonHost.discoverAndActivate. - IPC surface: sidebar-toggle / sidebar-open / sidebar-close / sidebar-state, addons-list / addons-set-enabled / addons-reveal / addons-open-dir / addons-reload, and origin-gated addon-storage-get/set/all. - Settings gains `disabledAddons: []` — off-toggled ids persist and the loader honours them without a restart (discoverAndActivate runs again on toggle). chrome.html: toolbar sidebar-toggle button, hidden until at least one add-on has registered a sidebar panel. settings.html: new "Add-ons" section under privacy. Lists installed add-ons with icon / name / version / description / capabilities; per-add-on enable/disable toggle + Show folder button; page-level Reload and Open add-ons folder buttons; warning note about the trust model. package.json: build.files gains sidebar-preload.js + addons-host.js. extraResources gains bundled-addons/ so the packaged app carries the reference notepad for the first-boot seed. Verified: `npm start` boots, addons-host discovers the notepad, activates it, registers one sidebar panel. Log confirms "1 installed, 1 enabled, 1 sidebar panels". Actual sidebar rendering + notepad UI need clicked-through validation on a real install. Not shipped yet - deploy still blocked on the fail2ban VPS SSH ban. Ships as 0.2.0 once SSH clears (this is a new subsystem, not a fix).
2026-08-31 13:51:08 +02:00
// Add-ons management (Settings > Add-ons tab).
listAddons: () => ipcRenderer.invoke("addons-list"),
setAddonEnabled: (id, enabled) => ipcRenderer.invoke("addons-set-enabled", id, !!enabled),
revealAddon: (folder) => ipcRenderer.invoke("addons-reveal", folder),
// Delete a non-bundled extension's folder (Settings Extensions Remove).
removeAddon: (id) => ipcRenderer.invoke("addons-remove", id),
// Install a staged signed update now (Settings Extensions "Update to vX"); no id = every staged extension.
applyStagedAddons: (id) => ipcRenderer.invoke("addons-apply-staged", typeof id === "string" ? id : undefined),
Theseus: add-on framework MVP + Notepad reference add-on New subsystem for extending Theseus with folders on disk. Each add-on lives at <userData>/addons/<id>/ with an addon.json manifest and a CommonJS entry that exports activate(api). Nothing about a private add-on ships in the public installer - drop the folder, restart, it's live. Bundled reference add-ons ride in the packaged app under resources/bundled-addons/ and are seeded into <userData>/addons/ on first boot; the framework treats seeded and drop-in add-ons the same. Files: - addons-host.js Loader + api.registerSidebarPanel() + per- addon storage on <userData>/addons-data/. Kept at the CommonJS-scoped top level (lib/ is ESM-scoped via its own package.json). - sidebar-preload.js Runs in every sidebar panel. Exposes window.silentmode.storage.{get,set,all} + onVisibility. Main-side handlers derive the add-on id from the sender file:// URL, so a panel can only touch its own store. - bundled-addons/notepad/ Reference add-on: addon.json, index.js, note.html. Autosaving textarea with char / word count. main.js: - Extension point: sidebar-panel. One right-anchored WebContentsView (SIDEBAR_W=340) hosts the current panel; layout() shrinks the tab views by the sidebar width when visible. First registered panel wins for MVP; picker for multiple panels lands later. - initAddons() at app.whenReady(): seedBundledAddons, then AddonHost.discoverAndActivate. - IPC surface: sidebar-toggle / sidebar-open / sidebar-close / sidebar-state, addons-list / addons-set-enabled / addons-reveal / addons-open-dir / addons-reload, and origin-gated addon-storage-get/set/all. - Settings gains `disabledAddons: []` — off-toggled ids persist and the loader honours them without a restart (discoverAndActivate runs again on toggle). chrome.html: toolbar sidebar-toggle button, hidden until at least one add-on has registered a sidebar panel. settings.html: new "Add-ons" section under privacy. Lists installed add-ons with icon / name / version / description / capabilities; per-add-on enable/disable toggle + Show folder button; page-level Reload and Open add-ons folder buttons; warning note about the trust model. package.json: build.files gains sidebar-preload.js + addons-host.js. extraResources gains bundled-addons/ so the packaged app carries the reference notepad for the first-boot seed. Verified: `npm start` boots, addons-host discovers the notepad, activates it, registers one sidebar panel. Log confirms "1 installed, 1 enabled, 1 sidebar panels". Actual sidebar rendering + notepad UI need clicked-through validation on a real install. Not shipped yet - deploy still blocked on the fail2ban VPS SSH ban. Ships as 0.2.0 once SSH clears (this is a new subsystem, not a fix).
2026-08-31 13:51:08 +02:00
openAddonsDir: () => ipcRenderer.invoke("addons-open-dir"),
reloadAddons: () => ipcRenderer.invoke("addons-reload"),
feat: community extensions — publish with a BCDN name, install from Settings, theseus.x catalog Anyone who owns a BCDN name can now publish a Theseus extension, and every Theseus can install it with the publisher's signature verified locally. Gateway (Argus/src/gateway/public-gateway.mjs): PUT /api/ext/<name>/<id>/<version> takes the gzipped tar, checks two BCH message signatures against the name's current NFT owner (one authorises the upload, one is stored in the channel), inspects the package (addon.json at the root, id/version/main match, 8 MB cap), enforces first-publisher ownership of an id and monotonic versions, and writes the tarball, the extension's updates.json and community/catalog.json to Sia. GET /api/ext/catalog reads the catalog back with CORS. Theseus: lib/publisher-sig.mjs recovers the signer of a channel entry; main.js compares it with the publisher name's owner from Theseus's own chain index before installing or updating, so neither the relay nor a tampered catalog can pass off code under a trusted name. addon-updater.js gains installCommunity() and accepts publisher-signed entries in the regular update check (operator Ed25519 entries unchanged). Settings › Extensions shows the community catalog with Install / Update; Settings › Plug-ins links to theseus.x/plug-ins. theseus.x: /plug-ins/ is a separate page for the first-party plug-ins (Aegis, Ariadne's Thread) with live versions and hashes; /extensions/ lists the bundled extensions, the community catalog, and how to build and publish; /extensions/publish/ signs and uploads a package in the browser with the wallet that holds the publisher's name (session helper + wallet bundle copied alongside).
2026-09-20 15:26:30 +02:00
// Community extensions from theseus.x/extensions: the catalog (with what
// is installed already) and a verified install/update of one entry.
communityCatalog: () => ipcRenderer.invoke("addons-community-catalog"),
installCommunity: (id) => ipcRenderer.invoke("addons-install-community", id),
feat(theseus/addons): CDP capture + editor Discard + manual update controls Three tied-together fixes: 1) captureTab moves from WebContents.capturePage() to CDP Page.captureScreenshot for every mode (visible / full / region). Blank-screenshot symptom: after a toolbar-menu selection, the OS popup teardown left the tab view marked occluded for a few frames on some Windows setups, so capturePage() snapshotted a stale/transparent frame at the correct dimensions — no 0x0, no retry hit. CDP forces a fresh composite regardless of occlusion state (same path the "Full page" mode was already using) and returns a base64 PNG directly; PNG dimensions come out of the IHDR chunk (bytes 16-24). Attach only when nothing else has, and detach after only if WE attached, so an open DevTools stays attached. 2) Editor gets a Discard button. Toolbar picks up an "×" glyph next to Save/Copy that closes the editor tab and drops the working screenshot. Top-level Escape now falls through the same path after unwinding an in-flight text placement or crop rectangle. A new "addon-tab-close" IPC lets an add-on's own tab close itself (main matches the sender's webContents id against the tab list, so a page can only close its own tab); window.silentmode.closeTab() exposes it from addon-tab-preload.js. 3) Manual update controls in Settings > Extensions. New "Check for updates" button at the top of the Extensions surface calls the same signed-update polling the boot timer runs; the result is surfaced inline ("All extensions are up to date" / "N updates staged; restart Theseus to apply"). A "Pending updates" box below lists what's in <userData>/addons-updates-staged/ so the user knows what will be promoted on next restart. Toolbar-menu popup settle bumped from 120 ms to 250 ms with an explicit win.focus() in the popup close callback — the previous window wasn't enough on slower Windows setups. CDP capture no longer depends on this delay anyway, but the settle still helps any add-on that does DOM work in its click handler before capture. Screenshot add-on bumped 0.2.2 → 0.2.3 (Discard button; capture fixes come from the host, not the add-on).
2026-09-08 02:27:36 +02:00
checkAddonUpdates: () => ipcRenderer.invoke("addons-check-updates"),
listStagedAddonUpdates: () => ipcRenderer.invoke("addons-list-staged"),
});