From 4e5ba634f2c79cbb426e8c3cee135d497ec3a153 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Wed, 26 Aug 2026 21:38:47 +0200 Subject: [PATCH] feat(canvas): the WiFi badge renders pre-Run and can hand its click to an overlay panel The badge used to exist only once a run produced a wifiStatus, which left no stable place to hang a WiFi panel off. It now renders from the moment a radio-capable board is active (disconnected style before a Run), and its click consults window.__velxio_wifi_panel_toggle__ first -- a private overlay claims it for its panel, which carries the gateway-open action forward. OSS builds have no hook, so the badge behaves exactly as always: nothing before an IP, gateway on click after one. --- .../components/simulator/SimulatorCanvas.tsx | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/simulator/SimulatorCanvas.tsx b/frontend/src/components/simulator/SimulatorCanvas.tsx index 1a059895..029055c0 100644 --- a/frontend/src/components/simulator/SimulatorCanvas.tsx +++ b/frontend/src/components/simulator/SimulatorCanvas.tsx @@ -2853,20 +2853,22 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { pairing on velxio.dev). Empty in the OSS build. */} - {/* WiFi status indicator + IoT-gateway launcher (ESP32 + Pico W) */} + {/* WiFi status indicator + IoT-gateway launcher (ESP32 + Pico W). + Renders from the moment a radio-capable board is active — + before a Run it shows as disconnected, so the icon is a + stable place to click (the overlay hangs its panel off it). */} {activeBoard && (isEsp32Kind(activeBoard.boardKind) || activeBoard.boardKind === 'pi-pico-w') && - activeBoard.wifiStatus && (() => { // The Pico W virtual net assigns its IP deterministically when // the sketch connects; the bridge reports 'started' carrying the // IP. Treat that as got_ip so the badge matches the ESP32 (green, // clickable → the same /api/gateway proxy). - const rawStatus = activeBoard.wifiStatus.status; + const rawStatus = activeBoard.wifiStatus?.status ?? 'disconnected'; const status = activeBoard.boardKind === 'pi-pico-w' && rawStatus === 'started' && - activeBoard.wifiStatus.ip + activeBoard.wifiStatus?.ip ? 'got_ip' : rawStatus; const hasIp = status === 'got_ip'; @@ -2878,6 +2880,16 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { const gatewayUrl = `${backendBase}/gateway/${clientId}/`; const openGateway = () => { + // A private overlay can claim the click for its WiFi + // panel (networks on the air, PCAP, local gateway); the + // panel carries the gateway-open action forward. OSS + // builds have no hook -> the badge behaves as always. + const panel = ( + window as unknown as { + __velxio_wifi_panel_toggle__?: () => boolean; + } + ).__velxio_wifi_panel_toggle__; + if (panel && panel()) return; if (!hasIp) return; // A private overlay (velxio.dev) can install a synchronous // gate to keep the IoT gateway behind a paid plan. When it @@ -2907,13 +2919,13 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => { }; return (