feat: Replace avatar placeholder with real image loading in ChatItem and RecentUserItem components

This commit is contained in:
k1ngsterr1
2026-01-28 02:10:00 +05:00
parent 3b4e4ee594
commit 6b59ed9bd8
2 changed files with 45 additions and 49 deletions

View File

@@ -10,6 +10,9 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.platform.LocalContext
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.components.AvatarImage
import androidx.compose.material3.*
import compose.icons.TablerIcons
import compose.icons.tablericons.*
@@ -1217,7 +1220,12 @@ private fun EmptyChatsState(isDarkTheme: Boolean, modifier: Modifier = Modifier)
// Chat item for list
@Composable
fun ChatItem(chat: Chat, isDarkTheme: Boolean, onClick: () -> Unit) {
fun ChatItem(
chat: Chat,
isDarkTheme: Boolean,
avatarRepository: com.rosetta.messenger.repository.AvatarRepository? = null,
onClick: () -> Unit
) {
val textColor = if (isDarkTheme) Color.White else Color.Black
val secondaryTextColor = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666)
val dividerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8)
@@ -1233,41 +1241,16 @@ fun ChatItem(chat: Chat, isDarkTheme: Boolean, onClick: () -> Unit) {
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
// Avatar
Box(
modifier =
Modifier.size(56.dp)
.clip(CircleShape)
.background(avatarColors.backgroundColor),
contentAlignment = Alignment.Center
) {
Text(
text = avatarText,
fontSize = 20.sp,
fontWeight = FontWeight.SemiBold,
color = avatarColors.textColor
// Avatar with real image
AvatarImage(
publicKey = chat.publicKey,
avatarRepository = avatarRepository,
size = 56.dp,
isDarkTheme = isDarkTheme,
showOnlineIndicator = true,
isOnline = chat.isOnline
)
// Online indicator
if (chat.isOnline) {
Box(
modifier =
Modifier.align(Alignment.BottomEnd)
.offset(x = 2.dp, y = 2.dp)
.size(16.dp)
.clip(CircleShape)
.background(
if (isDarkTheme)
Color(0xFF1A1A1A)
else Color.White
)
.padding(2.dp)
.clip(CircleShape)
.background(Color(0xFF4CAF50))
)
}
}
Spacer(modifier = Modifier.width(12.dp))
Column(modifier = Modifier.weight(1f)) {

View File

@@ -28,6 +28,9 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalView
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.database.RosettaDatabase
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@@ -84,6 +87,20 @@ fun SearchScreen(
// Recent users - отложенная подписка
val recentUsers by RecentSearchesManager.recentUsers.collectAsState()
// AvatarRepository для загрузки аватаров
val avatarRepository = remember(currentUserPublicKey) {
if (currentUserPublicKey.isNotBlank()) {
val database = RosettaDatabase.getDatabase(context)
AvatarRepository(
context = context,
avatarDao = database.avatarDao(),
currentPublicKey = currentUserPublicKey
)
} else {
null
}
}
// 🔥 ОПТИМИЗАЦИЯ: Lottie загружается асинхронно и не блокирует первый кадр
val searchLottieComposition by
rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.search))
@@ -258,6 +275,7 @@ fun SearchScreen(
isDarkTheme = isDarkTheme,
textColor = textColor,
secondaryTextColor = secondaryTextColor,
avatarRepository = avatarRepository,
onClick = {
hideKeyboardInstantly()
RecentSearchesManager.addUser(user)
@@ -325,6 +343,7 @@ private fun RecentUserItem(
isDarkTheme: Boolean,
textColor: Color,
secondaryTextColor: Color,
avatarRepository: AvatarRepository?,
onClick: () -> Unit,
onRemove: () -> Unit
) {
@@ -344,20 +363,14 @@ private fun RecentUserItem(
verticalAlignment = Alignment.CenterVertically
) {
// Avatar
Box(
modifier =
Modifier.size(48.dp)
.clip(CircleShape)
.background(avatarColors.backgroundColor),
contentAlignment = Alignment.Center
) {
Text(
text = initials,
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold,
color = avatarColors.textColor
AvatarImage(
publicKey = user.publicKey,
avatarRepository = avatarRepository,
size = 48.dp,
isDarkTheme = isDarkTheme,
showOnlineIndicator = false,
isOnline = false
)
}
Spacer(modifier = Modifier.width(12.dp))