import { io } from 'socket.io-client'; const WS_URL = import.meta.env.VITE_WS_URL || 'http://localhost:3000'; class SocketService { constructor() { this.socket = null; this.listeners = new Map(); } connect() { if (this.socket?.connected) { return this.socket; } this.socket = io(WS_URL, { withCredentials: true, transports: ['websocket', 'polling'], }); this.socket.on('connect', () => { console.log('WebSocket connected:', this.socket.id); }); this.socket.on('disconnect', () => { console.log('WebSocket disconnected'); }); this.socket.on('error', (error) => { console.error('WebSocket error:', error); }); return this.socket; } disconnect() { if (this.socket) { this.socket.disconnect(); this.socket = null; } } on(event, callback) { if (!this.socket) { this.connect(); } this.socket.on(event, callback); if (!this.listeners.has(event)) { this.listeners.set(event, []); } this.listeners.get(event).push(callback); } off(event, callback) { if (this.socket) { this.socket.off(event, callback); } if (this.listeners.has(event)) { const callbacks = this.listeners.get(event); const index = callbacks.indexOf(callback); if (index > -1) { callbacks.splice(index, 1); } } } emit(event, data) { if (!this.socket) { this.connect(); } this.socket.emit(event, data); } onReconnect(callback) { if (!this.socket) { this.connect(); } // Слушаем событие 'connect' которое происходит при переподключении this.socket.on('connect', callback); } offReconnect(callback) { if (this.socket) { this.socket.off('connect', callback); } } // Game-specific methods joinRoom(roomCode, userId) { this.emit('joinRoom', { roomCode, userId }); } startGame(roomId, roomCode, userId) { this.emit('startGame', { roomId, roomCode, userId }); } endGame(roomId, roomCode, userId) { this.emit('endGame', { roomId, roomCode, userId }); } // Note: Game actions now use 'playerAction' event with UUID // Direct emit is preferred over these helper methods // Example: socketService.emit('playerAction', { action: 'revealAnswer', ... }) updateRoomPack(roomId, roomCode, userId, questions) { this.emit('updateRoomPack', { roomId, roomCode, userId, questions }); } importQuestions(roomId, roomCode, userId, sourcePackId, questionIndices) { this.emit('importQuestions', { roomId, roomCode, userId, sourcePackId, questionIndices, }); } updatePlayerName(roomId, roomCode, userId, participantId, newName) { this.emit('updatePlayerName', { roomId, roomCode, userId, participantId, newName, }); } updatePlayerScore(roomId, roomCode, userId, participantId, newScore) { this.emit('updatePlayerScore', { roomId, roomCode, userId, participantId, newScore, }); } changeRoomTheme(roomId, roomCode, userId, themeId) { this.emit('changeRoomTheme', { roomId, roomCode, userId, themeId, }); } changeParticipantRole(roomId, roomCode, userId, participantId, newRole) { this.emit('changeParticipantRole', { roomId, roomCode, userId, participantId, newRole, }); } toggleParticles(roomId, roomCode, userId, particlesEnabled) { this.emit('toggleParticles', { roomId, roomCode, userId, particlesEnabled, }); } } export default new SocketService();