Синхронизация статусов и времени существующих сообщений, добавление новых сообщений в кэш
Some checks failed
Android Kernel Build / build (push) Has been cancelled

This commit is contained in:
2026-03-19 15:29:09 +05:00
parent 9a411ac473
commit af4a3a5f27

View File

@@ -902,38 +902,61 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
// 🔥 Берём ТЕКУЩЕЕ состояние UI (может уже содержать новые сообщения) // 🔥 Берём ТЕКУЩЕЕ состояние UI (может уже содержать новые сообщения)
val currentMessages = _messages.value val currentMessages = _messages.value
val existingIds = currentMessages.map { it.id }.toSet() val existingIds = currentMessages.map { it.id }.toSet()
val entitiesById = entities.associateBy { it.messageId }
// 🔄 Синхронизируем статусы/время уже существующих сообщений из БД.
// Это критично для случая WAITING -> ERROR: без этого в открытом диалоге остаются "часики".
val reconciledMessages =
currentMessages.map { message ->
val entity = entitiesById[message.id] ?: return@map message
val dbStatus =
when (entity.delivered) {
0 -> MessageStatus.SENDING
1 -> if (entity.read == 1) MessageStatus.READ else MessageStatus.DELIVERED
2 -> MessageStatus.ERROR
3 -> MessageStatus.READ
else -> MessageStatus.SENT
}
var updatedMessage = message
if (updatedMessage.status != dbStatus) {
updatedMessage = updatedMessage.copy(status = dbStatus)
}
if (updatedMessage.timestamp.time != entity.timestamp) {
updatedMessage = updatedMessage.copy(timestamp = Date(entity.timestamp))
}
updatedMessage
}
val hasExistingUpdates = reconciledMessages != currentMessages
// 🔥 Находим только НОВЫЕ сообщения (которых нет в текущем UI) // 🔥 Находим только НОВЫЕ сообщения (которых нет в текущем UI)
val newEntities = entities.filter { it.messageId !in existingIds } val newEntities = entities.filter { it.messageId !in existingIds }
val newMessages =
if (newEntities.isNotEmpty()) { if (newEntities.isNotEmpty()) {
val semaphore = Semaphore(DECRYPT_PARALLELISM) val semaphore = Semaphore(DECRYPT_PARALLELISM)
val newMessages = coroutineScope { coroutineScope {
newEntities newEntities
.map { entity -> .map { entity ->
async { semaphore.withPermit { entityToChatMessage(entity) } } async { semaphore.withPermit { entityToChatMessage(entity) } }
} }
.awaitAll() .awaitAll()
} }
} else {
// 🔥 ДОБАВЛЯЕМ новые к текущим, а не заменяем! emptyList()
// Сортируем по timestamp чтобы новые были в конце
val updatedMessages =
sortMessagesAscending((currentMessages + newMessages).distinctBy { it.id })
// 🔥 ИСПРАВЛЕНИЕ: Обновляем кэш сохраняя ВСЕ сообщения, не только отображаемые!
// Объединяем существующий кэш с новыми сообщениями
val existingCache = dialogMessagesCache[cacheKey(account, dialogKey)] ?: emptyList()
val allCachedIds = existingCache.map { it.id }.toSet()
val trulyNewMessages = newMessages.filter { it.id !in allCachedIds }
if (trulyNewMessages.isNotEmpty()) {
updateCacheWithLimit(
account,
dialogKey,
sortMessagesAscending(existingCache + trulyNewMessages)
)
} }
if (hasExistingUpdates || newMessages.isNotEmpty()) {
// 🔥 ДОБАВЛЯЕМ новые + применяем статусные апдейты к существующим
val updatedMessages =
sortMessagesAscending((reconciledMessages + newMessages).distinctBy { it.id })
// 🔥 Обновляем кэш: сохраняем старые страницы + применяем новые статусы/время
val existingCache = dialogMessagesCache[cacheKey(account, dialogKey)] ?: emptyList()
val mergedCache = sortMessagesAscending((existingCache + updatedMessages).distinctBy { it.id })
updateCacheWithLimit(account, dialogKey, mergedCache)
withContext(Dispatchers.Main.immediate) { _messages.value = updatedMessages } withContext(Dispatchers.Main.immediate) { _messages.value = updatedMessages }
} }