// Global connectivity signal. `online` is false while the app is actively failing to // reach the gateway — a unary call retrying after a transport/rate-limit failure, or the live // stream dropped. The transport and the live-stream owner report transitions; the UI reads // `connection.online` to show the "Connecting…" indicator and to softly disable proactive // actions. In mock mode nothing ever reports trouble, so it simply stays online. // // Recovery is guaranteed by a reachability watcher: while offline it periodically fires a // registered probe (a lightweight read) until one succeeds, so the indicator clears even when no // other traffic is in flight. import { backoffMs } from './retry'; let online = $state(true); let watchTimer: ReturnType | null = null; let probe: (() => Promise) | null = null; export const connection = { /** online is true when the app believes it can reach the gateway. */ get online(): boolean { return online; }, }; /** registerProbe installs the reachability probe the watcher fires while offline. The transport * wires a cheap authenticated read; it should reject when there is no session. */ export function registerProbe(fn: () => Promise): void { probe = fn; } /** reportOnline marks the gateway reachable and stops the watcher. */ export function reportOnline(): void { online = true; if (watchTimer) { clearTimeout(watchTimer); watchTimer = null; } } /** reportOffline marks the gateway unreachable and starts the reachability watcher (once). */ export function reportOffline(): void { online = false; if (!watchTimer && probe) scheduleProbe(1); } /** resetConnection restores the online state and stops the watcher (e.g. on logout). */ export function resetConnection(): void { reportOnline(); } function scheduleProbe(attempt: number): void { watchTimer = setTimeout( () => { watchTimer = null; if (online || !probe) return; probe().then(reportOnline, () => scheduleProbe(Math.min(attempt + 1, 6))); }, backoffMs(attempt), ); }