fix: improve avatar loading and rendering logic to prevent flickering and enhance performance
This commit is contained in:
@@ -1047,26 +1047,42 @@ private fun FullSizeAvatar(
|
||||
avatarRepository?.getAvatars(publicKey, allDecode = false)?.collectAsState()
|
||||
?: remember { mutableStateOf(emptyList()) }
|
||||
|
||||
// Сохраняем bitmap в remember чтобы не мигал при recomposition
|
||||
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
||||
var isLoading by remember { mutableStateOf(true) }
|
||||
// 🔥 FIX: Используем стабильный ключ (timestamp) вместо reference списка
|
||||
// Это предотвращает перезагрузку bitmap при recomposition когда данные не изменились
|
||||
val avatarKey = remember(avatars) {
|
||||
avatars.firstOrNull()?.timestamp ?: 0L
|
||||
}
|
||||
|
||||
LaunchedEffect(avatars) {
|
||||
if (avatars.isNotEmpty()) {
|
||||
// 🔥 FIX: Сохраняем bitmap БЕЗ сброса при изменении ключа
|
||||
// Предыдущий bitmap показывается пока загружается новый (double buffering)
|
||||
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
||||
|
||||
// 🔥 FIX: isLoading только для первой загрузки, не сбрасываем если bitmap уже есть
|
||||
var initialLoadComplete by remember { mutableStateOf(false) }
|
||||
|
||||
// 🔥 FIX: Декодируем только когда avatarKey (timestamp) реально изменился
|
||||
// НЕ сбрасываем bitmap в null перед загрузкой - показываем старый пока грузится новый
|
||||
LaunchedEffect(avatarKey) {
|
||||
val currentAvatars = avatars
|
||||
if (currentAvatars.isNotEmpty()) {
|
||||
val newBitmap = kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) {
|
||||
com.rosetta.messenger.utils.AvatarFileManager.base64ToBitmap(
|
||||
avatars.first().base64Data
|
||||
currentAvatars.first().base64Data
|
||||
)
|
||||
}
|
||||
bitmap = newBitmap
|
||||
isLoading = false
|
||||
// Устанавливаем новый bitmap только если декодирование успешно
|
||||
if (newBitmap != null) {
|
||||
bitmap = newBitmap
|
||||
}
|
||||
initialLoadComplete = true
|
||||
} else {
|
||||
isLoading = false
|
||||
// Нет аватарки - помечаем загрузку завершенной
|
||||
initialLoadComplete = true
|
||||
}
|
||||
}
|
||||
|
||||
// Показываем картинку если есть, иначе placeholder
|
||||
// НО не показываем placeholder пока идёт загрузка (чтобы не мигало)
|
||||
// 🔥 FIX: Показываем bitmap сразу если он есть (даже во время загрузки нового)
|
||||
when {
|
||||
bitmap != null -> {
|
||||
Image(
|
||||
@@ -1076,8 +1092,8 @@ private fun FullSizeAvatar(
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
}
|
||||
!isLoading -> {
|
||||
// Placeholder только когда точно нет аватарки
|
||||
initialLoadComplete -> {
|
||||
// Placeholder только когда точно нет аватарки И загрузка завершена
|
||||
val avatarColors = getAvatarColor(publicKey, isDarkTheme)
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize().background(avatarColors.backgroundColor),
|
||||
@@ -1091,7 +1107,8 @@ private fun FullSizeAvatar(
|
||||
)
|
||||
}
|
||||
}
|
||||
// Пока isLoading=true - ничего не показываем (прозрачно)
|
||||
// Пока initialLoadComplete=false - ничего не показываем (прозрачно)
|
||||
// Это только самый первый момент загрузки
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user