/** * ComputerStatusPill (Batch 4) — the header "Studio PC · Online" control. * * Binds to the Batch-2 spine (ComputerContext + HomePilotAccountProvider) and * shows live presence WITHOUT a manual Refresh — the account provider already * polls `/v1/account/mirror/nodes` on an interval (a cloud SSE presence stream * will make this <10s in a later cloud batch). Clicking opens the Journey-B * picker (Automatic / a specific computer); selection updates ComputerContext * only — it does NOT route execution yet (that is Batch 5). * * ADDITIVE: renders `null` unless the Account & Computers flag is on and there * is at least one computer, so dropping it into the header changes nothing by * default. */ import React, { useEffect, useRef, useState } from 'react' import { ChevronDown, Monitor } from 'lucide-react' import { useAccount } from './HomePilotAccountProvider' import { useComputer } from './ComputerContext' import type { PresenceState } from './types' function dotClass(state: PresenceState): string { return state === 'online' ? 'bg-emerald-400' : state === 'attention' ? 'bg-amber-400' : 'bg-white/30' } export function ComputerStatusPill(): JSX.Element | null { const { enabled, computers, loading, refresh } = useAccount() const { selectedComputer, selectionMode, presenceOf, anyOnline, selectComputer, setSelectionMode } = useComputer() const [open, setOpen] = useState(false) const rootRef = useRef(null) useEffect(() => { if (!open) return const onDoc = (e: MouseEvent) => { if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false) } document.addEventListener('mousedown', onDoc) return () => document.removeEventListener('mousedown', onDoc) }, [open]) // Additive: invisible unless enabled and there is something to show. if (!enabled || computers.length === 0) return null // Resolve the pill's label + presence. let label: string let state: PresenceState if (selectionMode === 'fixed' && selectedComputer) { label = selectedComputer.node_name || selectedComputer.node_id state = presenceOf(selectedComputer.node_id) // offline fixed pick → 'offline' (attention) if (state === 'offline') state = 'attention' } else if (computers.length === 1) { const c = computers[0] label = c.node_name || c.node_id state = presenceOf(c.node_id) } else { label = 'Automatic' state = anyOnline ? 'online' : 'offline' } return (
{open && (
{computers.map((c) => { const st = presenceOf(c.node_id) const active = selectionMode === 'fixed' && selectedComputer?.node_id === c.node_id return ( ) })}
{loading ? 'Updating…' : 'Updates automatically'}
)}
) }