From 56904422af22e76aa5308c2990fe3c48334419b3 Mon Sep 17 00:00:00 2001 From: Julian Cuni Date: Thu, 3 Sep 2026 16:31:48 +0200 Subject: [PATCH] feat(desktop): show the installed app's own version in the UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing displayed which desktop build was actually installed — debugging a stuck update meant inferring the current version backwards from the update prompt's target version. Added DesktopVersionBadge (next to the existing server-side VersionBadge) using @tauri-apps/api's getVersion(), the real running app version baked in from tauri.conf.json. No-ops in a browser. Exported inTauri() from origin.ts instead of redefining it again. --- apps/web/package.json | 1 + apps/web/src/lib/origin.ts | 2 +- apps/web/src/router.tsx | 27 ++++++++++++++++++++++++++- pnpm-lock.yaml | 3 +++ wiki/decisions/desktop-shell-tauri.md | 10 ++++++++++ wiki/log.md | 9 +++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index f3b9f02..0eb0686 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -18,6 +18,7 @@ "@radix-ui/react-tabs": "^1.1.15", "@tanstack/react-query": "^5.101.0", "@tanstack/react-router": "^1.170.16", + "@tauri-apps/api": "^2.11.1", "@tauri-apps/plugin-http": "^2.5.2", "@tauri-apps/plugin-process": "^2.3.1", "@tauri-apps/plugin-updater": "^2.10.1", diff --git a/apps/web/src/lib/origin.ts b/apps/web/src/lib/origin.ts index 41d947b..4fda7df 100644 --- a/apps/web/src/lib/origin.ts +++ b/apps/web/src/lib/origin.ts @@ -39,7 +39,7 @@ export function wsUrl(path: string): string { } /** True when running inside the Tauri webview (not a normal browser). */ -function inTauri(): boolean { +export function inTauri(): boolean { return typeof window !== "undefined" && "__TAURI_INTERNALS__" in window; } diff --git a/apps/web/src/router.tsx b/apps/web/src/router.tsx index 1a87f7f..12ab48d 100644 --- a/apps/web/src/router.tsx +++ b/apps/web/src/router.tsx @@ -6,7 +6,7 @@ import { Outlet, redirect, } from "@tanstack/react-router"; -import { lazy, Suspense, useState } from "react"; +import { lazy, Suspense, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import type { Lang, Permission, SessionUser, Theme } from "./api.js"; @@ -30,6 +30,7 @@ import { Spinner } from "./ui/Spinner.js"; import { setLanguage } from "./lib/i18n/index.js"; import { applyTheme, applyFontScale } from "./lib/theme.js"; import { useLiveFeed } from "./lib/use-live-feed.js"; +import { inTauri } from "./lib/origin.js"; import { useShift } from "./lib/use-shift.js"; import { DeviceFooter } from "./ui/DeviceFooter.js"; import { StatusDot } from "./ui/StatusDot.js"; @@ -106,6 +107,29 @@ function VersionBadge() { return {version}; } +/** The installed Tauri app's own "vX.Y.Z" (from tauri.conf.json, synced to the git tag by + * release.yml — see wiki/decisions/desktop-shell-tauri.md) — the client's version, distinct + * from VersionBadge's SERVER build. No-op / renders nothing in a browser (there's no Tauri + * API to call). Was invisible before this: an operator had no way to tell which desktop + * build was actually installed short of reading the update-available prompt. */ +function DesktopVersionBadge() { + const [version, setVersion] = useState(null); + useEffect(() => { + if (!inTauri()) return; + let cancelled = false; + void import("@tauri-apps/api/app").then(({ getVersion }) => + getVersion().then((v) => { + if (!cancelled) setVersion(v); + }), + ); + return () => { + cancelled = true; + }; + }, []); + if (!version) return null; + return app v{version}; +} + /** Setup layout — the config hub. Renders a permission-gated tab bar and the active * tab's screen via . Each tab is a child route (its own URL + guard), so * deep links and the back button work and a denied tab redirects to the booth. */ @@ -125,6 +149,7 @@ function SetupLayout() { {show("log:read") && } {show("backup:read") && } {show("site:read") && } + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1a25da..8697c72 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,6 +108,9 @@ importers: '@tanstack/react-router': specifier: ^1.170.16 version: 1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@tauri-apps/api': + specifier: ^2.11.1 + version: 2.11.1 '@tauri-apps/plugin-http': specifier: ^2.5.2 version: 2.6.0 diff --git a/wiki/decisions/desktop-shell-tauri.md b/wiki/decisions/desktop-shell-tauri.md index b4bb638..630883f 100644 --- a/wiki/decisions/desktop-shell-tauri.md +++ b/wiki/decisions/desktop-shell-tauri.md @@ -178,6 +178,16 @@ Per the user's choices — the operator **keeps OS access** (no fullscreen lockd together; a `resources.toml` change still needs a Komodo sync + Stack redeploy to take effect on a live booth, it isn't automatic from a git push alone — and see [[fleet-deployment-komodo]] for a real ResourceSync-branch gotcha this exact fix ran into. +- **No way to see the installed app's own version (found + fixed 2026-09-03).** `VersionBadge` in + `router.tsx` shows the *server's* `-` (from `/api/version`, gated `site:read`) — but + nothing showed the *desktop client's* own version. An operator debugging a stuck update had no way + to confirm which build was actually installed short of reading the update-available prompt's + target version and inferring backwards. Fixed with `DesktopVersionBadge`, next to `VersionBadge`: + calls `@tauri-apps/api/app`'s `getVersion()` (the real running app's version, baked in from + `tauri.conf.json` — synced to the git tag by `release.yml`, see the version-drift gotcha above), + no-ops/renders nothing in a browser (`inTauri()` guard, now exported from `origin.ts` instead of + redefined a 4th time). `@tauri-apps/api` added as an explicit dependency (was only ever transitive + via the plugins). - **`VITE_API_BASE` — desktop vs. browser (regression found + fixed 2026-09-03):** `apps/web/.env.production` (committed, shared by both builds) sets `VITE_API_BASE=` (empty) — this is correct for the **browser/booth** build (Fastify same-origin, stays relative) since commit diff --git a/wiki/log.md b/wiki/log.md index d4ec173..22ec5f5 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -2808,3 +2808,12 @@ and fixed a real, pre-existing Komodo ResourceSync misconfig (resource-sync-park `dev`, not `stage`, silently reading resources.toml from the wrong branch for months with zero effect until dev/stage first diverged today) — full writeup on [[fleet-deployment-komodo]], which had already warned about exactly this gotcha back in 2026-07-07 and it happened anyway. + +## [2026-09-03] feat | Desktop app version now visible in the UI (was invisible) + +There was no way to see which desktop build was actually installed anywhere in the app — an +operator debugging a stuck update had to infer it backwards from the update prompt's target +version ("it's offering v0.1.4, so I must be on v0.1.3"). Added DesktopVersionBadge next to the +existing server-side VersionBadge in router.tsx, using @tauri-apps/api's getVersion() (the real +running app version, synced to the git tag at build time by release.yml). No-ops in a browser. +Full detail on [[desktop-shell-tauri]].