From 5cd60f1df39759c7d9ee02db53a183cbedfbe361 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Tue, 8 Sep 2026 00:43:26 +0200 Subject: [PATCH] feat(theseus/settings): Check for updates button in Settings > General MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New "Updates" card under Startup: a single "Check for updates" button that hits the release manifest immediately (rather than waiting for the boot-time and 6h-interval auto-check). Reuses the existing recheck-update IPC; extended it to un-dismiss any chip the user closed this session AND to return the current app version so the button can render either: - "You're on the latest (v0.3.21)." when nothing newer exists - "vX.Y.Z is available — the update chip in the toolbar will offer it." Button disables + shows "Checking…" during the fetch. Silent failures report their reason ("Check failed: …") so the user isn't left staring at a dash. --- main.js | 10 +++++++++- settings-preload.js | 3 +++ settings.html | 31 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index da7846f..4ae8c8b 100644 --- a/main.js +++ b/main.js @@ -2859,7 +2859,15 @@ ipcMain.handle("open-update-download", (_e, url) => { } catch (e) { console.warn("update download failed:", e?.message); return false; } }); ipcMain.handle("dismiss-update", () => { updateDismissedThisSession = true; emitUpdateAvailable(); return true; }); -ipcMain.handle("recheck-update", async () => { await checkForUpdate(); return updateAvailable; }); +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 + // that. Report current app version too so the UI can render "you're on + // vN.M.O" when no newer build is out. + updateDismissedThisSession = false; + await checkForUpdate(); + return { updateAvailable, currentVersion: app.getVersion() }; +}); // One-click "Install & restart". Requires the silent pre-fetch to have // finished (updateDownloadState === "ready"). Launches the setup with /S // (skips the wizard; our nsis/installer.nsh's Ariadne prompt is bypassed diff --git a/settings-preload.js b/settings-preload.js index 7893750..749de7a 100644 --- a/settings-preload.js +++ b/settings-preload.js @@ -36,6 +36,9 @@ contextBridge.exposeInMainWorld("cfg", { 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), diff --git a/settings.html b/settings.html index 11c8884..c31bb40 100644 --- a/settings.html +++ b/settings.html @@ -159,6 +159,16 @@
Open previous windows and tabs
Restore the tabs from your last session when Theseus starts.
+
+
+
Updates
+
Theseus already checks the release manifest at boot and every 6h. Click below to check right now.
+
+
+
+ +
+

Appearance

Choose a theme for the browser. System follows your operating system's light/dark setting.

@@ -940,6 +950,27 @@ arRefresh.onclick = refreshAriadne; refreshAriadne(); + // ---- 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 + // "vX.Y.Z is available — the update chip in the toolbar will offer it". + const updStatus = document.getElementById("updStatus"); + const updCheck = document.getElementById("updCheck"); + updCheck.onclick = async () => { + const orig = updCheck.textContent; + updCheck.disabled = true; updCheck.textContent = "Checking…"; + updStatus.textContent = "Checking…"; + try { + const r = await C.recheckUpdate(); + if (r && r.updateAvailable && r.updateAvailable.version) { + updStatus.innerHTML = `v${r.updateAvailable.version} is available — the update chip in the toolbar will offer it.`; + } else { + updStatus.textContent = `You're on the latest (v${(r && r.currentVersion) || "?"}).`; + } + } catch (e) { updStatus.textContent = "Check failed: " + (e?.message || e); } + finally { updCheck.disabled = false; updCheck.textContent = orig; } + }; + // ---- Passwords section: three states (setup / locked / unlocked) --------- // The vault lives in main.js — this UI just calls IPC. No plaintext ever // sits in this DOM except the value produced by a specific Show/Copy click.