feat: Automatically mark messages as delivered when recipients come online or receive new messages.
This commit is contained in:
@@ -99,6 +99,26 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
|
||||
.catch((err) => {
|
||||
this.logger.warn(`Failed to update online status for ${userId}: ${err.message}`);
|
||||
});
|
||||
|
||||
// Mark pending SENT messages as DELIVERED now that this user is online
|
||||
this.messagesService.markPendingMessagesAsDelivered(userId)
|
||||
.then((results) => {
|
||||
for (const result of results) {
|
||||
// Notify each sender that their messages were delivered
|
||||
const deliveredEvent = {
|
||||
messageIds: result.messageIds,
|
||||
conversationId: result.conversationId,
|
||||
deliveredAt: result.deliveredAt,
|
||||
};
|
||||
this.sendToUser(result.senderId, 'message_delivered', deliveredEvent);
|
||||
}
|
||||
if (results.length > 0) {
|
||||
this.logger.log(`Marked pending messages as delivered for ${userId} across ${results.length} conversation(s)`);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
this.logger.warn(`Failed to mark pending messages as delivered for ${userId}: ${err.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,6 +210,18 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
|
||||
? participants.agentUserId
|
||||
: participants.userId;
|
||||
this.sendToUser(otherUserId, 'new_message', message);
|
||||
|
||||
// Auto-mark as DELIVERED if recipient is online
|
||||
if (this.isUserOnline(otherUserId)) {
|
||||
await this.messagesService.markMessageDelivered(message.id);
|
||||
const deliveredEvent = {
|
||||
messageId: message.id,
|
||||
conversationId: data.conversationId,
|
||||
deliveredAt: new Date(),
|
||||
};
|
||||
// Notify sender that message was delivered
|
||||
this.sendToUser(client.userId, 'message_delivered', deliveredEvent);
|
||||
}
|
||||
}
|
||||
} catch (participantError) {
|
||||
this.logger.warn(`Failed to get participants for direct delivery in ${data.conversationId}: ${participantError.message}`);
|
||||
|
||||
@@ -528,6 +528,52 @@ export class MessagesService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all SENT messages addressed to a user as DELIVERED (when they come online)
|
||||
* Returns the updated messages grouped by conversation for notification purposes
|
||||
*/
|
||||
async markPendingMessagesAsDelivered(userId: string): Promise<{ conversationId: string; senderId: string; messageIds: string[]; deliveredAt: Date }[]> {
|
||||
const now = new Date();
|
||||
|
||||
// Find all conversations where this user is a participant
|
||||
const conversations = await this.prisma.conversation.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{ userId },
|
||||
{ agentProfile: { userId } },
|
||||
],
|
||||
},
|
||||
select: { id: true, userId: true, agentProfile: { select: { userId: true } } },
|
||||
});
|
||||
|
||||
const results: { conversationId: string; senderId: string; messageIds: string[]; deliveredAt: Date }[] = [];
|
||||
|
||||
for (const conv of conversations) {
|
||||
const otherUserId = conv.userId === userId ? conv.agentProfile.userId : conv.userId;
|
||||
|
||||
// Find SENT messages from the other user in this conversation
|
||||
const sentMessages = await this.prisma.message.findMany({
|
||||
where: {
|
||||
conversationId: conv.id,
|
||||
senderId: otherUserId,
|
||||
status: MessageStatus.SENT,
|
||||
},
|
||||
select: { id: true },
|
||||
});
|
||||
|
||||
if (sentMessages.length > 0) {
|
||||
const messageIds = sentMessages.map((m) => m.id);
|
||||
await this.prisma.message.updateMany({
|
||||
where: { id: { in: messageIds } },
|
||||
data: { status: MessageStatus.DELIVERED, deliveredAt: now },
|
||||
});
|
||||
results.push({ conversationId: conv.id, senderId: otherUserId, messageIds, deliveredAt: now });
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conversation by ID with full details
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user