feat(canvas): the WiFi badge becomes a split button
David's review of the panel-first click: the one-click "icon -> the board's web page" flow is muscle memory and must not grow a second click. So the badge is now a split button, the standard pattern for primary-action-plus-related-surface: - the WiFi glyph keeps its one-click action: with an IP it opens the IoT gateway exactly as always (in-app iframe or new tab); before an IP it opens the overlay's WiFi panel, since there is nothing else to open yet. - an attached caret is the panel's handle -- always reachable, run or not, which is when PCAP matters most. Touch-friendly and visible, unlike the right-click experiment it replaces. The caret renders only when an overlay installed the panel hook; the OSS build shows exactly the badge it always did.
This commit is contained in:
parent
4e5ba634f2
commit
a765a0ed04
|
|
@ -2879,18 +2879,27 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
||||||
'http://localhost:8001/api';
|
'http://localhost:8001/api';
|
||||||
const gatewayUrl = `${backendBase}/gateway/${clientId}/`;
|
const gatewayUrl = `${backendBase}/gateway/${clientId}/`;
|
||||||
|
|
||||||
const openGateway = () => {
|
const togglePanel = (): boolean => {
|
||||||
// A private overlay can claim the click for its WiFi
|
// A private overlay can hang its WiFi panel (networks on
|
||||||
// panel (networks on the air, PCAP, local gateway); the
|
// the air, PCAP, local gateway) off this badge. OSS
|
||||||
// panel carries the gateway-open action forward. OSS
|
// builds install no hook -> false, nothing happens.
|
||||||
// builds have no hook -> the badge behaves as always.
|
|
||||||
const panel = (
|
const panel = (
|
||||||
window as unknown as {
|
window as unknown as {
|
||||||
__velxio_wifi_panel_toggle__?: () => boolean;
|
__velxio_wifi_panel_toggle__?: () => boolean;
|
||||||
}
|
}
|
||||||
).__velxio_wifi_panel_toggle__;
|
).__velxio_wifi_panel_toggle__;
|
||||||
if (panel && panel()) return;
|
return !!panel && panel();
|
||||||
if (!hasIp) return;
|
};
|
||||||
|
const openGateway = () => {
|
||||||
|
// With an IP, a click opens the board's web server
|
||||||
|
// DIRECTLY — the one-click flow users have muscle
|
||||||
|
// memory for. The panel takes the click only while
|
||||||
|
// there is nothing to open yet, and right-click
|
||||||
|
// reaches it any time.
|
||||||
|
if (!hasIp) {
|
||||||
|
togglePanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// A private overlay (velxio.dev) can install a synchronous
|
// A private overlay (velxio.dev) can install a synchronous
|
||||||
// gate to keep the IoT gateway behind a paid plan. When it
|
// gate to keep the IoT gateway behind a paid plan. When it
|
||||||
// returns true it has already handled the click (e.g. shown
|
// returns true it has already handled the click (e.g. shown
|
||||||
|
|
@ -2918,6 +2927,7 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<span
|
<span
|
||||||
className={`canvas-wifi-badge canvas-wifi-${status}${hasIp || (window as unknown as { __velxio_wifi_panel_toggle__?: unknown }).__velxio_wifi_panel_toggle__ ? ' canvas-wifi-clickable' : ''}`}
|
className={`canvas-wifi-badge canvas-wifi-${status}${hasIp || (window as unknown as { __velxio_wifi_panel_toggle__?: unknown }).__velxio_wifi_panel_toggle__ ? ' canvas-wifi-clickable' : ''}`}
|
||||||
onClick={openGateway}
|
onClick={openGateway}
|
||||||
|
|
@ -2947,6 +2957,28 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
||||||
<circle cx="12" cy="20" r="1" />
|
<circle cx="12" cy="20" r="1" />
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
|
{/* Split-button caret: the badge keeps its one-click
|
||||||
|
gateway action; the caret is the WiFi panel's
|
||||||
|
handle — always reachable, run or not. Rendered
|
||||||
|
only when an overlay installed the panel hook, so
|
||||||
|
the OSS build shows exactly what it always did. */}
|
||||||
|
{(window as unknown as { __velxio_wifi_panel_toggle__?: unknown })
|
||||||
|
.__velxio_wifi_panel_toggle__ ? (
|
||||||
|
<span
|
||||||
|
className={`canvas-wifi-badge canvas-wifi-${status} canvas-wifi-clickable`}
|
||||||
|
style={{ marginLeft: -4, paddingLeft: 2, paddingRight: 4 }}
|
||||||
|
title="WiFi panel"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
togglePanel();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
|
||||||
|
<path d="M6 9l6 6 6-6" />
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue