diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index aadf45c..27ff80e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -660,7 +660,8 @@ async fn download_and_install_update(app: tauri::AppHandle, tag: String) -> Resu #[derive(serde::Deserialize)] struct Release { assets: Vec } - let release: Release = resp.json().await.map_err(|e| e.to_string())?; + let body = resp.text().await.map_err(|e| e.to_string())?; + let release: Release = serde_json::from_str(&body).map_err(|e| e.to_string())?; let asset = release.assets .into_iter() @@ -682,12 +683,16 @@ async fn download_and_install_update(app: tauri::AppHandle, tag: String) -> Resu } drop(file); - // Launch the NSIS installer — it handles closing/replacing the running app. - std::process::Command::new("cmd") - .args(["/C", "start", "", &tmp_path.to_string_lossy()]) + // Launch the NSIS installer silently without a visible cmd window. + use std::os::windows::process::CommandExt; + const CREATE_NO_WINDOW: u32 = 0x08000000; + std::process::Command::new(&tmp_path) + .creation_flags(CREATE_NO_WINDOW) .spawn() .map_err(|e| e.to_string())?; + let _ = app.emit("update-launching", ()); + Ok(()) } } diff --git a/src/features/settings/sections/AboutSettings.svelte b/src/features/settings/sections/AboutSettings.svelte index fef71ab..12fd104 100644 --- a/src/features/settings/sections/AboutSettings.svelte +++ b/src/features/settings/sections/AboutSettings.svelte @@ -5,7 +5,7 @@ import { open as openUrl } from "@tauri-apps/plugin-shell"; interface ReleaseInfo { tag_name: string; name: string; body: string; published_at: string; html_url: string; } - type UpdatePhase = "idle" | "downloading" | "ready" | "error"; + type UpdatePhase = "idle" | "downloading" | "launching" | "ready" | "error"; const IS_WINDOWS = navigator.userAgent.includes("Windows"); let appVersion = $state("…"); @@ -33,6 +33,13 @@ return () => unlisten?.(); }); + $effect(() => { + let unlisten: (() => void) | undefined; + listen("update-launching", () => { updatePhase = "launching"; }) + .then(fn => { unlisten = fn; }); + return () => unlisten?.(); + }); + async function loadReleases() { releasesLoading = true; releasesError = null; try { @@ -81,7 +88,7 @@ try { if (IS_WINDOWS) { try { await invoke("kill_server"); } catch {} - await invoke("download_and_install_update"); + await invoke("download_and_install_update", { tag: release.tag_name }); updatePhase = "ready"; } else { await openUrl(release.html_url); @@ -134,6 +141,11 @@ {/if} + {#if updatePhase === "launching"} +
+ Launching installer for {targetTag}… +
+ {/if} {#if updatePhase === "ready"}
{targetTag} downloaded — restart to finish installing.