From 9b4e49b80179f3f4258a3befc83d1952ac580a25 Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Thu, 27 Aug 2026 09:34:35 +0000 Subject: [PATCH] Fix kiosk 'Install' installing the main hvac app instead The whole hvac SPA shares one index.html/, so 'Install' from any route always used the main manifest (start_url '/hvac/', staff AuthGate) -- hit 2026-08-26, installing from /hvac/kiosk opened the staff login instead of the kiosk password prompt. Fix: new static kiosk-manifest.webmanifest (start_url/scope '/hvac/kiosk', name 'HVAC Kiosk'), swapped into the document's manifest link while the Kiosk route is mounted (useKioskManifest hook), restored on unmount. Reuses the existing hvac icon set. Co-Authored-By: Claude Sonnet 5 --- frontend/public/kiosk-manifest.webmanifest | 13 +++++++++++++ frontend/src/pages/Kiosk.tsx | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 frontend/public/kiosk-manifest.webmanifest diff --git a/frontend/public/kiosk-manifest.webmanifest b/frontend/public/kiosk-manifest.webmanifest new file mode 100644 index 0000000..4bdbf1b --- /dev/null +++ b/frontend/public/kiosk-manifest.webmanifest @@ -0,0 +1,13 @@ +{ + "name": "HVAC Kiosk", + "short_name": "HVAC Kiosk", + "start_url": "/hvac/kiosk", + "scope": "/hvac/kiosk", + "display": "standalone", + "theme_color": "#c1440e", + "background_color": "#c1440e", + "icons": [ + { "src": "/hvac/icons/icon-192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "/hvac/icons/icon-512.png", "sizes": "512x512", "type": "image/png" } + ] +} diff --git a/frontend/src/pages/Kiosk.tsx b/frontend/src/pages/Kiosk.tsx index b9c8629..dc7047f 100644 --- a/frontend/src/pages/Kiosk.tsx +++ b/frontend/src/pages/Kiosk.tsx @@ -17,6 +17,23 @@ function liveDevicesOf(zone: ZoneStatus): DeviceSummary[] { return zone.devices.filter(d => KIOSK_DEVICE_TYPES.includes(d.device_type)) } +// The whole hvac SPA shares one index.html, so there's only one in the document — "Install" from any route otherwise always +// installs the main app (start_url '/hvac/', staff login). Swap it to a +// kiosk-specific manifest (start_url/scope '/hvac/kiosk') while this route is +// mounted, so installing from here opens straight back into the kiosk and its +// own password prompt instead — restore it on unmount in case something ever +// navigates away client-side rather than via a full page load. +function useKioskManifest() { + useEffect(() => { + const link = document.querySelector('link[rel="manifest"]') + if (!link) return + const original = link.href + link.href = '/hvac/kiosk-manifest.webmanifest' + return () => { link.href = original } + }, []) +} + // The wall-panel kiosk view — a dedicated route/login, deliberately outside the // normal staff AuthGate/Layout (see App.tsx). One master panel: one tile per // ROOM/ZONE (same as the Dashboard's ZoneCard — a room's TRV and AC show @@ -25,6 +42,8 @@ function liveDevicesOf(zone: ZoneStatus): DeviceSummary[] { // across zones. See project_hvac_kiosk memory for the design decisions behind // this (access model, layout, bulk-edit mechanism). export default function Kiosk() { + useKioskManifest() + const [authState, setAuthState] = useState<'checking' | 'login' | 'authed'>('checking') const [password, setPassword] = useState('') const [loginError, setLoginError] = useState('')