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).
50 lines
3.3 KiB
JavaScript
50 lines
3.3 KiB
JavaScript
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),
|
|
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),
|
|
// 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"),
|
|
// 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),
|
|
openAddonsDir: () => ipcRenderer.invoke("addons-open-dir"),
|
|
reloadAddons: () => ipcRenderer.invoke("addons-reload"),
|
|
checkAddonUpdates: () => ipcRenderer.invoke("addons-check-updates"),
|
|
listStagedAddonUpdates: () => ipcRenderer.invoke("addons-list-staged"),
|
|
});
|