Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 4,805 Bytes
5acd9c3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
// lib/services/chat_service.dart
import 'dart:async';
import 'dart:math';
import 'package:aitube2/services/websocket_api_service.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
import '../models/chat_message.dart';
class ChatService {
static final ChatService _instance = ChatService._internal();
factory ChatService() => _instance;
ChatService._internal();
static const _userIdKey = 'chat_user_id';
static const _usernameKey = 'chat_username';
static const _userColorKey = 'chat_user_color';
final _chatController = StreamController<ChatMessage>.broadcast();
Stream<ChatMessage> get chatStream => _chatController.stream;
final WebSocketApiService _websocketService = WebSocketApiService();
String? _userId;
String? _username;
String? _userColor;
String? _currentRoomId;
bool _isInitialized = false;
Future<void> initialize() async {
if (_isInitialized) return;
final prefs = await SharedPreferences.getInstance();
_userId = prefs.getString(_userIdKey);
_username = prefs.getString(_usernameKey);
_userColor = prefs.getString(_userColorKey);
if (_userId == null) {
_userId = const Uuid().v4();
_username = 'User${_userId!.substring(0, 4)}';
_userColor = _generateRandomColor();
await prefs.setString(_userIdKey, _userId!);
await prefs.setString(_usernameKey, _username!);
await prefs.setString(_userColorKey, _userColor!);
}
// Set up message handling before attempting to join
_websocketService.chatStream.listen(_handleChatMessage);
_isInitialized = true;
}
Future<void> joinRoom(String videoId) async {
if (_currentRoomId == videoId) return; // Already in this room
try {
// Leave current room if in one
if (_currentRoomId != null) {
await leaveRoom(_currentRoomId!);
}
// Initialize if needed
if (!_isInitialized) {
await initialize();
}
await _websocketService.joinChatRoom(videoId);
_currentRoomId = videoId;
debugPrint('Successfully joined chat room for video: $videoId');
} catch (e) {
debugPrint('Error joining chat room: $e');
rethrow;
}
}
Future<void> leaveRoom(String videoId) async {
if (_currentRoomId == videoId && _websocketService.isConnected) {
await _websocketService.leaveChatRoom(videoId);
_currentRoomId = null;
debugPrint('Left chat room for video: $videoId');
}
}
String _generateRandomColor() {
final colors = [
'#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4',
'#FFEEAD', '#D4A5A5', '#9B9B9B', '#A8E6CF'
];
return colors[Random().nextInt(colors.length)];
}
Future<bool> sendMessage(String content, String videoId) async {
if (content.trim().isEmpty) return false;
if (content.length > 256) {
content = content.substring(0, 256);
}
try {
debugPrint('ChatService: Attempting to send message to room $videoId');
if (_currentRoomId != videoId) {
debugPrint('ChatService: Not in correct room, joining...');
await joinRoom(videoId);
}
if (!_websocketService.isConnected) {
debugPrint('ChatService: WebSocket not connected, attempting to connect...');
await _websocketService.connect();
}
final message = ChatMessage(
userId: _userId!,
username: _username!,
content: content,
videoId: videoId,
color: _userColor,
);
debugPrint('ChatService: Sending message via WebSocket...');
await _websocketService.sendChatMessage(message);
debugPrint('ChatService: Message sent successfully');
return true;
} catch (e) {
debugPrint('ChatService: Error sending message: $e');
if (e is TimeoutException) {
// Try to reconnect on timeout
debugPrint('ChatService: Timeout occurred, attempting to reconnect...');
try {
await _websocketService.connect();
debugPrint('ChatService: Reconnected, retrying message send...');
return sendMessage(content, videoId); // Retry once
} catch (reconnectError) {
debugPrint('ChatService: Reconnection failed: $reconnectError');
}
}
return false;
}
}
void _handleChatMessage(ChatMessage message) {
// Only add messages if they're for the current room
if (message.videoId == _currentRoomId) {
_chatController.add(message);
debugPrint('Received chat message: ${message.id} from ${message.username}');
}
}
void dispose() {
if (_currentRoomId != null) {
leaveRoom(_currentRoomId!);
}
_chatController.close();
_isInitialized = false;
}
}
|