import { useEffect, useRef, useState } from "react"; import * as Y from "yjs"; import { WebsocketProvider } from "y-websocket"; const COLORS = [ "#ef4444", "#f97316", "#eab308", "#22c55e", "#06b6d4", "#3b82f6", "#8b5cf6", "#ec4899", ]; const NAMES = [ "Hiker", "Cyclist", "Runner", "Explorer", "Wanderer", "Pathfinder", "Trailblazer", "Navigator", ]; function randomItem(arr: T[]): T { return arr[Math.floor(Math.random() * arr.length)]!; } function getOrCreateUserIdentity(): { color: string; name: string } { try { const stored = localStorage.getItem("trails:user"); if (stored) return JSON.parse(stored); } catch { /* localStorage unavailable */ } const identity = { color: randomItem(COLORS), name: randomItem(NAMES) }; try { localStorage.setItem("trails:user", JSON.stringify(identity)); } catch { /* localStorage unavailable */ } return identity; } export interface YjsState { doc: Y.Doc; provider: WebsocketProvider; waypoints: Y.Array>; routeData: Y.Map; awareness: WebsocketProvider["awareness"]; connected: boolean; } export function useYjs(sessionId: string): YjsState | null { const [state, setState] = useState(null); const providerRef = useRef(null); const docRef = useRef(null); useEffect(() => { const doc = new Y.Doc(); docRef.current = doc; const wsUrl = `${window.location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/sync`; const provider = new WebsocketProvider(wsUrl, sessionId, doc); providerRef.current = provider; const waypoints = doc.getArray>("waypoints"); const routeData = doc.getMap("routeData"); // Use persistent identity const { color, name } = getOrCreateUserIdentity(); provider.awareness.setLocalStateField("user", { color, name }); const updateState = (connected: boolean) => { setState({ doc, provider, waypoints, routeData, awareness: provider.awareness, connected, }); }; provider.on("status", ({ status }: { status: string }) => { updateState(status === "connected"); }); updateState(false); return () => { provider.destroy(); doc.destroy(); providerRef.current = null; docRef.current = null; }; }, [sessionId]); return state; }