feat: Replace avatar placeholder with real image loading in ChatItem and RecentUserItem components
This commit is contained in:
@@ -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,40 +1241,15 @@ 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
|
||||
)
|
||||
|
||||
// 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))
|
||||
)
|
||||
}
|
||||
}
|
||||
// Avatar with real image
|
||||
AvatarImage(
|
||||
publicKey = chat.publicKey,
|
||||
avatarRepository = avatarRepository,
|
||||
size = 56.dp,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showOnlineIndicator = true,
|
||||
isOnline = chat.isOnline
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user