feat(kiosk): launch the UI in a pinned Electron shell - #260
Conversation
start-kiosk.sh previously shelled out to whichever of chromium-browser/chromium/google-chrome/firefox happened to be installed. Add an Electron kiosk shell (ui/electron/main.cjs) that loads the same URL in a pinned, chromeless BrowserWindow, and make it the default; the old browser detection remains only as a fallback if Electron isn't installed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QvFHgWxQdwJCQNZ1DRg2B
Explain why Electron replaces ad hoc system-browser detection (pinned runtime, consistent kiosk lockdown, single code path, main-process OS access), and sketch two designs for self-updating later: a main-process git-pull-driven update (recommended first) versus a packaged electron-builder/electron-updater release pipeline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015QvFHgWxQdwJCQNZ1DRg2B
…atibility with Electron 44.
…-shell Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # ui/package-lock.json # ui/package.json
…te related documentation
There was a problem hiding this comment.
🟡 Changes recommended
The new Node.js version check helper uses sort -V, which will break setup/kiosk flows on macOS where GNU sort -V is not available by default.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR pins the kiosk UI runtime by launching the existing Flask-served React UI inside a dedicated Electron shell, making kiosk behavior consistent across OS images while keeping a Chromium fallback when Electron isn’t installed.
Changes:
- Added an Electron main-process kiosk shell (
ui/electron/) with URL resolution logic and Vitest coverage. - Updated kiosk startup/setup scripts to prefer Electron, enforce a Node.js 22.12+ minimum via a shared helper, and improve cleanup/build checks.
- Updated docs to reflect the Electron-based kiosk path and the Node.js version floor.
File summaries
| File | Description |
|---|---|
| ui/vite.config.ts | Expands Vitest include globs to run Electron unit tests. |
| ui/README.md | Updates UI dev prerequisite to Node 22.12+. |
| ui/package.json | Declares Electron entrypoint, Node engine floor, and adds Electron dependency + script. |
| ui/package-lock.json | Locks Electron and related packages; records Node engine constraints. |
| ui/electron/resolveTargetUrl.test.js | Adds Vitest coverage for URL resolution precedence. |
| ui/electron/resolveTargetUrl.js | Adds testable target-URL resolution for the Electron shell. |
| ui/electron/main.js | Implements the fullscreen/kiosk Electron BrowserWindow wrapper. |
| tests/test_start_kiosk.py | Adds regression tests for Electron-first launching, fallback, cleanup, and build checks. |
| scripts/start-kiosk.sh | Prefers Electron shell, falls back to Chromium, and ensures UI+Electron are installed/built. |
| scripts/setup/setup.sh | Uses shared Node version gate (22.12+) during setup. |
| scripts/require-node.sh | Introduces shared Node version check + install hint messaging. |
| README.md | Adds link to the Electron kiosk shell documentation. |
| docs/raspberry-pi-setup.md | Documents installing Node 22.12+ on Raspberry Pi before setup. |
| docs/electron-kiosk-shell.md | Documents rationale for Electron shell and possible future update designs. |
| CONTRIBUTING.md | Updates contributor prereqs to Node 22.12+. |
Review details
Files not reviewed (1)
- ui/package-lock.json: Generated file
- Files reviewed: 14/15 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@jewbetcha The issue this is addressing has already occurred to me after an update: https://discord.com/channels/1512485363875057674/1512488110762754168/1543044121717903491 |
…131/openflight into feat/electron-react-shell
What does this PR do?
scripts/start-kiosk.shused to pick whichever ofchromium-browser/chromium/google-chrome/firefoxwas installed and pass Chromium-oriented--kioskflags. Rendering engine and lockdown then depended on the OS image.This PR adds a small Electron shell (
ui/electron/main.js,electron@44.1.0) that loads the same Flask URL (http://localhost:8080, overridable withOPENFLIGHT_URL) in a chromeless, fullscreenBrowserWindow(kiosk: true, no application menu, popups denied). Electron is the default kiosk path. Ifui/node_modules/.bin/electronis missing, it still falls back tochromium-browserorchromium.The React app, WebSocket client, and Flask server are unchanged: Electron is a window around the existing UI. Auto-update is not implemented;
docs/electron-kiosk-shell.mdrecords why the shell exists and two possible future designs.Installing Electron 44 needs Node.js 22.12+. Setup and kiosk scripts share
scripts/require-node.sh, fail with an install hint when Node is too old, and docs (CONTRIBUTING.md,docs/raspberry-pi-setup.md,ui/README.md) match that floor.Why was this required?
System-browser detection drifted between Pis, kiosk flags were Chromium-specific, and a browser tab cannot later drive OS-level work (for example a main-process updater). A pinned Electron runtime gives every unit the same Chromium, the same lockdown, and a Node main process if self-update is built later. Without this, kiosk behavior keeps depending on whatever browser the image happens to have.
Automated tests
tests/test_start_kiosk.py: Electron is tried before Chromium; Chromium fallback still exists if Electron is missing; cleanuppkills the Electron process tree; the UI-build check also requires the Electron binary.ui/electron/resolveTargetUrl.test.js: default Flask URL;OPENFLIGHT_URLwins over the CLI arg; empty env falls through to the CLI arg. URL resolution lives inresolveTargetUrl.jsso Vitest can run without importingelectron(which throws outside a real runtime).Manual (human) testing
Ran the kiosk on Raspberry Pi hardware with no radar attached. Confirmed scripts/start-kiosk.sh starts the Electron shell fullscreen on the Pi display and the React UI loads from Flask (http://localhost:8080) without needing a system Chromium/Firefox window. Shot capture was not exercised (no radar). Did not re-test Chromium fallback or a too-old Node install on this unit.
AI assistance
I specified and designed this change (Electron as the kiosk shell, Chromium fallback, Node 22.12 floor, no auto-update in this PR). Claude drafted the implementation (
ui/electron/,start-kiosk.shlaunch/cleanup,docs/electron-kiosk-shell.md) and the first cut of the automated tests (including the ESM split so URL resolution can be tested without importingelectron). Cursor Grok ported those tests onto this branch and drafted the CHANGELOG entry.I reviewed the change and manually tested it on Pi hardware without radar attached:
start-kiosk.shopened the Electron window fullscreen and the Flask UI loaded. I am responsible for the submitted work under AI-POLICY.md.Checklist
uv run pytest tests/ -v)uv run pylint src/openflight/ --fail-under=9)uv run ruff check src/openflight/)cd ui && npm run build)cd ui && npm run lint)