Skip to main content

brows3r_lib/commands/
updater_cmd.rs

1//! Tauri commands for auto-update operations.
2//!
3//! # Commands
4//!
5//! - `updater_check`   — checks the update endpoint; emits `updater:status`
6//!                       transitions (`Checking` → `Available`/`UpToDate`/`Error`).
7//! - `updater_install` — downloads and installs a pending update; emits
8//!                       `Downloading { progress }` → `Ready` (or `Error`).
9//!
10//! # OCP
11//!
12//! New updater commands are additive — each is an independent `#[tauri::command]`
13//! registered in `lib.rs`.  `UpdateStatus` variants in `updater/mod.rs` extend
14//! without touching these handlers.
15
16use tauri::AppHandle;
17
18use crate::{
19    error::AppError,
20    events::{self, EventKind},
21    updater::{self, UpdateStatus},
22};
23
24// ---------------------------------------------------------------------------
25// updater_restart
26// ---------------------------------------------------------------------------
27
28/// Restart the application after a successful `updater_install`.
29///
30/// The frontend's "Restart now" button used to call
31/// `window.location.reload()` which only reloaded the WebView inside the
32/// still-running old binary — the staged update never took effect.
33/// `app.restart()` exits and re-execs into the freshly-installed binary.
34#[tauri::command]
35pub fn updater_restart(app: AppHandle) {
36    updater::restart(&app);
37}
38
39// ---------------------------------------------------------------------------
40// updater_check
41// ---------------------------------------------------------------------------
42
43/// Check the configured update endpoint for a newer release.
44///
45/// Emits `updater:status` events:
46///   1. `{ "status": "checking" }` — immediately on entry.
47///   2. `{ "status": "available", "version": "…", "notes": "…" }` — when a
48///       newer version is found.
49///   3. `{ "status": "upToDate" }` — when already on latest.
50///   4. `{ "status": "error", "message": "…" }` — on any failure.
51///
52/// Returns the final `UpdateStatus` for callers who prefer a synchronous result
53/// (the frontend can use either the return value or the events).
54#[tauri::command]
55pub async fn updater_check(app: AppHandle) -> Result<UpdateStatus, AppError> {
56    // Emit "checking" immediately so the UI can show a spinner.
57    let _ = events::emit(&app, EventKind::UpdaterStatus, &UpdateStatus::Checking);
58
59    let status = updater::check_for_update(&app).await?;
60
61    // Emit the terminal state.
62    let _ = events::emit(&app, EventKind::UpdaterStatus, &status);
63
64    Ok(status)
65}
66
67// ---------------------------------------------------------------------------
68// updater_install
69// ---------------------------------------------------------------------------
70
71/// Download and install the pending update.
72///
73/// Must be called after `updater_check` returned `Available`.
74///
75/// Emits `updater:status` events:
76///   1. `{ "status": "downloading", "progress": null }` — download started.
77///   2. `{ "status": "ready" }` — download + install complete; restart pending.
78///   3. `{ "status": "error", "message": "…" }` — on any failure.
79#[tauri::command]
80pub async fn updater_install(app: AppHandle) -> Result<(), AppError> {
81    let _ = events::emit(
82        &app,
83        EventKind::UpdaterStatus,
84        &UpdateStatus::Downloading { progress: None },
85    );
86
87    match updater::install_update(&app).await {
88        Ok(()) => {
89            let _ = events::emit(&app, EventKind::UpdaterStatus, &UpdateStatus::Ready);
90            Ok(())
91        }
92        Err(e) => {
93            let status = UpdateStatus::Error {
94                message: e.message(),
95            };
96            let _ = events::emit(&app, EventKind::UpdaterStatus, &status);
97            Err(e)
98        }
99    }
100}