diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index 95c7956..1859ef8 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -525,3 +525,8 @@ ### Step 84 - Chats list preview icon policy cleanup - Updated chat last-message preview text to remove emoji prefixes. - Switched media-type preview prefixes to plain text labels (`Photo`, `Video`, `Voice`, etc.) to match Material-icons-only UI policy. + +### Step 85 - Unread counter fix for active/read chats +- Added `ChatDao.markChatRead(chatId)` to clear `unread_count` and `unread_mentions_count` in Room. +- Applied optimistic local unread reset on `markMessageRead(...)` in message repository. +- Fixed realtime unread logic: incoming messages in currently active chat no longer increment unread badge. diff --git a/android/app/src/main/java/ru/daemonlord/messenger/data/chat/local/dao/ChatDao.kt b/android/app/src/main/java/ru/daemonlord/messenger/data/chat/local/dao/ChatDao.kt index eb4f652..4e2d840 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/data/chat/local/dao/ChatDao.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/data/chat/local/dao/ChatDao.kt @@ -139,6 +139,16 @@ interface ChatDao { ) suspend fun incrementUnread(chatId: Long, incrementBy: Int = 1) + @Query( + """ + UPDATE chats + SET unread_count = 0, + unread_mentions_count = 0 + WHERE id = :chatId + """ + ) + suspend fun markChatRead(chatId: Long) + @Transaction suspend fun clearAndReplaceChats( archived: Boolean, diff --git a/android/app/src/main/java/ru/daemonlord/messenger/data/message/repository/NetworkMessageRepository.kt b/android/app/src/main/java/ru/daemonlord/messenger/data/message/repository/NetworkMessageRepository.kt index f3fc6d0..57d978d 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/data/message/repository/NetworkMessageRepository.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/data/message/repository/NetworkMessageRepository.kt @@ -401,6 +401,8 @@ class NetworkMessageRepository @Inject constructor( } override suspend fun markMessageRead(chatId: Long, messageId: Long): AppResult = withContext(ioDispatcher) { + // User already viewed this chat/message in UI, so unread badge should drop immediately. + chatDao.markChatRead(chatId) try { messageApiService.updateMessageStatus( request = MessageStatusUpdateRequestDto( diff --git a/android/app/src/main/java/ru/daemonlord/messenger/domain/realtime/usecase/HandleRealtimeEventsUseCase.kt b/android/app/src/main/java/ru/daemonlord/messenger/domain/realtime/usecase/HandleRealtimeEventsUseCase.kt index 96167f4..b355def 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/domain/realtime/usecase/HandleRealtimeEventsUseCase.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/domain/realtime/usecase/HandleRealtimeEventsUseCase.kt @@ -45,6 +45,7 @@ class HandleRealtimeEventsUseCase @Inject constructor( } is RealtimeEvent.ReceiveMessage -> { + val activeChatId = activeChatTracker.activeChatId.value messageDao.upsertMessages( listOf( MessageEntity( @@ -75,8 +76,11 @@ class HandleRealtimeEventsUseCase @Inject constructor( lastMessageCreatedAt = event.createdAt, updatedSortAt = event.createdAt, ) - chatDao.incrementUnread(chatId = event.chatId) - val activeChatId = activeChatTracker.activeChatId.value + if (activeChatId == event.chatId) { + chatDao.markChatRead(chatId = event.chatId) + } else { + chatDao.incrementUnread(chatId = event.chatId) + } val muted = chatDao.isChatMuted(event.chatId) == true val shouldNotify = shouldShowMessageNotificationUseCase( chatId = event.chatId,