Repository Public
1'use client';2import { useConn } from '@/stores/conn';3import { Tooltip } from '@/components/ui/tooltip';4import { Wifi, WifiOff } from 'lucide-react';5import { Dot, type Tone } from '@/components/ui/badge';6import { cn } from '@/lib/cn';78/** Live connection state of the events channel. */9export function useConnectionSummary(): { tone: Tone; label: string; detail: string; pulse: boolean } {10 const { events, online } = useConn();11 if (!online) return { tone: 'error', label: 'Offline', detail: 'No network. Missions keep running on the server.', pulse: false };12 if (events !== 'open') return { tone: 'warning', label: events === 'connecting' ? 'Connecting' : 'Reconnecting', detail: 'Live updates are not connected; the console resumes from the last event it received.', pulse: true };13 return { tone: 'success', label: 'Live', detail: 'Live updates connected.', pulse: false };14}1516export function ConnectionIndicator({ compact, className }: { compact?: boolean; className?: string }) {17 const s = useConnectionSummary();18 return (19 <Tooltip content={s.detail}>20 <span role="status" aria-label={`Connection: ${s.label}`} data-testid="conn-indicator" data-tone={s.tone} className={cn('tnum inline-flex items-center gap-1.5 text-[11px] text-text-2', className)}>21 {compact ? (22 // an icon, not a dot: on phones it sits in the title bar23 s.tone === 'error' ? <WifiOff className="size-4 text-error" aria-hidden /> : <Wifi className={cn('size-4', s.tone === 'success' ? 'text-success' : 'text-warning', s.pulse && 'anim-pulse')} aria-hidden />24 ) : (25 <>26 <Dot tone={s.tone} pulse={s.pulse} />27 {s.label}28 </>29 )}30 </span>31 </Tooltip>32 );33}34