feat: Implement message delivered event handling to update message statuses in conversations.

This commit is contained in:
pradeepkumar
2026-03-28 02:03:04 +05:30
parent 3f9554c8ba
commit bd40eaeb0c
3 changed files with 40 additions and 0 deletions

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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;