Standard browser Ctrl+F support:
- main.js: Ctrl+F caught in the shared before-input-event handler (same
place as F12 / reload shortcuts) fires 'find-open' to chrome.
Two new IPC handlers proxy to activeTab().view.webContents:
find-in-page(query, {forward, findNext, matchCase})
find-stop
Each tab's webContents listens for 'found-in-page' and forwards
{activeMatchOrdinal, matches, finalUpdate} back to chrome via
'find-result' — only when it's the active tab so the bar doesn't
update from a background tab's stale match count.
- preload.js: exposes onFindOpen / findInPage / findStop / onFindResult.
- chrome.html: adds a .findbar strip below the bookmarks bar (part of
chrome-view height like .tordisc / .bcnrbar, so syncHeight picks it
up). Input + "N of M" counter + prev/next/close buttons. Enter jumps
next, Shift+Enter previous, Esc closes. Typing runs findNext:false
(fresh search); pressing Enter runs findNext:true (walk matches).
No-match state paints the input border red.
91 lines
6 KiB
JavaScript
91 lines
6 KiB
JavaScript
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),
|
|
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)),
|
|
// Update chip: chrome subscribes to update-available; clicking the chip's
|
|
// download button opens the URL in the system browser; ✕ dismisses for
|
|
// the current session.
|
|
onUpdateAvailable: (cb) => ipcRenderer.on("update-available", (_e, d) => cb(d)),
|
|
openUpdateDownload: (url) => ipcRenderer.invoke("open-update-download", url),
|
|
installUpdateNow: () => ipcRenderer.invoke("install-update-now"),
|
|
dismissUpdate: () => ipcRenderer.invoke("dismiss-update"),
|
|
goHome: () => ipcRenderer.invoke("go-home"),
|
|
back: () => ipcRenderer.invoke("go-back"),
|
|
forward: () => ipcRenderer.invoke("go-forward"),
|
|
reload: (hard) => ipcRenderer.invoke("reload", !!hard),
|
|
stop: () => ipcRenderer.invoke("stop"),
|
|
toggleTor: () => ipcRenderer.invoke("toggle-tor"),
|
|
openSettings: () => ipcRenderer.invoke("open-settings"),
|
|
getSettings: () => ipcRenderer.invoke("settings-get"),
|
|
setSetting: (key, val) => ipcRenderer.invoke("settings-set", key, val),
|
|
onSettingsUpdate: (cb) => ipcRenderer.on("settings-update", (_e, d) => cb(d)),
|
|
// Find-in-page. main.js fires 'find-open' on Ctrl+F; chrome renderer
|
|
// owns the bar UI and drives findInPage / stopFindInPage via these
|
|
// wrappers. Match count / active ordinal comes back through onFindResult.
|
|
onFindOpen: (cb) => ipcRenderer.on("find-open", () => cb()),
|
|
findInPage: (query, opts) => ipcRenderer.invoke("find-in-page", query, opts || {}),
|
|
findStop: () => ipcRenderer.invoke("find-stop"),
|
|
onFindResult: (cb) => ipcRenderer.on("find-result", (_e, d) => cb(d)),
|
|
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),
|
|
updateBookmark: (url, patch) => ipcRenderer.invoke("bookmark-update", url, patch),
|
|
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)),
|
|
tabReload: (id) => ipcRenderer.invoke("tab-reload", id),
|
|
tabDuplicate: (id) => ipcRenderer.invoke("tab-duplicate", id),
|
|
tabMute: (id, on) => ipcRenderer.invoke("tab-mute", id, on),
|
|
tabGroup: (id, color) => ipcRenderer.invoke("tab-group", id, color),
|
|
tabGroupToggle: (color) => ipcRenderer.invoke("tab-group-toggle", color),
|
|
tabBookmark: (id) => ipcRenderer.invoke("tab-bookmark", id),
|
|
onAddressPicked: (cb) => ipcRenderer.on("address-picked", (_e, url) => cb(url)),
|
|
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)),
|
|
// Add-on sidebar: toggle, open on a specific panel, close, or subscribe
|
|
// to state (visibility + which panel is active + the panel list). The
|
|
// extension dock in chrome.html renders one button per panel and calls
|
|
// openSidebar / closeSidebar accordingly.
|
|
toggleSidebar: () => ipcRenderer.invoke("sidebar-toggle"),
|
|
openSidebar: (panelId) => ipcRenderer.invoke("sidebar-open", panelId),
|
|
closeSidebar: () => ipcRenderer.invoke("sidebar-close"),
|
|
sidebarState: () => ipcRenderer.invoke("sidebar-state"),
|
|
onSidebarState: (cb) => ipcRenderer.on("sidebar-state", (_e, d) => cb(d)),
|
|
// Toolbar-menu (dropdown from an add-on's dock icon): dispatch the picked
|
|
// item id to the add-on's "menu-select" handler.
|
|
addonMenuSelect: (addonId, itemId) => ipcRenderer.invoke("addon-menu-select", addonId, itemId),
|
|
// Pop the dock-icon dropdown as a NATIVE menu. Renderer-side DOM popovers
|
|
// get clipped by chrome.html's own WebContentsView height (CHROME_H) and
|
|
// then covered by the tab view below it — a native Menu.popup escapes that
|
|
// layering entirely. Pass the button's viewport-rect so main can anchor.
|
|
toolbarMenuPopup: (addonId, rect) => ipcRenderer.invoke("toolbar-menu-popup", addonId, rect),
|
|
// Chrome listens so it can drop the "active" tint when the native menu
|
|
// dismisses (Esc, outside click, item picked — main fires all three).
|
|
onToolbarMenuClosed: (cb) => ipcRenderer.on("toolbar-menu-closed", () => cb()),
|
|
});
|