2026-07-29 13:54:34 +02:00
|
|
|
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)),
|
Theseus 0.0.4: cheap in-app update-check chip
Bumps version so the chip actually surfaces itself on 0.0.3 installs
(the version-newer check requires a strict semver bump — same-version
rebuilds don't trigger the chip). From this release on, whenever the
manifest names a newer Theseus, users get a one-click download.
Mechanism
- main.js checkForUpdate() fetches https://dl.silentmode.st/releases-
manifest.json on startup (5s timeout, cache: no-store) + every 6h.
Finds the theseus-navigator release, compares version to
app.getVersion() with a numeric a.b.c comparator that handles
"0.10.0 > 0.9.9" correctly.
- On a match → stores { version, setupUrl, portableUrl, setupHash,
portableHash, date } and emits update-available to chrome. Cleared
after the user upgrades + relaunches (same-version → null).
- Re-emits on chrome's did-finish-load in case the fetch beats the
chrome view.
Chip UI (chrome.html)
- Acid-yellow pill between the downloads button and the Tor toggle:
"↓ Update to X.Y.Z" + a ✕. Main body opens setupUrl in the system
browser via shell.openExternal (origin-validated to
https://dl.silentmode.st/ or https://silentmode.st/). ✕ dismisses
for the current session — you'll see it again next launch if still
behind.
Trust anchor
- No signing / no cryptographic verification of the download in this
phase. releases.silentmode.bch publishes the SAME manifest URL, so
users who want to verify can cross-check the manifest hash against
what BCNR returns. The proper auto-updater with signature checks is
the follow-on to this cheap version.
Non-goals in phase 1
- No delta downloads; the user clicks and gets a full installer.
- No auto-install; download → user runs the installer themselves.
- No "check now" button in Settings; the periodic timer suffices.
- No portable-vs-installed detection; the chip prefers setupUrl (the
installer upgrades in place). Right-click for portable is future work.
2026-08-28 20:21:44 +02:00
|
|
|
// 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),
|
|
|
|
|
dismissUpdate: () => ipcRenderer.invoke("dismiss-update"),
|
2026-07-29 13:54:34 +02:00
|
|
|
goHome: () => ipcRenderer.invoke("go-home"),
|
|
|
|
|
back: () => ipcRenderer.invoke("go-back"),
|
|
|
|
|
forward: () => ipcRenderer.invoke("go-forward"),
|
2026-08-31 02:50:57 +02:00
|
|
|
reload: (hard) => ipcRenderer.invoke("reload", !!hard),
|
2026-07-30 19:29:32 +02:00
|
|
|
stop: () => ipcRenderer.invoke("stop"),
|
2026-07-29 13:54:34 +02:00
|
|
|
toggleTor: () => ipcRenderer.invoke("toggle-tor"),
|
|
|
|
|
openSettings: () => ipcRenderer.invoke("open-settings"),
|
2026-07-30 08:16:55 +02:00
|
|
|
toggleSiteInfo: (rect) => ipcRenderer.invoke("toggle-site-info", rect),
|
2026-07-29 13:54:34 +02:00
|
|
|
switchToBcnr: () => ipcRenderer.invoke("switch-to-bcnr"),
|
|
|
|
|
setChromeHeight: (h) => ipcRenderer.invoke("set-chrome-height", h),
|
2026-07-30 08:16:55 +02:00
|
|
|
getSearchEngines: () => ipcRenderer.invoke("search-engines"),
|
|
|
|
|
setSearchEngine: (id) => ipcRenderer.invoke("set-search-engine", id),
|
2026-07-30 20:58:45 +02:00
|
|
|
addEngine: (eng) => ipcRenderer.invoke("add-engine", eng),
|
|
|
|
|
removeEngine: (id) => ipcRenderer.invoke("remove-engine", id),
|
2026-07-30 22:55:52 +02:00
|
|
|
toggleEnginePicker: (rect) => ipcRenderer.invoke("toggle-engine-picker", rect),
|
2026-07-30 20:58:45 +02:00
|
|
|
onEngines: (cb) => ipcRenderer.on("engines", (_e, d) => cb(d)),
|
2026-07-30 08:16:55 +02:00
|
|
|
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)),
|
2026-07-29 13:54:34 +02:00
|
|
|
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)),
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
Merges a parallel session's work with the multi-source BNS story from 0.0.7.
The dApp side (parallel session)
--------------------------------
* bcnr-preload.js — installs `window.bcnr` on every page via contextBridge.
Read-only surface: resolveName(name), isRegistered(name), getBcnrTlds(),
getRecordVersion(name), plus getPermissionOrigin() for diagnostics. All
Promises; a missing name returns null (not throw). No signing, no wallet
unlock — that surface is designed but deliberately out of scope for 0.0.8
(see TheseusNavigator/DESIGN-integrated-wallet.md).
* bcnr-origin.js — pure function that computes the eTLD+1 permission origin
for a URL. ICANN suffixes via `psl` (same PSL Chromium uses, handles
.co.uk / .github.io / etc); BNS names key off the on-chain TLD list so
foo.wallet becomes a public suffix as soon as `wallet` appears there.
Match browser cookie / MetaMask semantics: a grant on pay.merchant.com
covers account.merchant.com but not evil.com.
* dev/bcnr-selftest.js, dev/origin-selftest.mjs — self-tests, no I/O.
* main.js wires bcnr-preload.js into session.defaultSession.setPreloads() so
it runs BEFORE per-WebContentsView preloads; adds bcnr:* IPC handlers.
* preload.js + chrome.html — small hooks so the shell picks up window.bcnr
the same way regular content does.
* package.json — psl dep, bcnr-preload.js/bcnr-origin.js in `files`.
Also included
-------------
* AriadneResolver/mobile/.../UpdateCheck.java — in-app update-check for the
Android app; already active in the shipped 0.11 APK (build.ps1 -Recurse
picked it up), formalising the source now.
* TheseusNavigator/snapshots/bns-name-snapshot.json — refreshed bundled
starter (73 beacon txs, root c37b8596…c54e414ba).
* Site pages + manifest updated to point at 0.0.8.
TheseusNavigator-Setup-0.0.8.exe 95.4 MB
21939743eafdfe8742a6b7c4b987bd2782384d7bc41289cb80a7e08019dc9f02
TheseusNavigator-0.0.8-portable.exe 92.7 MB
2aa429fe39dc0fa4ac040fc6d6eb31b0f890c8a83175c49fcb50f052c480d39d
2026-08-31 01:38:55 +02:00
|
|
|
onAddressPicked: (cb) => ipcRenderer.on("address-picked", (_e, url) => cb(url)),
|
2026-07-29 13:54:34 +02:00
|
|
|
onBcnrOffer: (cb) => ipcRenderer.on("bcnr-offer", (_e, d) => cb(d)),
|
2026-08-02 11:39:00 +02:00
|
|
|
// 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)),
|
2026-07-29 13:54:34 +02:00
|
|
|
});
|