import 'dart:async'; import 'dart:convert'; import 'package:web_socket_channel/web_socket_channel.dart'; import '../logging/logger.dart'; class WebSocketManager { static WebSocketManager? _instance; static WebSocketManager get instance => _instance ??= WebSocketManager._(); WebSocketManager._(); final Set _connections = {}; void addConnection(WebSocketChannel channel) { _connections.add(channel); Logger.info('WebSocket connection added. Total connections: ${_connections.length}'); // Listen for messages and connection close channel.stream.listen( (message) { try { final data = jsonDecode(message as String) as Map; final messageType = data['type'] as String?; // Handle ping messages if (messageType == 'ping') { final pongMessage = { 'type': 'pong', 'timestamp': DateTime.now().millisecondsSinceEpoch, }; channel.sink.add(jsonEncode(pongMessage)); } } catch (e) { Logger.error('Error processing WebSocket message: $e'); } }, onDone: () => _removeConnection(channel), onError: (error) { Logger.error('WebSocket connection error: $error'); _removeConnection(channel); }, ); } void _removeConnection(WebSocketChannel channel) { _connections.remove(channel); Logger.info('WebSocket connection removed. Total connections: ${_connections.length}'); } void broadcast(Map message) { if (_connections.isEmpty) { return; } final jsonMessage = jsonEncode(message); final connectionsToRemove = []; for (final connection in _connections) { try { connection.sink.add(jsonMessage); } catch (e) { Logger.error('Failed to send WebSocket message: $e'); connectionsToRemove.add(connection); } } // Remove failed connections for (final connection in connectionsToRemove) { _removeConnection(connection); } } void close() { for (final connection in _connections) { try { connection.sink.close(); } catch (e) { Logger.error('Error closing WebSocket connection: $e'); } } _connections.clear(); Logger.info('All WebSocket connections closed'); } int get connectionCount => _connections.length; bool get hasConnections => _connections.isNotEmpty; }