feat: Implement message delivered event handling to update message statuses in conversations.
This commit is contained in:
@@ -10,6 +10,7 @@ import type {
|
||||
TypingIndicator,
|
||||
UserStatusChange,
|
||||
MessagesReadEvent,
|
||||
MessageDeliveredEvent,
|
||||
MessageType,
|
||||
MessageStatus,
|
||||
} from '@/types/messaging';
|
||||
@@ -561,6 +562,25 @@ export function useMessaging(options: UseMessagingOptions = {}): UseMessagingRet
|
||||
}
|
||||
);
|
||||
|
||||
const unsubscribeDelivered = socketService.onMessageDelivered(
|
||||
(data: MessageDeliveredEvent) => {
|
||||
if (data.conversationId === currentConversationIdRef.current) {
|
||||
// Update single message or batch of messages to DELIVERED
|
||||
const deliveredIds = data.messageIds || (data.messageId ? [data.messageId] : []);
|
||||
if (deliveredIds.length > 0) {
|
||||
setMessages((prev) =>
|
||||
prev.map((m) => {
|
||||
if (deliveredIds.includes(m.id) && m.status === 'SENT') {
|
||||
return { ...m, status: 'DELIVERED' as MessageStatus, deliveredAt: data.deliveredAt };
|
||||
}
|
||||
return m;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Auth error handling (token refresh + reconnect) is handled globally
|
||||
// by PresenceProvider — no duplicate handler needed here.
|
||||
|
||||
@@ -571,6 +591,7 @@ export function useMessaging(options: UseMessagingOptions = {}): UseMessagingRet
|
||||
unsubscribeTypingStop();
|
||||
unsubscribeStatus();
|
||||
unsubscribeRead();
|
||||
unsubscribeDelivered();
|
||||
};
|
||||
}, [updateUserStatus]);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
TypingIndicator,
|
||||
UserStatusChange,
|
||||
MessagesReadEvent,
|
||||
MessageDeliveredEvent,
|
||||
CreateMessageDto,
|
||||
} from '@/types/messaging';
|
||||
|
||||
@@ -11,6 +12,7 @@ type MessageHandler = (message: Message) => void;
|
||||
type TypingHandler = (data: TypingIndicator) => void;
|
||||
type StatusHandler = (data: UserStatusChange) => void;
|
||||
type ReadHandler = (data: MessagesReadEvent) => void;
|
||||
type DeliveredHandler = (data: MessageDeliveredEvent) => void;
|
||||
|
||||
class SocketService {
|
||||
private socket: Socket | null = null;
|
||||
@@ -21,6 +23,7 @@ class SocketService {
|
||||
private typingStopHandlers: Set<TypingHandler> = new Set();
|
||||
private statusHandlers: Set<StatusHandler> = new Set();
|
||||
private readHandlers: Set<ReadHandler> = new Set();
|
||||
private deliveredHandlers: Set<DeliveredHandler> = new Set();
|
||||
private connectionHandlers: Set<(connected: boolean) => void> = new Set();
|
||||
private authErrorHandlers: Set<() => void> = new Set();
|
||||
private isConnecting = false;
|
||||
@@ -125,6 +128,10 @@ class SocketService {
|
||||
this.socket.on('messages_read', (data: MessagesReadEvent) => {
|
||||
this.readHandlers.forEach((handler) => handler(data));
|
||||
});
|
||||
|
||||
this.socket.on('message_delivered', (data: MessageDeliveredEvent) => {
|
||||
this.deliveredHandlers.forEach((handler) => handler(data));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -265,6 +272,11 @@ class SocketService {
|
||||
return () => this.readHandlers.delete(handler);
|
||||
}
|
||||
|
||||
onMessageDelivered(handler: DeliveredHandler): () => void {
|
||||
this.deliveredHandlers.add(handler);
|
||||
return () => this.deliveredHandlers.delete(handler);
|
||||
}
|
||||
|
||||
onConnectionChange(handler: (connected: boolean) => void): () => void {
|
||||
this.connectionHandlers.add(handler);
|
||||
return () => this.connectionHandlers.delete(handler);
|
||||
|
||||
@@ -99,6 +99,13 @@ export interface MessagesReadEvent {
|
||||
readAt: string;
|
||||
}
|
||||
|
||||
export interface MessageDeliveredEvent {
|
||||
messageId?: string;
|
||||
messageIds?: string[];
|
||||
conversationId: string;
|
||||
deliveredAt: string;
|
||||
}
|
||||
|
||||
export interface PaginationInfo {
|
||||
page: number;
|
||||
limit: number;
|
||||
|
||||
Reference in New Issue
Block a user