import { createContext, useState, useEffect, useCallback, useRef } from 'react'; import { io } from 'socket.io-client'; export const SocketContext = createContext(); export const SocketProvider = ({ children }) => { const [socket, setSocket] = useState(null); const [connected, setConnected] = useState(false); const connectAttempts = useRef(0); const maxAttempts = 3; const reconnectDelay = 2000; // ms // Connect to socket server const connect = useCallback(() => { if (socket) return; // Determine server URL based on environment const serverUrl = process.env.NODE_ENV === 'production' ? window.location.origin : 'http://localhost:5287'; try { const newSocket = io(serverUrl, { reconnectionAttempts: 3, timeout: 10000, reconnectionDelay: 1000 }); newSocket.on('connect', () => { console.log('Socket connected with ID:', newSocket.id); setConnected(true); connectAttempts.current = 0; // Store player ID in localStorage for persistence localStorage.setItem('playerId', newSocket.id); }); newSocket.on('disconnect', (reason) => { console.log('Socket disconnected:', reason); setConnected(false); }); newSocket.on('connect_error', (error) => { console.error('Connection error:', error); connectAttempts.current += 1; if (connectAttempts.current >= maxAttempts) { console.error('Max connection attempts reached, giving up'); newSocket.disconnect(); } }); setSocket(newSocket); } catch (err) { console.error('Error creating socket connection:', err); } }, [socket]); // Disconnect socket const disconnect = useCallback(() => { if (socket) { socket.disconnect(); setSocket(null); setConnected(false); console.log('Socket manually disconnected'); } }, [socket]); // Send event through socket const send = useCallback((event, data) => { if (!socket || !connected) { console.warn(`Cannot send event "${event}": socket not connected`); return false; } try { socket.emit(event, data); return true; } catch (err) { console.error(`Error sending event "${event}":`, err); return false; } }, [socket, connected]); // Register event listener const on = useCallback((event, callback) => { if (!socket) { console.warn(`Cannot listen for event "${event}": socket not initialized`); return () => {}; } socket.on(event, callback); return () => socket.off(event, callback); }, [socket]); // Clean up socket on component unmount useEffect(() => { return () => { if (socket) { socket.disconnect(); } }; }, [socket]); return ( {children} ); };