@@ -12,6 +12,7 @@ import { UseGuards } from '@nestjs/common';
1212import { JwtService } from '@nestjs/jwt' ;
1313import { ConfigService } from '@nestjs/config' ;
1414import { MessagesService } from './messages.service' ;
15+ import { ChatRepository } from 'src/chat/chat.repository' ;
1516import { GetMessagesQueryDto , SendMessageDto , UpdateMessageDto } from './dto' ;
1617import { WsJwtGuard } from 'src/auth/guards/ws-jwt.guard' ;
1718
@@ -36,6 +37,7 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
3637 private userSockets = new Map < string , Set < string > > ( ) ;
3738 constructor (
3839 private readonly messages_service : MessagesService ,
40+ private readonly chat_repository : ChatRepository ,
3941 private readonly jwt_service : JwtService ,
4042 private readonly config_service : ConfigService
4143 ) { }
@@ -52,12 +54,34 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
5254 this . userSockets . get ( user_id ) ?. add ( client . id ) ;
5355
5456 console . log ( `Client connected: ${ client . id } (User: ${ user_id } )` ) ;
57+
58+ // Send unread messages count to newly connected client
59+ await this . sendUnreadChatsOnConnection ( client , user_id ) ;
5560 } catch ( error ) {
5661 console . error ( 'Connection error:' , error ) ;
5762 client . disconnect ( ) ;
5863 }
5964 }
6065
66+ /**
67+ * Notify client about chats with unread messages when they connect
68+ * Frontend should then request full message history for these chats
69+ */
70+ private async sendUnreadChatsOnConnection ( client : IAuthenticatedSocket , user_id : string ) {
71+ try {
72+ const unread_chats = await this . messages_service . getUnreadChatsForUser ( user_id ) ;
73+
74+ if ( unread_chats . length > 0 ) {
75+ client . emit ( 'unread_chats_summary' , {
76+ chats : unread_chats ,
77+ message : 'You have unread messages in these chats' ,
78+ } ) ;
79+ }
80+ } catch ( error ) {
81+ console . error ( 'Error sending unread chats on connection:' , error ) ;
82+ }
83+ }
84+
6185 handleDisconnect ( client : IAuthenticatedSocket ) {
6286 const user_id = client . user ?. user_id ;
6387 if ( user_id ) {
@@ -81,7 +105,12 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
81105 const user_id = client . user ! . user_id ;
82106 const { chat_id } = data ;
83107
84- await this . messages_service . validateChatParticipation ( user_id , chat_id ) ;
108+ const chat = await this . messages_service . validateChatParticipation ( user_id , chat_id ) ;
109+
110+ // Reset unread count for this user when they join the chat
111+ const unread_field =
112+ chat . user1_id === user_id ? 'unread_count_user1' : 'unread_count_user2' ;
113+ await this . chat_repository . update ( { id : chat_id } , { [ unread_field ] : 0 } ) ;
85114
86115 await client . join ( chat_id ) ;
87116 return {
@@ -128,21 +157,29 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
128157 const user_id = client . user ! . user_id ;
129158 const { chat_id, message } = data ;
130159
131- const result = await this . messages_service . sendMessage ( user_id , chat_id , message ) ;
160+ // Check if recipient is actively in the chat room
161+ const chat = await this . messages_service . validateChatParticipation ( user_id , chat_id ) ;
162+ const recipient_id = chat . user1_id === user_id ? chat . user2_id : chat . user1_id ;
163+ console . log ( 'Recipient ID:' , recipient_id ) ;
164+ const is_recipient_in_room = await this . isUserInChatRoom ( recipient_id , chat_id ) ;
132165
133- // Emit to the chat room (for users already in the room)
134- this . server . to ( chat_id ) . emit ( 'new_message' , {
135- chat_id : chat_id ,
136- message : result ,
137- } ) ;
166+ const result = await this . messages_service . sendMessage (
167+ user_id ,
168+ chat_id ,
169+ message ,
170+ is_recipient_in_room
171+ ) ;
138172
139- // Also emit directly to the recipient (in case they're not in the room yet)
140- const recipient_id = result . recipient_id ;
141173 if ( recipient_id ) {
142174 this . emitToUser ( recipient_id , 'new_message' , {
143175 chat_id,
144176 message : result ,
145177 } ) ;
178+ } else {
179+ this . server . to ( chat_id ) . emit ( 'new_message' , {
180+ chat_id,
181+ message : result ,
182+ } ) ;
146183 }
147184
148185 return {
@@ -157,29 +194,6 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
157194 }
158195 }
159196
160- @SubscribeMessage ( 'get_messages' )
161- async handleGetMessages (
162- @ConnectedSocket ( ) client : IAuthenticatedSocket ,
163- @MessageBody ( ) data : { chat_id : string ; query ?: GetMessagesQueryDto }
164- ) {
165- try {
166- const user_id = client . user ! . user_id ;
167- const { chat_id, query } = data ;
168-
169- const messages = await this . messages_service . getMessages ( user_id , chat_id , query || { } ) ;
170-
171- return {
172- event : 'messages_retrieved' ,
173- data : messages ,
174- } ;
175- } catch ( error ) {
176- return {
177- event : 'error' ,
178- data : { message : error . message || 'Failed to retrieve messages' } ,
179- } ;
180- }
181- }
182-
183197 @SubscribeMessage ( 'update_message' )
184198 async handleUpdateMessage (
185199 @ConnectedSocket ( ) client : IAuthenticatedSocket ,
@@ -196,11 +210,6 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
196210 message_id ,
197211 update
198212 ) ;
199- this . server . to ( chat_id ) . emit ( 'message_updated' , {
200- chat_id,
201- message_id,
202- message : result ,
203- } ) ;
204213
205214 const recipient_id = result . recipient_id ;
206215 if ( recipient_id ) {
@@ -209,6 +218,12 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
209218 message_id,
210219 message : result ,
211220 } ) ;
221+ } else {
222+ this . server . to ( chat_id ) . emit ( 'message_updated' , {
223+ chat_id,
224+ message_id,
225+ message : result ,
226+ } ) ;
212227 }
213228
214229 return {
@@ -233,10 +248,6 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
233248 const { chat_id, message_id } = data ;
234249
235250 const result = await this . messages_service . deleteMessage ( user_id , chat_id , message_id ) ;
236- this . server . to ( chat_id ) . emit ( 'message_deleted' , {
237- chat_id,
238- message_id,
239- } ) ;
240251
241252 const recipient_id = result . recipient_id ;
242253 if ( recipient_id ) {
@@ -245,6 +256,11 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
245256 message_id,
246257 message : result ,
247258 } ) ;
259+ } else {
260+ this . server . to ( chat_id ) . emit ( 'message_deleted' , {
261+ chat_id,
262+ message_id,
263+ } ) ;
248264 }
249265
250266 return {
@@ -322,4 +338,20 @@ export class MessagesGateway implements OnGatewayConnection, OnGatewayDisconnect
322338 } ) ;
323339 }
324340 }
341+
342+ async isUserInChatRoom ( user_id : string , chat_id : string ) : Promise < boolean > {
343+ const socket_ids = this . userSockets . get ( user_id ) ;
344+ if ( ! socket_ids ) return false ;
345+ // Check if any of the user's sockets are in the chat room
346+ const sockets_in_room = await this . server . in ( chat_id ) . fetchSockets ( ) ;
347+ const room_socket_ids = new Set ( sockets_in_room . map ( ( s ) => s . id ) ) ;
348+
349+ for ( const socket_id of socket_ids ) {
350+ if ( room_socket_ids . has ( socket_id ) ) {
351+ console . log ( `User ${ user_id } is in chat room ${ chat_id } via socket ${ socket_id } ` ) ;
352+ return true ;
353+ }
354+ }
355+ return false ;
356+ }
325357}
0 commit comments