diff --git a/console/index.html b/console/index.html
index 9edeacc..88fc820 100644
--- a/console/index.html
+++ b/console/index.html
@@ -28,6 +28,7 @@
+
diff --git a/console/src/main.ts b/console/src/main.ts
index 2958162..f5b8c9a 100644
--- a/console/src/main.ts
+++ b/console/src/main.ts
@@ -596,13 +596,22 @@ interface UpdateInfo {
}
function setupUpdater(): void {
const el = document.getElementById("update-btn") as HTMLButtonElement | null;
+ const dismissEl = document.getElementById("update-dismiss") as HTMLButtonElement | null;
const invoke = tauriInvoke();
if (!el || !invoke) return; // browser build — no updater
el.hidden = false;
let pending: UpdateInfo | null = null;
+ // Finding an update must not force installing it (you may want to keep working
+ // or wait for a later nightly). The install button + this dismiss share the
+ // pending state; dismiss clears it back to "Check for updates".
+ const setPending = (info: UpdateInfo | null): void => {
+ pending = info;
+ if (dismissEl) dismissEl.hidden = info === null;
+ };
+
const reset = (): void => {
- pending = null;
+ setPending(null);
el.textContent = "Check for updates";
el.classList.remove("has-update");
};
@@ -613,10 +622,10 @@ function setupUpdater(): void {
try {
const info = await inv("check_update");
if (info) {
- pending = info;
+ setPending(info);
btn.textContent = `Update to v${info.version} ↻`;
btn.classList.add("has-update");
- note("info", `update: v${info.version} available (current v${info.current}) — click to install`);
+ note("info", `update: v${info.version} available (current v${info.current}) — click to install, or Later to keep this build`);
} else {
note("info", "update: already up to date");
btn.textContent = "Up to date";
@@ -633,17 +642,24 @@ function setupUpdater(): void {
async function install(btn: HTMLButtonElement, inv: Invoke): Promise {
btn.disabled = true;
btn.textContent = "Installing…";
+ if (dismissEl) dismissEl.hidden = true;
try {
// On success the backend restarts the app, so this may never resolve.
await inv("install_update");
} catch (e) {
btn.disabled = false;
btn.textContent = pending ? `Update to v${pending.version} ↻` : "Check for updates";
+ if (dismissEl) dismissEl.hidden = pending === null;
note("error", `update: install failed — ${errText(e)}`);
}
}
el.addEventListener("click", () => void (pending ? install(el, invoke) : check(el, invoke)));
+ dismissEl?.addEventListener("click", () => {
+ const skipped = pending?.version;
+ reset();
+ if (skipped) note("info", `update: skipped v${skipped} — staying on the current build`);
+ });
}
// Live remote-connection status: the backend pushes `remote-status` events as the
diff --git a/console/src/styles.css b/console/src/styles.css
index 8042e10..47e017a 100644
--- a/console/src/styles.css
+++ b/console/src/styles.css
@@ -133,6 +133,22 @@ body {
background: var(--s-starting);
border-color: var(--s-starting);
}
+/* Skip an available update and keep the current build (shown only while an
+ update is pending) — so finding a nightly doesn't force installing it. */
+.update-dismiss {
+ appearance: none;
+ border: 0;
+ background: transparent;
+ color: var(--muted);
+ font: inherit;
+ font-size: 12px;
+ padding: 3px 6px;
+ cursor: pointer;
+ text-decoration: underline;
+}
+.update-dismiss:hover {
+ color: var(--text);
+}
/* Appearance toggle — cycles System / Light / Dark. Mirrors the update button;
fixed min-width so the label swap doesn't shift the toolbar. */