feat: implement message delivery status tracking via socket events and provider state updates
This commit is contained in:
@@ -36,6 +36,7 @@ class SocketService {
|
|||||||
final _supportTypingStopController = StreamController<Map<String, dynamic>>.broadcast();
|
final _supportTypingStopController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
final _connectionRequestController = StreamController<Map<String, dynamic>>.broadcast();
|
final _connectionRequestController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
final _connectionResponseController = StreamController<Map<String, dynamic>>.broadcast();
|
final _connectionResponseController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
|
final _deliveredController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
|
|
||||||
Stream<ChatMessage> get onNewMessage => _messageController.stream;
|
Stream<ChatMessage> get onNewMessage => _messageController.stream;
|
||||||
Stream<Map<String, dynamic>> get onTypingStart => _typingStartController.stream;
|
Stream<Map<String, dynamic>> get onTypingStart => _typingStartController.stream;
|
||||||
@@ -48,6 +49,7 @@ class SocketService {
|
|||||||
Stream<Map<String, dynamic>> get onSupportTypingStop => _supportTypingStopController.stream;
|
Stream<Map<String, dynamic>> get onSupportTypingStop => _supportTypingStopController.stream;
|
||||||
Stream<Map<String, dynamic>> get onConnectionRequest => _connectionRequestController.stream;
|
Stream<Map<String, dynamic>> get onConnectionRequest => _connectionRequestController.stream;
|
||||||
Stream<Map<String, dynamic>> get onConnectionResponse => _connectionResponseController.stream;
|
Stream<Map<String, dynamic>> get onConnectionResponse => _connectionResponseController.stream;
|
||||||
|
Stream<Map<String, dynamic>> get onMessageDelivered => _deliveredController.stream;
|
||||||
bool get isConnected => _isConnected;
|
bool get isConnected => _isConnected;
|
||||||
|
|
||||||
Future<void> connect() async {
|
Future<void> connect() async {
|
||||||
@@ -186,6 +188,10 @@ class SocketService {
|
|||||||
_connectionResponseController.add(Map<String, dynamic>.from(data as Map));
|
_connectionResponseController.add(Map<String, dynamic>.from(data as Map));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_socket!.on('message_delivered', (data) {
|
||||||
|
_deliveredController.add(Map<String, dynamic>.from(data as Map));
|
||||||
|
});
|
||||||
|
|
||||||
_socket!.connect();
|
_socket!.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,5 +318,6 @@ class SocketService {
|
|||||||
_supportTypingStopController.close();
|
_supportTypingStopController.close();
|
||||||
_connectionRequestController.close();
|
_connectionRequestController.close();
|
||||||
_connectionResponseController.close();
|
_connectionResponseController.close();
|
||||||
|
_deliveredController.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,6 +171,38 @@ class MessagingNotifier extends StateNotifier<MessagingState> {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Delivered receipts — update single tick → double tick
|
||||||
|
_subscriptions.add(_socket.onMessageDelivered.listen((data) {
|
||||||
|
if (!mounted) return;
|
||||||
|
final convId = data['conversationId'] as String?;
|
||||||
|
final messageId = data['messageId'] as String?;
|
||||||
|
final deliveredAt = data['deliveredAt'] as String?;
|
||||||
|
if (convId == null) return;
|
||||||
|
|
||||||
|
final currentMessages = List<ChatMessage>.from(state.messages[convId] ?? []);
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
final updatedMessages = currentMessages.map((m) {
|
||||||
|
// Update specific message or all sent messages in this conversation
|
||||||
|
if (messageId != null && m.id == messageId && m.status == MessageStatus.sent) {
|
||||||
|
changed = true;
|
||||||
|
return m.copyWith(status: MessageStatus.delivered, deliveredAt: deliveredAt);
|
||||||
|
}
|
||||||
|
// If no specific messageId, mark all sent messages as delivered
|
||||||
|
if (messageId == null && m.senderId == _currentUserId && m.status == MessageStatus.sent) {
|
||||||
|
changed = true;
|
||||||
|
return m.copyWith(status: MessageStatus.delivered, deliveredAt: deliveredAt);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
final newMessages = Map<String, List<ChatMessage>>.from(state.messages)
|
||||||
|
..[convId] = updatedMessages;
|
||||||
|
state = state.copyWith(messages: newMessages);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
// Read receipts — update message ticks and conversation unread count
|
// Read receipts — update message ticks and conversation unread count
|
||||||
_subscriptions.add(_socket.onMessagesRead.listen((data) {
|
_subscriptions.add(_socket.onMessagesRead.listen((data) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user