feat: Preserve optimistic message status during UI updates for improved user experience
This commit is contained in:
@@ -300,8 +300,18 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
// ProtocolManager.setupPacketHandlers() не вызывается, поэтому сохраняем сами
|
// ProtocolManager.setupPacketHandlers() не вызывается, поэтому сохраняем сами
|
||||||
// Используем fromPublicKey как opponent для корректного dialogKey
|
// Используем fromPublicKey как opponent для корректного dialogKey
|
||||||
val senderKey = packet.fromPublicKey
|
val senderKey = packet.fromPublicKey
|
||||||
|
|
||||||
|
// 🔥 FIX: Если messageId пустой - генерируем новый UUID
|
||||||
|
val finalMessageId = if (packet.messageId.isNullOrEmpty()) {
|
||||||
|
UUID.randomUUID().toString().replace("-", "").take(32).also {
|
||||||
|
ProtocolManager.addLog("⚠️ Empty messageId from server, generated: ${it.take(8)}...")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
packet.messageId
|
||||||
|
}
|
||||||
|
|
||||||
saveMessageToDatabase(
|
saveMessageToDatabase(
|
||||||
messageId = packet.messageId,
|
messageId = finalMessageId,
|
||||||
text = decryptedText,
|
text = decryptedText,
|
||||||
encryptedContent = packet.content,
|
encryptedContent = packet.content,
|
||||||
encryptedKey = packet.chachaKey,
|
encryptedKey = packet.chachaKey,
|
||||||
@@ -441,8 +451,12 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
ProtocolManager.addLog("📋 Decrypted and loaded ${messages.size} messages from DB")
|
ProtocolManager.addLog("📋 Decrypted and loaded ${messages.size} messages from DB")
|
||||||
|
|
||||||
// 🔥 СРАЗУ обновляем UI - пользователь видит сообщения мгновенно
|
// 🔥 СРАЗУ обновляем UI - пользователь видит сообщения мгновенно
|
||||||
|
// НО сохраняем оптимистичные сообщения (SENDING), которые ещё не в БД
|
||||||
withContext(Dispatchers.Main.immediate) {
|
withContext(Dispatchers.Main.immediate) {
|
||||||
_messages.value = messages
|
val optimisticMessages = _messages.value.filter { msg ->
|
||||||
|
msg.status == MessageStatus.SENDING && messages.none { it.id == msg.id }
|
||||||
|
}
|
||||||
|
_messages.value = messages + optimisticMessages
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1080,13 +1094,22 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
try {
|
try {
|
||||||
val dialogKey = getDialogKey(account, opponent)
|
val dialogKey = getDialogKey(account, opponent)
|
||||||
|
|
||||||
|
// 🔒 Проверяем messageId - если пустой, генерируем новый
|
||||||
|
val finalMessageId = if (messageId.isEmpty()) {
|
||||||
|
val generated = UUID.randomUUID().toString().replace("-", "").take(32)
|
||||||
|
ProtocolManager.addLog("⚠️ Empty messageId detected, generated new: $generated")
|
||||||
|
generated
|
||||||
|
} else {
|
||||||
|
messageId
|
||||||
|
}
|
||||||
|
|
||||||
// 🔒 Шифруем plainMessage с использованием приватного ключа
|
// 🔒 Шифруем plainMessage с использованием приватного ключа
|
||||||
val encryptedPlainMessage = CryptoManager.encryptWithPassword(text, privateKey)
|
val encryptedPlainMessage = CryptoManager.encryptWithPassword(text, privateKey)
|
||||||
|
|
||||||
// Проверяем существует ли сообщение
|
// Проверяем существует ли сообщение
|
||||||
val exists = messageDao.messageExists(account, messageId)
|
val exists = messageDao.messageExists(account, finalMessageId)
|
||||||
ProtocolManager.addLog("💾 Saving message to DB:")
|
ProtocolManager.addLog("💾 Saving message to DB:")
|
||||||
ProtocolManager.addLog(" messageId: $messageId")
|
ProtocolManager.addLog(" messageId: $finalMessageId")
|
||||||
ProtocolManager.addLog(" exists in DB: $exists")
|
ProtocolManager.addLog(" exists in DB: $exists")
|
||||||
ProtocolManager.addLog(" dialogKey: $dialogKey")
|
ProtocolManager.addLog(" dialogKey: $dialogKey")
|
||||||
ProtocolManager.addLog(" text: ${text.take(20)}...")
|
ProtocolManager.addLog(" text: ${text.take(20)}...")
|
||||||
@@ -1101,7 +1124,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
read = if (isFromMe) 1 else 0,
|
read = if (isFromMe) 1 else 0,
|
||||||
fromMe = if (isFromMe) 1 else 0,
|
fromMe = if (isFromMe) 1 else 0,
|
||||||
delivered = delivered,
|
delivered = delivered,
|
||||||
messageId = messageId,
|
messageId = finalMessageId,
|
||||||
plainMessage = encryptedPlainMessage, // 🔒 Зашифрованный текст для хранения в БД
|
plainMessage = encryptedPlainMessage, // 🔒 Зашифрованный текст для хранения в БД
|
||||||
attachments = attachmentsJson,
|
attachments = attachmentsJson,
|
||||||
replyToMessageId = null,
|
replyToMessageId = null,
|
||||||
|
|||||||
Reference in New Issue
Block a user