theseus/preload.js

47 lines
2.8 KiB
JavaScript
Raw Normal View History

const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("theseus", {
navigate: (input) => ipcRenderer.invoke("navigate", input),
search: (q) => ipcRenderer.invoke("search", q),
newTab: () => ipcRenderer.invoke("new-tab"),
closeTab: (id) => ipcRenderer.invoke("close-tab", id),
switchTab: (id) => ipcRenderer.invoke("switch-tab", id),
Theseus UX batch: tabs, address history, password autofill MVP, home cards Six user-visible improvements + supporting infra, all uncommitted from the earlier session-in-progress state. Ships together in one release. Chrome / tabs - Same-size tabs: flex 1 1 0 with max 200px, min 60px. Container gets overflow: hidden so many tabs shrink evenly instead of scrolling out. - Drag-and-drop tab reordering. HTML5 drag events on each .tab; drop side chosen by pointer x within target (Chrome UX). New move-tab IPC splices the tabs array + re-emits. Address bar - Persistent history at userData/history.json capped at 500 LRU. Ranked by host-prefix > url-prefix > contains > title-contains > recency. - Floating suggestions dropdown (addressPicker WebContentsView) anchored under the URL bar. Debounced 80ms input; ArrowUp/Down forward to the picker via address-cursor IPC; Enter fires goURL; blur closes after 160ms so click-through registers. New files address-picker.html + address-picker-preload.js. Cleared by existing clearHistoryOnQuit. Password autofill (A.2 MVP) - Green key chip in the address bar appears when the vault is UNLOCKED and the active tab's host has matching credentials (exact hostname match for phase 1; eTLD+1 upgrade queued as A.2.5). - Click chip → floating picker of usernames. Click a match → main.js runs a small script in the active tab: finds first visible input[type=password]:not([disabled]), walks the same form for a visible text/email/tel/url/search input whose name/id/autocomplete matches /username|user|email|login|account|id/, fills both via the native value setter + dispatches input/change so React/Vue-controlled inputs update. New files pw-fill.html + pw-fill-preload.js. - emitPwAvailability fires from pushNav + vault setup/unlock/lock so the chip's visibility + count stays accurate. Bookmarks bar - Right-click context menu on the favorites bar. On empty area: "Add current page" (or "Remove current page" if already saved). On a specific bookmark: "Open", "Edit title…" (prompt), "Remove", plus the add/remove-current entry. Uses a shared .ctxmenu style mirroring the settings ctxmenu (dark/light aware). - Empty-state text updated to mention right-click. Home page - Larger responsive card grid: auto-fill minmax(260-280px, 1fr) with breakpoints at 600/900/1200. Cards have a subtitle line, a colored badge (on-chain / Sia / server / custom), and edit affordances that reveal only in Edit mode. - User-editable set: Edit toggle reveals per-card ✎/✕ + a dashed "+ Add card" tile. Modal for add/edit with title / URL / subtitle / badge. Reset-to-defaults button. - Persisted at userData/home-cards.json. New home-preload.js exposes window.home = { getCards, setCards, resetCards, navigate }. IPC handlers in main.js validate sender.getURL() matches our own home.html — third-party pages see the API shape via the preload but can't act on the user's local cards. - Fallback set of 2 cards renders when window.home is unavailable (e.g. opening home.html directly outside Electron for preview) so the grid is never blank. Docs - TheseusNavigator/ROADMAP-identity-wallet.md — the phased plan for the two independent strands (password manager A.2/3, browser wallet B.1-6). Committed earlier this session; re-listed here for context. - TheseusNavigator/SESSION-PROMPT-identity-wallet.md — pastable kickoff for the next session picking up either strand. Files added to build.files: address-picker.html, address-picker-preload.js, pw-fill.html, pw-fill-preload.js, home-preload.js.
2026-08-17 02:17:12 +02:00
moveTab: (id, targetId, place) => ipcRenderer.invoke("move-tab", id, targetId, place),
suggestAddress: (query, rect) => ipcRenderer.invoke("suggest-address", query, rect),
closeAddressPicker: () => ipcRenderer.invoke("close-address-picker"),
addressCursor: (dir) => ipcRenderer.invoke("address-cursor", dir),
togglePwFill: (rect) => ipcRenderer.invoke("toggle-pw-fill", rect),
onPwAvailability: (cb) => ipcRenderer.on("pw-availability", (_e, d) => cb(d)),
goHome: () => ipcRenderer.invoke("go-home"),
back: () => ipcRenderer.invoke("go-back"),
forward: () => ipcRenderer.invoke("go-forward"),
reload: () => ipcRenderer.invoke("reload"),
stop: () => ipcRenderer.invoke("stop"),
toggleTor: () => ipcRenderer.invoke("toggle-tor"),
openSettings: () => ipcRenderer.invoke("open-settings"),
toggleSiteInfo: (rect) => ipcRenderer.invoke("toggle-site-info", rect),
switchToBcnr: () => ipcRenderer.invoke("switch-to-bcnr"),
setChromeHeight: (h) => ipcRenderer.invoke("set-chrome-height", h),
getSearchEngines: () => ipcRenderer.invoke("search-engines"),
setSearchEngine: (id) => ipcRenderer.invoke("set-search-engine", id),
addEngine: (eng) => ipcRenderer.invoke("add-engine", eng),
removeEngine: (id) => ipcRenderer.invoke("remove-engine", id),
toggleEnginePicker: (rect) => ipcRenderer.invoke("toggle-engine-picker", rect),
onEngines: (cb) => ipcRenderer.on("engines", (_e, d) => cb(d)),
getBookmarks: () => ipcRenderer.invoke("bookmarks-get"),
addBookmark: (bm) => ipcRenderer.invoke("bookmark-add", bm),
removeBookmark: (url) => ipcRenderer.invoke("bookmark-remove", url),
onBookmarks: (cb) => ipcRenderer.on("bookmarks", (_e, d) => cb(d)),
onNav: (cb) => ipcRenderer.on("nav", (_e, d) => cb(d)),
onTor: (cb) => ipcRenderer.on("tor", (_e, d) => cb(d)),
onTabs: (cb) => ipcRenderer.on("tabs", (_e, d) => cb(d)),
onBcnrOffer: (cb) => ipcRenderer.on("bcnr-offer", (_e, d) => cb(d)),
// Collision-mode (BCNR ↔ ICANN) live switcher for the active tab
collisionSwitch: (arg) => ipcRenderer.invoke("collision-switch", arg),
collisionState: () => ipcRenderer.invoke("collision-state"),
// Downloads — the toolbar button subscribes to `downloads` to update its
// badge, and toggleDownloads opens/closes the floating panel.
getDownloads: () => ipcRenderer.invoke("downloads-get"),
toggleDownloads: (rect) => ipcRenderer.invoke("toggle-downloads", rect),
onDownloads: (cb) => ipcRenderer.on("downloads", (_e, d) => cb(d)),
});