feat: Implement baseline profile generation and startup benchmarking

- Added baseline profile generator for Rosetta Messenger to optimize startup performance.
- Created startup benchmark tests to measure cold start times under different compilation modes.
- Introduced a new Gradle module for baseline profile and benchmark tests.
- Updated ChatsListViewModel to show loading skeleton while data is being fetched.
- Improved keyboard handling in MessageInputBar by using SHOW_IMPLICIT instead of SHOW_FORCED.
- Minor code cleanups and optimizations across various components.
This commit is contained in:
2026-02-08 09:21:05 +05:00
parent 8b8c883a63
commit abe1a1a710
13 changed files with 1111 additions and 564 deletions

View File

@@ -117,11 +117,18 @@ class ChatsListViewModel(application: Application) : AndroidViewModel(applicatio
return
}
// 🔥 Показываем skeleton пока данные грузятся
_isLoading.value = true
// 🔥 Очищаем кэш запрошенных user info при смене аккаунта
requestedUserInfoKeys.clear()
currentAccount = publicKey
currentPrivateKey = privateKey
// 🚀 Pre-warm PBKDF2 ключ — чтобы к моменту дешифровки кэш был горячий
viewModelScope.launch(Dispatchers.Default) { CryptoManager.getPbkdf2Key(privateKey) }
// Подписываемся на обычные диалоги
@OptIn(FlowPreview::class)
viewModelScope.launch {
@@ -268,6 +275,8 @@ class ChatsListViewModel(application: Application) : AndroidViewModel(applicatio
.distinctUntilChanged() // 🔥 ИСПРАВЛЕНИЕ: Игнорируем дублирующиеся списки
.collect { decryptedDialogs ->
_dialogs.value = decryptedDialogs
// 🚀 Убираем skeleton после первой загрузки
if (_isLoading.value) _isLoading.value = false
// 🟢 Подписываемся на онлайн-статусы всех собеседников
// 📁 Исключаем Saved Messages - не нужно подписываться на свой собственный

View File

@@ -25,7 +25,7 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -89,7 +89,6 @@ fun MessageInputBar(
inputFocusTrigger: Int = 0
) {
val hasReply = replyMessages.isNotEmpty()
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
val scope = rememberCoroutineScope()
val context = LocalContext.current
@@ -206,7 +205,8 @@ fun MessageInputBar(
showKeyboard = {
editTextView?.let { editText ->
editText.requestFocus()
imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED)
@Suppress("DEPRECATION")
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT)
}
},
hideEmoji = { onToggleEmojiPicker(false) }

View File

@@ -214,7 +214,7 @@ private fun OnlineIndicator(modifier: Modifier = Modifier) {
*/
@Composable
fun AvatarPicker(
onAvatarSelected: (String) -> Unit
@Suppress("UNUSED_PARAMETER") onAvatarSelected: (String) -> Unit
) {
// TODO: Реализовать выбор изображения через ActivityResultContract
// 1. Использовать rememberLauncherForActivityResult с ActivityResultContracts.GetContent()

View File

@@ -129,7 +129,6 @@ object OptimizedEmojiCache {
isPreloading = true
// Берем первые N эмодзи из категории Smileys (самые популярные)
val smileyCategory = EMOJI_CATEGORIES.find { it.key == "Smileys" }
val smileysToPreload = emojisByCategory?.get("Smileys")
?.take(PRELOAD_COUNT)
?: emptyList()