import { useEffect, useRef, useState } from 'react'; import { io } from 'socket.io-client'; import { api } from './api.js'; let shared = null; export function getSocket() { if (!shared) shared = io({ path: '/socket.io', transports: ['websocket', 'polling'] }); return shared; } /** Abonniert den Live-Zustand eines Matches. Meldet sich nach jedem Reconnect neu an. */ export function useMatch(matchId, token) { const [state, setState] = useState(null); const [error, setError] = useState(null); const [connected, setConnected] = useState(false); const tokenRef = useRef(token); tokenRef.current = token; useEffect(() => { const socket = getSocket(); const subscribe = () => socket.emit('match:subscribe', { matchId, token: tokenRef.current }); const onState = (s) => { if (s.id !== matchId) return; setState(s); setError(null); }; const onError = (e) => setError(e); const onConnect = () => { setConnected(true); subscribe(); }; const onDisconnect = () => setConnected(false); socket.on('match:state', onState); socket.on('match:error', onError); socket.on('connect', onConnect); socket.on('disconnect', onDisconnect); if (socket.connected) onConnect(); // Erster Stand per REST, falls der Socket noch verbindet; neuere Socket-Stände haben Vorrang. let active = true; api(`/matches/${matchId}`, { token }) .then((s) => active && setState((prev) => (prev && prev.updatedAt >= s.updatedAt ? prev : s))) .catch((e) => active && setError({ error: e.message, code: e.code })); return () => { active = false; socket.off('match:state', onState); socket.off('match:error', onError); socket.off('connect', onConnect); socket.off('disconnect', onDisconnect); }; }, [matchId, token]); return { state, error, connected }; } export function useOverview() { const [matches, setMatches] = useState(null); const [connected, setConnected] = useState(false); useEffect(() => { const socket = getSocket(); const onConnect = () => { setConnected(true); socket.emit('overview:subscribe'); }; const onOverview = (d) => setMatches(d.matches); const onDisconnect = () => setConnected(false); socket.on('overview', onOverview); socket.on('connect', onConnect); socket.on('disconnect', onDisconnect); if (socket.connected) onConnect(); return () => { socket.off('overview', onOverview); socket.off('connect', onConnect); socket.off('disconnect', onDisconnect); }; }, []); return { matches, connected }; }