import { useEffect, useState } from 'react'; import { onRealtimeStatus } from './api'; // Grace period before a missing realtime connection counts as offline (app start, short reconnects) export const SERVER_OFFLINE_GRACE_MS = 4000; // Whether the server is reachable, judged by the app-wide realtime connection (WebSocket/SSE). Unlike // navigator.onLine it also notices a server that is down while the device still has network. Without // device network it is offline right away; otherwise only after the connection stayed away for a moment. export function useServerOnline(): boolean { const [online, setOnline] = useState(true); useEffect(() => { let connected = false; let timer: number | undefined; // Reconnect attempts report "not connected" every few seconds; they must not restart the grace period const update = () => { if (connected) { window.clearTimeout(timer); timer = undefined; setOnline(true); } else if (navigator.onLine === false) { window.clearTimeout(timer); timer = undefined; setOnline(false); } else if (timer === undefined) { timer = window.setTimeout(() => setOnline(false), SERVER_OFFLINE_GRACE_MS); } }; const unsubscribe = onRealtimeStatus((isConnected) => { connected = isConnected; update(); }); window.addEventListener('online', update); window.addEventListener('offline', update); return () => { unsubscribe(); window.clearTimeout(timer); window.removeEventListener('online', update); window.removeEventListener('offline', update); }; }, []); return online; }