Skip to content

Commit bb22016

Browse files
feat: add "Check for updates" CTA in Settings/About
Manual update check + install in the About panel, reusing the auto- updater plugin (check -> downloadAndInstall -> relaunch). Shows state: checking / up-to-date / available (Install & relaunch) / error. Updater capabilities were already granted. Bumps desktop app to 1.1.67. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 7543717 commit bb22016

3 files changed

Lines changed: 80 additions & 2 deletions

File tree

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@code-reviewer/desktop",
3-
"version": "1.1.66",
3+
"version": "1.1.67",
44
"private": true,
55
"scripts": {
66
"dev": "lsof -ti:1420 | xargs kill -9 2>/dev/null; vite",

apps/desktop/src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-utils/schema.json",
33
"identifier": "com.codevetter.desktop",
44
"productName": "CodeVetter",
5-
"version": "1.1.66",
5+
"version": "1.1.67",
66
"build": {
77
"beforeDevCommand": "npm run dev",
88
"beforeBuildCommand": "npm run build",

apps/desktop/src/pages/Settings.tsx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,42 @@ export default function Settings() {
594594
};
595595
}, []);
596596

597+
// Manual "Check for updates" CTA (reuses the auto-updater plugin).
598+
type UpdateState = "idle" | "checking" | "available" | "latest" | "error" | "installing";
599+
const [updateState, setUpdateState] = useState<UpdateState>("idle");
600+
const [pendingUpdate, setPendingUpdate] = useState<
601+
{ version: string; install: () => Promise<void> } | null
602+
>(null);
603+
604+
const checkForUpdates = useCallback(async () => {
605+
setUpdateState("checking");
606+
try {
607+
const { check } = await import("@tauri-apps/plugin-updater");
608+
const result = await check();
609+
if (result?.available) {
610+
setPendingUpdate({ version: result.version, install: () => result.downloadAndInstall() });
611+
setUpdateState("available");
612+
} else {
613+
setPendingUpdate(null);
614+
setUpdateState("latest");
615+
}
616+
} catch {
617+
setUpdateState("error");
618+
}
619+
}, []);
620+
621+
const installUpdate = useCallback(async () => {
622+
if (!pendingUpdate) return;
623+
setUpdateState("installing");
624+
try {
625+
await pendingUpdate.install();
626+
const { relaunch } = await import("@tauri-apps/plugin-process");
627+
await relaunch();
628+
} catch {
629+
setUpdateState("error");
630+
}
631+
}, [pendingUpdate]);
632+
597633
// Menu-bar tray
598634
const [trayCadence, setTrayCadence] = usePref("tray_refresh_cadence_secs", "120");
599635

@@ -988,6 +1024,48 @@ export default function Settings() {
9881024

9891025
<Divider />
9901026

1027+
{/* Check for updates */}
1028+
<div className="flex items-center justify-between py-4">
1029+
<div className="flex flex-col gap-0.5">
1030+
<span className="text-sm text-slate-400">Updates</span>
1031+
<span className="text-xs text-slate-500">
1032+
{updateState === "checking"
1033+
? "Checking for updates…"
1034+
: updateState === "available"
1035+
? `Update available: v${pendingUpdate?.version}`
1036+
: updateState === "latest"
1037+
? "You're on the latest version."
1038+
: updateState === "installing"
1039+
? "Downloading & installing…"
1040+
: updateState === "error"
1041+
? "Couldn't check — try again."
1042+
: "Check GitHub Releases for a newer build."}
1043+
</span>
1044+
</div>
1045+
{updateState === "available" ? (
1046+
<Button
1047+
variant="ghost"
1048+
size="sm"
1049+
onClick={installUpdate}
1050+
className="h-auto px-3 py-1 text-xs text-amber-400 hover:text-amber-300"
1051+
>
1052+
Install &amp; relaunch
1053+
</Button>
1054+
) : (
1055+
<Button
1056+
variant="ghost"
1057+
size="sm"
1058+
onClick={checkForUpdates}
1059+
disabled={updateState === "checking" || updateState === "installing"}
1060+
className="h-auto px-3 py-1 text-xs text-slate-400 hover:text-slate-200"
1061+
>
1062+
{updateState === "checking" ? "Checking…" : "Check for updates"}
1063+
</Button>
1064+
)}
1065+
</div>
1066+
1067+
<Divider />
1068+
9911069
{/* Links */}
9921070
<div className="flex flex-col gap-2 py-4">
9931071
<h4 className="text-xs font-semibold uppercase tracking-wider text-slate-400 mb-1">Links</h4>

0 commit comments

Comments
 (0)