Skip to content

Commit ba663e3

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. Other hosts and platforms continue opening the existing release URL. Run WinGet silently without a console window and let the NSIS installer close the application. 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 ba663e3

4 files changed

Lines changed: 37 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: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::process::Command;
2+
3+
#[cfg(windows)]
4+
use std::os::windows::process::CommandExt;
5+
6+
#[tauri::command]
7+
pub fn install_stable_update() -> Result<(), String> {
8+
let mut command = Command::new("winget");
9+
command.args([
10+
"upgrade",
11+
"--exact",
12+
"--id",
13+
"NeuralNomadsAI.CodeNomad",
14+
"--source",
15+
"winget",
16+
"--silent",
17+
"--accept-source-agreements",
18+
"--accept-package-agreements",
19+
"--disable-interactivity",
20+
]);
21+
22+
#[cfg(windows)]
23+
command.creation_flags(0x08000000);
24+
25+
command
26+
.spawn()
27+
.map(|_| ())
28+
.map_err(|err| format!("Unable to start the WinGet update: {err}"))
29+
}

packages/ui/src/lib/notifications.tsx

Lines changed: 2 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,7 @@ 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={() => void (payload.action!.onClick?.() ?? openExternalUrl(payload.action!.href))}
385386
>
386387
{payload.action.label}
387388
</button>

packages/ui/src/stores/releases.ts

Lines changed: 3 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,7 @@ function ensureVisibilityEffect() {
6163
? {
6264
label: tGlobal("releases.upgradeRequired.action.getUpdate"),
6365
href: support.latestServerUrl,
66+
onClick: isTauriHost() && isLocalWindow() && navigator.userAgent.includes("Windows") ? () => invoke("install_stable_update") : undefined,
6467
}
6568
: undefined,
6669
})

0 commit comments

Comments
 (0)