Разделение навигации и реактивности
This commit is contained in:
@@ -13,6 +13,13 @@ class SignalRService {
|
||||
SignalRService(this.prefs);
|
||||
|
||||
Future<void> init() async {
|
||||
if (_hubConnection?.state == HubConnectionState.Connected ||
|
||||
_hubConnection?.state == HubConnectionState.Connecting) {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Connection already active or connecting. Skipping init.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hubConnection != null) {
|
||||
await stop();
|
||||
}
|
||||
@@ -22,27 +29,48 @@ class SignalRService {
|
||||
if (token == null) return;
|
||||
|
||||
final hubUrl = '${apiUrl.replaceAll(RegExp(r'/+$'), '')}/hubs/chat';
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Initializing connection to: $hubUrl');
|
||||
|
||||
_hubConnection = HubConnectionBuilder()
|
||||
.withUrl(hubUrl, options: HttpConnectionOptions(
|
||||
accessTokenFactory: () async => token,
|
||||
// logging: (level, message) => print('[SignalR] $level: $message'),
|
||||
))
|
||||
.withAutomaticReconnect()
|
||||
.build();
|
||||
|
||||
_hubConnection?.onclose(({error}) {
|
||||
// print('[SignalR] Connection closed: $error');
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Connection closed. Error: $error');
|
||||
});
|
||||
|
||||
_hubConnection?.onreconnecting(({error}) {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Reconnecting... Error: $error');
|
||||
});
|
||||
|
||||
_hubConnection?.onreconnected(({connectionId}) {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Reconnected! ID: $connectionId');
|
||||
});
|
||||
|
||||
// Handle multiple possible event names to be safe
|
||||
_hubConnection?.on('ReceiveMessage', _handleReceiveMessage);
|
||||
_hubConnection?.on('receiveMessage', _handleReceiveMessage);
|
||||
_hubConnection?.on('UserTyping', _handleUserTyping);
|
||||
_hubConnection?.on('user_typing', _handleUserTyping);
|
||||
_hubConnection?.on('UserStoppedTyping', _handleUserStoppedTyping);
|
||||
_hubConnection?.on('user_stopped_typing', _handleUserStoppedTyping);
|
||||
|
||||
try {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Starting connection...');
|
||||
await _hubConnection?.start();
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Connection started successfully. State: ${_hubConnection?.state}');
|
||||
} catch (e) {
|
||||
// ignore
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] Connection failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +78,8 @@ class SignalRService {
|
||||
Stream<Map<String, dynamic>> get typingUpdates => _typingController.stream;
|
||||
|
||||
void _handleUserTyping(List<dynamic>? arguments) {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] _handleUserTyping: $arguments');
|
||||
if (arguments != null && arguments.isNotEmpty) {
|
||||
final data = arguments[0] as Map<String, dynamic>;
|
||||
_typingController.add({'chatId': data['ChatId'] ?? data['chatId'], 'userId': data['UserId'] ?? data['userId'], 'isTyping': true});
|
||||
@@ -57,6 +87,8 @@ class SignalRService {
|
||||
}
|
||||
|
||||
void _handleUserStoppedTyping(List<dynamic>? arguments) {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] _handleUserStoppedTyping: $arguments');
|
||||
if (arguments != null && arguments.isNotEmpty) {
|
||||
final data = arguments[0] as Map<String, dynamic>;
|
||||
_typingController.add({'chatId': data['ChatId'] ?? data['chatId'], 'userId': data['UserId'] ?? data['userId'], 'isTyping': false});
|
||||
@@ -72,13 +104,34 @@ class SignalRService {
|
||||
}
|
||||
|
||||
void _handleReceiveMessage(List<dynamic>? arguments) {
|
||||
// ignore: avoid_print
|
||||
print('[SignalR] _handleReceiveMessage: $arguments');
|
||||
if (arguments != null && arguments.isNotEmpty) {
|
||||
final data = arguments[0] as Map<String, dynamic>;
|
||||
// Map JSON to Message entity and add to stream
|
||||
// I'll need a Message.fromJson mapper
|
||||
final message = Message(
|
||||
id: data['id'] ?? '',
|
||||
chatId: data['chatId'] ?? '',
|
||||
senderId: data['userId'] ?? (data['senderId'] ?? ''),
|
||||
content: data['content'] ?? '',
|
||||
messageType: data['type']?.toString().toLowerCase() ?? 'text',
|
||||
createdAt: _parseDateTime(data['createdAt']),
|
||||
updatedAt: _parseDateTime(data['updatedAt']),
|
||||
isRead: data['isRead'] ?? false,
|
||||
media: data['media'] is Map<String, dynamic> ? data['media'] as Map<String, dynamic> : null,
|
||||
);
|
||||
_messageController.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
DateTime? _parseDateTime(String? dateStr) {
|
||||
if (dateStr == null) return null;
|
||||
String normalized = dateStr;
|
||||
if (!normalized.endsWith('Z') && !normalized.contains('+')) {
|
||||
normalized += 'Z';
|
||||
}
|
||||
return DateTime.parse(normalized).toLocal();
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _hubConnection?.stop();
|
||||
_hubConnection = null;
|
||||
|
||||
Reference in New Issue
Block a user