feat: Optimize emoji picker performance by eliminating chunk loading, reducing animations, and improving emoji caching
This commit is contained in:
@@ -262,13 +262,8 @@ fun ChatDetailScreen(
|
||||
// 🔥 Флаг видимости панели эмодзи (тот же что в MessageInputBar) - единый источник правды
|
||||
val isEmojiPanelVisible = showEmojiPicker && !isKeyboardVisible
|
||||
|
||||
// 🔥 Анимированный отступ для списка сообщений когда emoji picker открыт
|
||||
// Используем isEmojiPanelVisible для синхронизации с анимацией панели
|
||||
val emojiPanelPadding by animateDpAsState(
|
||||
targetValue = if (isEmojiPanelVisible) emojiPanelHeight else 0.dp,
|
||||
animationSpec = tween(100, easing = FastOutSlowInEasing), // 100ms как exit анимация панели
|
||||
label = "emojiPanelPadding"
|
||||
)
|
||||
// <EFBFBD> Простой отступ без анимации - AnimatedVisibility сама анимирует
|
||||
val emojiPanelPadding = if (isEmojiPanelVisible) emojiPanelHeight else 0.dp
|
||||
|
||||
// 🔥 Reply/Forward state
|
||||
val replyMessages by viewModel.replyMessages.collectAsState()
|
||||
@@ -2322,11 +2317,11 @@ private fun MessageInputBar(
|
||||
visible = showPanel,
|
||||
enter = slideInVertically(
|
||||
initialOffsetY = { it }, // Снизу вверх
|
||||
animationSpec = tween(100, easing = FastOutSlowInEasing)
|
||||
animationSpec = tween(150, easing = FastOutSlowInEasing) // 🚀 Быстрее и плавнее
|
||||
),
|
||||
exit = slideOutVertically(
|
||||
targetOffsetY = { it }, // Сверху вниз
|
||||
animationSpec = tween(100, easing = FastOutSlowInEasing) // 🔥 Синхронизировано с padding анимацией
|
||||
animationSpec = tween(150, easing = FastOutSlowInEasing)
|
||||
)
|
||||
) {
|
||||
AppleEmojiPickerPanel(
|
||||
|
||||
@@ -280,32 +280,11 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
|
||||
_messages.value = _messages.value + message
|
||||
}
|
||||
|
||||
// 🔥 Сохраняем в БД здесь (в ChatViewModel)
|
||||
// ProtocolManager.setupPacketHandlers() не вызывается, поэтому сохраняем сами
|
||||
// Используем fromPublicKey как opponent для корректного dialogKey
|
||||
// ✅ НЕ сохраняем в БД здесь - это делает MessageRepository.handleIncomingMessage()!
|
||||
// Убираем дублирование: одно сообщение не должно сохраняться дважды
|
||||
|
||||
// 🔥 Обновляем диалог - используем fromPublicKey
|
||||
val senderKey = packet.fromPublicKey
|
||||
|
||||
// 🔥 FIX: Если messageId пустой - генерируем новый UUID
|
||||
val finalMessageId = if (packet.messageId.isNullOrEmpty()) {
|
||||
UUID.randomUUID().toString().replace("-", "").take(32).also {
|
||||
}
|
||||
} else {
|
||||
packet.messageId
|
||||
}
|
||||
|
||||
saveMessageToDatabase(
|
||||
messageId = finalMessageId,
|
||||
text = decryptedText,
|
||||
encryptedContent = packet.content,
|
||||
encryptedKey = packet.chachaKey,
|
||||
timestamp = packet.timestamp,
|
||||
isFromMe = false, // Это входящее сообщение
|
||||
delivered = DeliveryStatus.DELIVERED.value,
|
||||
attachmentsJson = attachmentsJson,
|
||||
opponentPublicKey = senderKey
|
||||
)
|
||||
|
||||
// 🔥 Обновляем диалог - используем senderKey
|
||||
updateDialog(senderKey, decryptedText, packet.timestamp, incrementUnread = !isDialogActive)
|
||||
|
||||
// 👁️ НЕ отправляем read receipt автоматически!
|
||||
@@ -1059,8 +1038,12 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
|
||||
// 🔒 Шифруем plainMessage с использованием приватного ключа
|
||||
val encryptedPlainMessage = CryptoManager.encryptWithPassword(text, privateKey)
|
||||
|
||||
// Проверяем существует ли сообщение
|
||||
// ✅ Проверяем существует ли сообщение - ИСПОЛЬЗУЕМ результат!
|
||||
val exists = messageDao.messageExists(account, finalMessageId)
|
||||
if (exists) {
|
||||
// Сообщение уже есть в БД - не дублируем
|
||||
return
|
||||
}
|
||||
|
||||
val entity = MessageEntity(
|
||||
account = account,
|
||||
|
||||
Reference in New Issue
Block a user