import 'dart:async'; import 'dart:convert'; import 'package:web_socket_channel/web_socket_channel.dart'; import '../config/api_config.dart'; enum ChatConnectionState { disconnected, connecting, connected, error, } class ChatService { WebSocketChannel? _channel; String? _token; final _messageController = StreamController>.broadcast(); final _stateController = StreamController.broadcast(); Stream> get messages => _messageController.stream; Stream get connectionState => _stateController.stream; ChatConnectionState _currentState = ChatConnectionState.disconnected; ChatConnectionState get currentState => _currentState; void setToken(String? token) { _token = token; } Future connect() async { if (_token == null) { _updateState(ChatConnectionState.error); return; } _updateState(ChatConnectionState.connecting); try { final uri = Uri.parse('${ApiConfig.wsUrl}${ApiConfig.wsChat}'); _channel = WebSocketChannel.connect(uri); await _channel!.ready; // Send auth token _channel!.sink.add(jsonEncode({'token': _token})); _channel!.stream.listen( (data) { try { final message = jsonDecode(data); if (message['type'] == 'connected') { _updateState(ChatConnectionState.connected); } _messageController.add(message); } catch (e) { // Handle parse error } }, onError: (error) { _updateState(ChatConnectionState.error); }, onDone: () { _updateState(ChatConnectionState.disconnected); }, ); } catch (e) { _updateState(ChatConnectionState.error); } } void sendMessage(String content, {List? files}) { if (_channel == null || _currentState != ChatConnectionState.connected) { return; } _channel!.sink.add(jsonEncode({ 'type': 'message', 'content': content, 'files': files ?? [], })); } void ping() { if (_channel != null && _currentState == ChatConnectionState.connected) { _channel!.sink.add(jsonEncode({'type': 'ping'})); } } void _updateState(ChatConnectionState state) { _currentState = state; _stateController.add(state); } void disconnect() { _channel?.sink.close(); _channel = null; _updateState(ChatConnectionState.disconnected); } void dispose() { disconnect(); _messageController.close(); _stateController.close(); } }