Skip to content

Commit 34ca646

Browse files
committed
feat(tauri): install stable Windows updates with WinGet
Replace the official release notification link with a native WinGet upgrade on local Tauri Windows sessions. Web, Electron, remote, macOS, and Linux sessions continue opening the existing release URL. Run WinGet silently without a console window and let the NSIS installer close the running application. The application remains closed after installation because WinGet provides no relaunch option. Validated with Cargo check, the UI TypeScript check, and a live upgrade from CodeNomad 0.17.0 to 0.18.0.
1 parent 07e8ce6 commit 34ca646

4 files changed

Lines changed: 48 additions & 2 deletions

File tree

packages/tauri-app/src-tauri/src/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod desktop_event_transport;
77
#[cfg(target_os = "linux")]
88
mod linux_tls;
99
mod managed_node;
10+
mod windows_update;
1011

1112
use cli_manager::{CliProcessManager, CliStatus};
1213
use desktop_event_transport::{DesktopEventTransportManager, DesktopEventsStartRequest, DesktopEventsStartResult};
@@ -642,7 +643,8 @@ fn main() {
642643
wake_lock_start,
643644
wake_lock_stop,
644645
needs_local_certificate_install,
645-
open_remote_window
646+
open_remote_window,
647+
windows_update::install_stable_update
646648
])
647649
.on_menu_event(|app_handle, event| {
648650
match event.id().0.as_str() {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#[tauri::command]
2+
pub fn install_stable_update() -> Result<(), String> {
3+
#[cfg(windows)]
4+
{
5+
use std::os::windows::process::CommandExt;
6+
use std::process::Command;
7+
8+
const CREATE_NO_WINDOW: u32 = 0x08000000;
9+
10+
Command::new("winget")
11+
.args([
12+
"upgrade",
13+
"--exact",
14+
"--id",
15+
"NeuralNomadsAI.CodeNomad",
16+
"--source",
17+
"winget",
18+
"--silent",
19+
"--accept-source-agreements",
20+
"--accept-package-agreements",
21+
"--disable-interactivity",
22+
])
23+
.creation_flags(CREATE_NO_WINDOW)
24+
.spawn()
25+
.map_err(|err| format!("Unable to start the WinGet update: {err}"))?;
26+
27+
Ok(())
28+
}
29+
30+
#[cfg(not(windows))]
31+
{
32+
Err("WinGet updates are only available on Windows".to_string())
33+
}
34+
}

packages/ui/src/lib/notifications.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type ToastPayload = {
2020
action?: {
2121
label: string
2222
href: string
23+
onClick?: () => void | Promise<void>
2324
}
2425
}
2526

@@ -381,7 +382,10 @@ export function showToastNotification(payload: ToastPayload): ToastHandle {
381382
<button
382383
type="button"
383384
class="mt-3 inline-flex items-center text-xs font-semibold uppercase tracking-wide text-sky-300 hover:text-sky-200"
384-
onClick={() => void openExternalUrl(payload.action!.href)}
385+
onClick={() => {
386+
const action = payload.action!
387+
void (action.onClick ? action.onClick() : openExternalUrl(action.href))
388+
}}
385389
>
386390
{payload.action.label}
387391
</button>

packages/ui/src/stores/releases.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { createEffect, createSignal } from "solid-js"
2+
import { invoke } from "@tauri-apps/api/core"
23
import type { ServerMeta, SupportMeta } from "../../../server/src/api-types"
34
import { getServerMeta } from "../lib/server-meta"
45
import { showToastNotification, ToastHandle } from "../lib/notifications"
56
import { getLogger } from "../lib/logger"
67
import { tGlobal } from "../lib/i18n"
8+
import { isLocalWindow, isTauriHost } from "../lib/runtime-env"
79
import { hasInstances, showFolderSelection } from "./ui"
810

911
const log = getLogger("actions")
@@ -61,6 +63,10 @@ function ensureVisibilityEffect() {
6163
? {
6264
label: tGlobal("releases.upgradeRequired.action.getUpdate"),
6365
href: support.latestServerUrl,
66+
onClick:
67+
isTauriHost() && isLocalWindow() && navigator.userAgent.includes("Windows")
68+
? () => invoke("install_stable_update")
69+
: undefined,
6470
}
6571
: undefined,
6672
})

0 commit comments

Comments
 (0)