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 (