import { IndexeddbPersistence } from "y-indexeddb"; import { WebrtcProvider } from "y-webrtc"; import * as Y from "yjs"; import type { ConnectionStatus, OptionRecord } from "./state"; export interface AppSync { doc: Y.Doc; yTitle: Y.Text; options: Y.Map; votes: Y.Map; deadlineMap: Y.Map; provider: WebrtcProvider; persistence: IndexeddbPersistence; getConnectionStatus: () => ConnectionStatus; getPeerCount: () => number; destroy: () => void; } export function initSync(roomId: string): AppSync { const doc = new Y.Doc(); const yTitle = doc.getText("poll-title"); const options = doc.getMap("poll-options"); const votes = doc.getMap("poll-votes"); const deadlineMap = doc.getMap("poll-deadline"); let connectionStatus: ConnectionStatus = navigator.onLine ? "connecting" : "offline"; const provider = new WebrtcProvider(roomId, doc,{ signaling: ["ws://localhost:4444", "ws://lynxpi.ddns.net:4444"] }); const persistence = new IndexeddbPersistence(roomId, doc); const syncConnectionStatus = (status: ConnectionStatus) => { connectionStatus = navigator.onLine ? status : "offline"; }; const handleOnline = () => { syncConnectionStatus(provider.connected ? "connected" : "connecting"); }; const handleOffline = () => { connectionStatus = "offline"; }; provider.on("status", (event: { connected: boolean }) => { syncConnectionStatus(event.connected ? "connected" : "connecting"); }); provider.on("synced", ({ synced }: { synced: boolean }) => { if (synced) syncConnectionStatus("connected"); }); window.addEventListener("online", handleOnline); window.addEventListener("offline", handleOffline); return { doc, yTitle, options, votes, deadlineMap, provider, persistence, getConnectionStatus: () => connectionStatus, getPeerCount: () => { const total = provider.awareness.getStates().size; return Math.max(0, total - 1); }, destroy: () => { window.removeEventListener("online", handleOnline); window.removeEventListener("offline", handleOffline); persistence.destroy(); provider.destroy(); doc.destroy(); }, }; }