diff --git a/main.js b/main.js
index dd23831..543d35a 100644
--- a/main.js
+++ b/main.js
@@ -2978,6 +2978,9 @@ ipcMain.handle("find-stop", () => {
// Just the app version — no network. Used by Settings > General so the
// user can see which Theseus they're on without clicking "Check for updates".
ipcMain.handle("app-version", () => app.getVersion());
+// Clean relaunch — used by the Aegis card to apply a staged add-on update
+// (promotion happens on next boot; this is just how the user gets there).
+ipcMain.handle("app-restart", () => { try { app.relaunch(); } catch {} app.quit(); });
ipcMain.handle("recheck-update", async () => {
// Manual "Check for updates" also un-dismisses any chip the user closed
// in this session — they're actively asking to see the status, so honour
@@ -4056,9 +4059,9 @@ app.on("web-contents-created", (_event, wc) => {
return e.preventDefault();
}
// DevTools: F12 or Ctrl+Shift+I toggles Chromium DevTools on the active
- // TAB (not the chrome/overlay that received the keystroke — a user
- // debugging a page wants the page's inspector, always). Detach into
- // its own window so we don't shove tools into the tab strip.
+ // TAB. Docked to the right of the tab view (mode: "right") so the tools
+ // ride alongside the page instead of popping a separate Theseus window.
+ // Users who prefer detached can still drag out via the DevTools UI.
const isI = input.key === "I" || input.key === "i";
if (input.key === "F12" || (input.control && input.shift && isI)) {
const t = activeTab();
@@ -4066,7 +4069,7 @@ app.on("web-contents-created", (_event, wc) => {
try {
const twc = t.view.webContents;
if (twc.isDevToolsOpened()) twc.closeDevTools();
- else twc.openDevTools({ mode: "detach" });
+ else twc.openDevTools({ mode: "right" });
} catch {}
}
return e.preventDefault();
diff --git a/settings-preload.js b/settings-preload.js
index 029583a..20babb6 100644
--- a/settings-preload.js
+++ b/settings-preload.js
@@ -40,6 +40,7 @@ contextBridge.exposeInMainWorld("cfg", {
// fetches the release manifest. Returns { updateAvailable, currentVersion }.
recheckUpdate: () => ipcRenderer.invoke("recheck-update"),
appVersion: () => ipcRenderer.invoke("app-version"),
+ restartApp: () => ipcRenderer.invoke("app-restart"),
// Add-ons management (Settings > Add-ons tab).
listAddons: () => ipcRenderer.invoke("addons-list"),
setAddonEnabled: (id, enabled) => ipcRenderer.invoke("addons-set-enabled", id, !!enabled),
diff --git a/settings.html b/settings.html
index 4d237db..2bb795a 100644
--- a/settings.html
+++ b/settings.html
@@ -234,6 +234,22 @@
silentmode.st/tools.
+
+
+
Built-in wallet — Aegis
+
+ Multi-chain wallet (BCH, BTC, TRX, ETH, SOL, SC, DGB) that ships in the box.
+ Bundled with Theseus, but updates are delivered over-the-air: new signed
+ versions land without a Theseus release. Runs entirely inside this browser —
+ never system-wide.
+
+
+
Loading…
+
+
+
+
+
@@ -982,6 +998,49 @@
arRefresh.onclick = refreshAriadne;
refreshAriadne();
+ // ---- Aegis (bchwallet) update card --------------------------------------
+ // Aegis is a bundled add-on but its updates are shipped OTA via the signed
+ // add-on update endpoint, so users can get new wallet versions without
+ // updating Theseus. The same addons-check-updates IPC the Extensions page
+ // uses is filtered for the bchwallet id so this card only speaks for Aegis.
+ const aegisStatus = document.getElementById("aegisStatus");
+ const aegisCheck = document.getElementById("aegisCheck");
+ const aegisApply = document.getElementById("aegisApply");
+ async function refreshAegis() {
+ aegisApply.hidden = true;
+ try {
+ const [installed, staged] = await Promise.all([
+ C.listAddons ? C.listAddons() : Promise.resolve([]),
+ C.listStagedAddonUpdates ? C.listStagedAddonUpdates() : Promise.resolve([]),
+ ]);
+ const cur = (installed || []).find((a) => a.id === "bchwallet");
+ const upd = (staged || []).find((a) => a.id === "bchwallet");
+ if (!cur) { aegisStatus.textContent = "Aegis isn't installed. Reinstall Theseus to add it back, or open Settings > Extensions to load it manually."; return; }
+ const curVer = cur.version || "?";
+ if (upd && upd.version) {
+ aegisStatus.innerHTML = `v${upd.version} staged — restart Theseus to switch to it. You're on v${curVer}.`;
+ aegisApply.hidden = false;
+ } else {
+ aegisStatus.textContent = `You're on v${curVer}. Updates arrive over-the-air; the next check runs at boot and every 6h.`;
+ }
+ } catch (e) { aegisStatus.textContent = "Status check failed: " + (e?.message || e); }
+ }
+ aegisCheck.onclick = async () => {
+ const orig = aegisCheck.textContent;
+ aegisCheck.disabled = true; aegisCheck.textContent = "Checking…";
+ aegisStatus.textContent = "Checking…";
+ try {
+ const staged = await (C.checkAddonUpdates ? C.checkAddonUpdates() : Promise.resolve([]));
+ const upd = (staged || []).find((a) => a.id === "bchwallet");
+ if (!upd) { aegisStatus.textContent = "You're on the latest Aegis."; }
+ // refresh will populate everything else + toggle the Apply button
+ refreshAegis();
+ } catch (e) { aegisStatus.textContent = "Check failed: " + (e?.message || e); }
+ finally { aegisCheck.disabled = false; aegisCheck.textContent = orig; }
+ };
+ aegisApply.onclick = () => { if (C && C.restartApp) C.restartApp(); };
+ refreshAegis();
+
// ---- Manual "Check for updates" -----------------------------------------
// Fires an IPC that un-dismisses any lingering session chip and hits the
// release manifest. Renders either "you're on the latest (vN.M.O)" or