import { state } from './state.js'; let ws; let reconnectAttempts = 0; let reconnectTimer = null; const outbox = []; let sessionId = localStorage.getItem('sessionId') || null; let lastRoomId = localStorage.getItem('lastRoomId') || null; export function wsIsOpen() { return ws && ws.readyState === WebSocket.OPEN; } export function sendMsg(obj) { if (wsIsOpen()) ws.send(JSON.stringify(obj)); else outbox.push(obj); } function scheduleReconnect(connect) { if (reconnectTimer) return; const delay = Math.min(30000, 1000 * Math.pow(2, reconnectAttempts)); reconnectAttempts++; reconnectTimer = setTimeout(() => { reconnectTimer = null; connect(); }, delay); } export function connectWS(onMessage) { const url = (location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host; ws = new WebSocket(url); ws.addEventListener('open', () => { reconnectAttempts = 0; // Try to resume session immediately on (re)connect if (sessionId) { try { ws.send(JSON.stringify({ type: 'resume', sessionId })); } catch {} } setTimeout(() => { while (outbox.length && wsIsOpen()) { try { ws.send(JSON.stringify(outbox.shift())); } catch { break; } } }, 100); }); ws.addEventListener('message', (ev) => onMessage(ev)); ws.addEventListener('close', () => { scheduleReconnect(() => connectWS(onMessage)); }); ws.addEventListener('error', () => { try { ws.close(); } catch {} }); } window.addEventListener('online', () => { if (!wsIsOpen()) { if (reconnectTimer) { clearTimeout(reconnectTimer); reconnectTimer = null; } // Kick off a reconnect by calling connectWS from app main again } }); // Helpers to update cached ids from other modules export function cacheSessionId(id) { if (!id) return; sessionId = id; try { localStorage.setItem('sessionId', id); } catch {} } export function cacheLastRoomId(id) { if (!id) return; lastRoomId = id; try { localStorage.setItem('lastRoomId', id); } catch {} }