From 23d636be7e257a84f47b0deda76b91b85677bb02 Mon Sep 17 00:00:00 2001 From: Codex Date: Tue, 10 Mar 2026 20:33:50 +0300 Subject: [PATCH] fix(android): preload message reactions on chat open --- .../messenger/ui/chat/ChatViewModel.kt | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt index 6135a34..30dc0f8 100644 --- a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt +++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt @@ -68,6 +68,7 @@ class ChatViewModel @Inject constructor( private val visibleMessagesLimit = MutableStateFlow(MESSAGES_PAGE_SIZE) private var lastDeliveredMessageId: Long? = null private var lastReadMessageId: Long? = null + private val reactionsRequestedMessageIds = mutableSetOf() init { activeChatTracker.setActiveChat(chatId) @@ -562,13 +563,14 @@ class ChatViewModel @Inject constructor( visibleMessagesLimit .flatMapLatest { limit -> observeMessagesUseCase(chatId = chatId, limit = limit) } .collectLatest { messages -> + val sortedMessages = messages.sortedBy { msg -> msg.id } _uiState.update { val pinnedId = it.pinnedMessageId val normalized = it.inlineSearchQuery.trim().lowercase() val inlineMatches = if (normalized.isBlank()) { emptyList() } else { - messages + sortedMessages .filter { msg -> (msg.text ?: "").lowercase().contains(normalized) } .map { msg -> msg.id } } @@ -579,13 +581,14 @@ class ChatViewModel @Inject constructor( } it.copy( isLoading = false, - messages = messages.sortedBy { msg -> msg.id }, - pinnedMessage = pinnedId?.let { id -> messages.firstOrNull { msg -> msg.id == id } }, + messages = sortedMessages, + pinnedMessage = pinnedId?.let { id -> sortedMessages.firstOrNull { msg -> msg.id == id } }, inlineSearchMatches = inlineMatches, highlightedMessageId = highlighted, ) } - acknowledgeLatestMessages(messages) + preloadReactions(sortedMessages) + acknowledgeLatestMessages(sortedMessages) } } } @@ -659,6 +662,28 @@ class ChatViewModel @Inject constructor( } } + private fun preloadReactions(messages: List) { + val toRequest = messages + .asReversed() + .map { it.id } + .filter { reactionsRequestedMessageIds.add(it) } + + if (toRequest.isEmpty()) return + + toRequest.forEach { messageId -> + viewModelScope.launch { + when (val result = listMessageReactionsUseCase(messageId = messageId)) { + is AppResult.Success -> { + _uiState.update { + it.copy(reactionByMessageId = it.reactionByMessageId + (messageId to result.data)) + } + } + is AppResult.Error -> Unit + } + } + } + } + private fun acknowledgeLatestMessages(messages: List) { val latestIncoming = messages.asReversed().firstOrNull { !it.isOutgoing }