refactor: Clean up imports and improve code formatting in OtherProfileScreen

This commit is contained in:
k1ngsterr1
2026-01-31 04:09:28 +05:00
parent 3ed4986393
commit c6f1998dc9

View File

@@ -1,32 +1,21 @@
package com.rosetta.messenger.ui.settings package com.rosetta.messenger.ui.settings
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Block import androidx.compose.material.icons.outlined.Block
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rosetta.messenger.data.MessageRepository
import com.rosetta.messenger.database.RosettaDatabase
import com.rosetta.messenger.ui.chats.ChatViewModel
import com.rosetta.messenger.ui.chats.ChatsListViewModel
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import com.rosetta.messenger.ui.components.VerifiedBadge
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
@@ -41,17 +30,22 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rosetta.messenger.data.MessageRepository
import com.rosetta.messenger.database.RosettaDatabase
import com.rosetta.messenger.network.SearchUser import com.rosetta.messenger.network.SearchUser
import com.rosetta.messenger.repository.AvatarRepository import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.chats.ChatViewModel
import com.rosetta.messenger.ui.chats.ChatsListViewModel
import com.rosetta.messenger.ui.components.AvatarImage import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.ui.components.BlurredAvatarBackground import com.rosetta.messenger.ui.components.BlurredAvatarBackground
import com.rosetta.messenger.ui.components.VerifiedBadge
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.math.roundToInt
// Collapsing header constants // Collapsing header constants
private val EXPANDED_HEADER_HEIGHT_OTHER = 280.dp private val EXPANDED_HEADER_HEIGHT_OTHER = 280.dp
@@ -62,10 +56,10 @@ private val AVATAR_SIZE_COLLAPSED_OTHER = 36.dp
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable @Composable
fun OtherProfileScreen( fun OtherProfileScreen(
user: SearchUser, user: SearchUser,
isDarkTheme: Boolean, isDarkTheme: Boolean,
onBack: () -> Unit, onBack: () -> Unit,
avatarRepository: AvatarRepository? = null avatarRepository: AvatarRepository? = null
) { ) {
var isBlocked by remember { mutableStateOf(false) } var isBlocked by remember { mutableStateOf(false) }
var showAvatarMenu by remember { mutableStateOf(false) } var showAvatarMenu by remember { mutableStateOf(false) }
@@ -84,9 +78,7 @@ fun OtherProfileScreen(
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
// 🔥 Загружаем статус блокировки при открытии экрана // 🔥 Загружаем статус блокировки при открытии экрана
LaunchedEffect(user.publicKey) { LaunchedEffect(user.publicKey) { isBlocked = chatsListViewModel.isUserBlocked(user.publicKey) }
isBlocked = chatsListViewModel.isUserBlocked(user.publicKey)
}
// 🎹 Для закрытия клавиатуры // 🎹 Для закрытия клавиатуры
val keyboardController = LocalSoftwareKeyboardController.current val keyboardController = LocalSoftwareKeyboardController.current
@@ -103,8 +95,10 @@ fun OtherProfileScreen(
// <20>🟢 Наблюдаем за онлайн статусом пользователя в реальном времени // <20>🟢 Наблюдаем за онлайн статусом пользователя в реальном времени
val messageRepository = remember { MessageRepository.getInstance(context) } val messageRepository = remember { MessageRepository.getInstance(context) }
val onlineStatus by messageRepository.observeUserOnlineStatus(user.publicKey) val onlineStatus by
.collectAsState(initial = false to 0L) messageRepository
.observeUserOnlineStatus(user.publicKey)
.collectAsState(initial = false to 0L)
val isOnline = onlineStatus.first val isOnline = onlineStatus.first
val lastSeen = onlineStatus.second val lastSeen = onlineStatus.second
@@ -112,15 +106,14 @@ fun OtherProfileScreen(
val density = LocalDensity.current val density = LocalDensity.current
val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
val expandedHeightPx = with(density) { (EXPANDED_HEADER_HEIGHT_OTHER + statusBarHeight).toPx() } val expandedHeightPx = with(density) { (EXPANDED_HEADER_HEIGHT_OTHER + statusBarHeight).toPx() }
val collapsedHeightPx = with(density) { (COLLAPSED_HEADER_HEIGHT_OTHER + statusBarHeight).toPx() } val collapsedHeightPx =
with(density) { (COLLAPSED_HEADER_HEIGHT_OTHER + statusBarHeight).toPx() }
var scrollOffset by remember { mutableFloatStateOf(0f) } var scrollOffset by remember { mutableFloatStateOf(0f) }
val maxScrollOffset = expandedHeightPx - collapsedHeightPx val maxScrollOffset = expandedHeightPx - collapsedHeightPx
val collapseProgress by remember { val collapseProgress by remember {
derivedStateOf { derivedStateOf { (scrollOffset / maxScrollOffset).coerceIn(0f, 1f) }
(scrollOffset / maxScrollOffset).coerceIn(0f, 1f)
}
} }
val nestedScrollConnection = remember { val nestedScrollConnection = remember {
@@ -128,19 +121,22 @@ fun OtherProfileScreen(
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val delta = available.y val delta = available.y
val newOffset = scrollOffset - delta val newOffset = scrollOffset - delta
val consumed = when { val consumed =
delta < 0 && scrollOffset < maxScrollOffset -> { when {
val consumed = (newOffset.coerceIn(0f, maxScrollOffset) - scrollOffset) delta < 0 && scrollOffset < maxScrollOffset -> {
scrollOffset = newOffset.coerceIn(0f, maxScrollOffset) val consumed =
-consumed (newOffset.coerceIn(0f, maxScrollOffset) - scrollOffset)
} scrollOffset = newOffset.coerceIn(0f, maxScrollOffset)
delta > 0 && scrollOffset > 0 -> { -consumed
val consumed = scrollOffset - newOffset.coerceIn(0f, maxScrollOffset) }
scrollOffset = newOffset.coerceIn(0f, maxScrollOffset) delta > 0 && scrollOffset > 0 -> {
consumed val consumed =
} scrollOffset - newOffset.coerceIn(0f, maxScrollOffset)
else -> 0f scrollOffset = newOffset.coerceIn(0f, maxScrollOffset)
} consumed
}
else -> 0f
}
return Offset(0f, consumed) return Offset(0f, consumed)
} }
} }
@@ -150,16 +146,21 @@ fun OtherProfileScreen(
BackHandler { onBack() } BackHandler { onBack() }
Box( Box(
modifier = Modifier modifier =
.fillMaxSize() Modifier.fillMaxSize()
.background(backgroundColor) .background(backgroundColor)
.nestedScroll(nestedScrollConnection) .nestedScroll(nestedScrollConnection)
) { ) {
// Scrollable content // Scrollable content
LazyColumn( LazyColumn(
modifier = Modifier modifier =
.fillMaxSize() Modifier.fillMaxSize()
.padding(top = with(density) { (expandedHeightPx - scrollOffset).toDp() }) .padding(
top =
with(density) {
(expandedHeightPx - scrollOffset).toDp()
}
)
) { ) {
item { item {
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@@ -171,10 +172,10 @@ fun OtherProfileScreen(
TelegramSectionTitle(title = "Info", isDarkTheme = isDarkTheme) TelegramSectionTitle(title = "Info", isDarkTheme = isDarkTheme)
TelegramCopyField( TelegramCopyField(
value = "@${user.username}", value = "@${user.username}",
fullValue = user.username, fullValue = user.username,
label = "Username", label = "Username",
isDarkTheme = isDarkTheme isDarkTheme = isDarkTheme
) )
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
@@ -184,10 +185,10 @@ fun OtherProfileScreen(
TelegramSectionTitle(title = "Public Key", isDarkTheme = isDarkTheme) TelegramSectionTitle(title = "Public Key", isDarkTheme = isDarkTheme)
TelegramCopyField( TelegramCopyField(
value = user.publicKey.take(16) + "..." + user.publicKey.takeLast(6), value = user.publicKey.take(16) + "..." + user.publicKey.takeLast(6),
fullValue = user.publicKey, fullValue = user.publicKey,
label = "Public Key", label = "Public Key",
isDarkTheme = isDarkTheme isDarkTheme = isDarkTheme
) )
Spacer(modifier = Modifier.height(32.dp)) Spacer(modifier = Modifier.height(32.dp))
@@ -198,43 +199,43 @@ fun OtherProfileScreen(
// 🎨 COLLAPSING HEADER // 🎨 COLLAPSING HEADER
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
CollapsingOtherProfileHeader( CollapsingOtherProfileHeader(
name = user.title.ifEmpty { "Unknown User" }, name = user.title.ifEmpty { "Unknown User" },
username = user.username, username = user.username,
publicKey = user.publicKey, publicKey = user.publicKey,
verified = user.verified, verified = user.verified,
isOnline = isOnline, isOnline = isOnline,
lastSeen = lastSeen, lastSeen = lastSeen,
avatarColors = avatarColors, avatarColors = avatarColors,
collapseProgress = collapseProgress, collapseProgress = collapseProgress,
onBack = onBack, onBack = onBack,
isDarkTheme = isDarkTheme, isDarkTheme = isDarkTheme,
showAvatarMenu = showAvatarMenu, showAvatarMenu = showAvatarMenu,
onAvatarMenuChange = { showAvatarMenu = it }, onAvatarMenuChange = { showAvatarMenu = it },
isBlocked = isBlocked, isBlocked = isBlocked,
onBlockToggle = { onBlockToggle = {
coroutineScope.launch { coroutineScope.launch {
if (isBlocked) { if (isBlocked) {
chatsListViewModel.unblockUser(user.publicKey) chatsListViewModel.unblockUser(user.publicKey)
} else { } else {
chatsListViewModel.blockUser(user.publicKey) chatsListViewModel.blockUser(user.publicKey)
}
// Обновляем локальное состояние
isBlocked = !isBlocked
} }
// Обновляем локальное состояние },
isBlocked = !isBlocked avatarRepository = avatarRepository,
} onClearChat = {
}, viewModel.clearChatHistory()
avatarRepository = avatarRepository, // 🗑️ Удаляем диалог из списка после очистки истории
onClearChat = { CoroutineScope(Dispatchers.IO).launch {
viewModel.clearChatHistory() try {
// 🗑️ Удаляем диалог из списка после очистки истории val account = viewModel.myPublicKey ?: return@launch
CoroutineScope(Dispatchers.IO).launch { database.dialogDao().deleteDialog(account, user.publicKey)
try { } catch (e: Exception) {
val account = viewModel.myPublicKey ?: return@launch android.util.Log.e("OtherProfileScreen", "Failed to delete dialog", e)
database.dialogDao().deleteDialog(account, user.publicKey) }
} catch (e: Exception) {
android.util.Log.e("OtherProfileScreen", "Failed to delete dialog", e)
} }
} }
}
) )
} }
} }
@@ -243,22 +244,22 @@ fun OtherProfileScreen(
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
@Composable @Composable
private fun CollapsingOtherProfileHeader( private fun CollapsingOtherProfileHeader(
name: String, name: String,
username: String, username: String,
publicKey: String, publicKey: String,
verified: Int, verified: Int,
isOnline: Boolean, isOnline: Boolean,
lastSeen: Long, lastSeen: Long,
avatarColors: AvatarColors, avatarColors: AvatarColors,
collapseProgress: Float, collapseProgress: Float,
onBack: () -> Unit, onBack: () -> Unit,
isDarkTheme: Boolean, isDarkTheme: Boolean,
showAvatarMenu: Boolean, showAvatarMenu: Boolean,
onAvatarMenuChange: (Boolean) -> Unit, onAvatarMenuChange: (Boolean) -> Unit,
isBlocked: Boolean, isBlocked: Boolean,
onBlockToggle: () -> Unit, onBlockToggle: () -> Unit,
avatarRepository: AvatarRepository? = null, avatarRepository: AvatarRepository? = null,
onClearChat: () -> Unit onClearChat: () -> Unit
) { ) {
val density = LocalDensity.current val density = LocalDensity.current
val configuration = LocalConfiguration.current val configuration = LocalConfiguration.current
@@ -269,14 +270,16 @@ private fun CollapsingOtherProfileHeader(
val expandedHeight = EXPANDED_HEADER_HEIGHT_OTHER + statusBarHeight val expandedHeight = EXPANDED_HEADER_HEIGHT_OTHER + statusBarHeight
val collapsedHeight = COLLAPSED_HEADER_HEIGHT_OTHER + statusBarHeight val collapsedHeight = COLLAPSED_HEADER_HEIGHT_OTHER + statusBarHeight
val headerHeight = androidx.compose.ui.unit.lerp(expandedHeight, collapsedHeight, collapseProgress) val headerHeight =
androidx.compose.ui.unit.lerp(expandedHeight, collapsedHeight, collapseProgress)
// Avatar animation // Avatar animation
val avatarCenterX = (screenWidthDp - AVATAR_SIZE_EXPANDED_OTHER) / 2 val avatarCenterX = (screenWidthDp - AVATAR_SIZE_EXPANDED_OTHER) / 2
val avatarStartY = statusBarHeight + 32.dp val avatarStartY = statusBarHeight + 32.dp
val avatarEndY = statusBarHeight - 60.dp val avatarEndY = statusBarHeight - 60.dp
val avatarY = androidx.compose.ui.unit.lerp(avatarStartY, avatarEndY, collapseProgress) val avatarY = androidx.compose.ui.unit.lerp(avatarStartY, avatarEndY, collapseProgress)
val avatarSize = androidx.compose.ui.unit.lerp(AVATAR_SIZE_EXPANDED_OTHER, 0.dp, collapseProgress) val avatarSize =
androidx.compose.ui.unit.lerp(AVATAR_SIZE_EXPANDED_OTHER, 0.dp, collapseProgress)
val avatarFontSize = androidx.compose.ui.unit.lerp(40.sp, 0.sp, collapseProgress) val avatarFontSize = androidx.compose.ui.unit.lerp(40.sp, 0.sp, collapseProgress)
// Text animation - always centered // Text animation - always centered
@@ -287,41 +290,34 @@ private fun CollapsingOtherProfileHeader(
val nameFontSize = androidx.compose.ui.unit.lerp(24.sp, 18.sp, collapseProgress) val nameFontSize = androidx.compose.ui.unit.lerp(24.sp, 18.sp, collapseProgress)
val onlineFontSize = androidx.compose.ui.unit.lerp(14.sp, 13.sp, collapseProgress) val onlineFontSize = androidx.compose.ui.unit.lerp(14.sp, 13.sp, collapseProgress)
Box( Box(modifier = Modifier.fillMaxWidth().height(headerHeight)) {
modifier = Modifier
.fillMaxWidth()
.height(headerHeight)
) {
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// 🎨 BLURRED AVATAR BACKGROUND // 🎨 BLURRED AVATAR BACKGROUND
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
BlurredAvatarBackground( BlurredAvatarBackground(
publicKey = publicKey, publicKey = publicKey,
avatarRepository = avatarRepository, avatarRepository = avatarRepository,
fallbackColor = avatarColors.backgroundColor, fallbackColor = avatarColors.backgroundColor,
blurRadius = 25f, blurRadius = 25f,
alpha = 0.3f alpha = 0.3f
) )
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// 🔙 BACK BUTTON // 🔙 BACK BUTTON
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
Box( Box(
modifier = Modifier modifier =
.padding(top = statusBarHeight) Modifier.padding(top = statusBarHeight)
.padding(start = 4.dp, top = 4.dp) .padding(start = 4.dp, top = 4.dp)
.size(48.dp), .size(48.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
IconButton( IconButton(onClick = onBack, modifier = Modifier.size(48.dp)) {
onClick = onBack,
modifier = Modifier.size(48.dp)
) {
Icon( Icon(
imageVector = Icons.Filled.ArrowBack, imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back", contentDescription = "Back",
tint = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White, tint = if (isDarkTheme) Color.White else Color(0xFF007AFF),
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
} }
} }
@@ -330,39 +326,38 @@ private fun CollapsingOtherProfileHeader(
// ⋮ MENU BUTTON (top right corner) // ⋮ MENU BUTTON (top right corner)
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
Box( Box(
modifier = Modifier modifier =
.align(Alignment.TopEnd) Modifier.align(Alignment.TopEnd)
.padding(top = statusBarHeight) .padding(top = statusBarHeight)
.padding(end = 4.dp, top = 4.dp) .padding(end = 4.dp, top = 4.dp)
.size(48.dp), .size(48.dp),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
IconButton( IconButton(onClick = { onAvatarMenuChange(true) }, modifier = Modifier.size(48.dp)) {
onClick = { onAvatarMenuChange(true) },
modifier = Modifier.size(48.dp)
) {
Icon( Icon(
imageVector = Icons.Default.MoreVert, imageVector = Icons.Default.MoreVert,
contentDescription = "Profile menu", contentDescription = "Profile menu",
tint = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White, tint =
modifier = Modifier.size(24.dp) if (isColorLight(avatarColors.backgroundColor)) Color.Black
else Color.White,
modifier = Modifier.size(24.dp)
) )
} }
// Меню с блокировкой пользователя // Меню с блокировкой пользователя
com.rosetta.messenger.ui.chats.components.OtherProfileMenu( com.rosetta.messenger.ui.chats.components.OtherProfileMenu(
expanded = showAvatarMenu, expanded = showAvatarMenu,
onDismiss = { onAvatarMenuChange(false) }, onDismiss = { onAvatarMenuChange(false) },
isDarkTheme = isDarkTheme, isDarkTheme = isDarkTheme,
isBlocked = isBlocked, isBlocked = isBlocked,
onBlockClick = { onBlockClick = {
onAvatarMenuChange(false) onAvatarMenuChange(false)
onBlockToggle() onBlockToggle()
}, },
onClearChatClick = { onClearChatClick = {
onAvatarMenuChange(false) onAvatarMenuChange(false)
onClearChat() onClearChat()
} }
) )
} }
@@ -371,23 +366,26 @@ private fun CollapsingOtherProfileHeader(
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
if (avatarSize > 1.dp) { if (avatarSize > 1.dp) {
Box( Box(
modifier = Modifier modifier =
.offset( Modifier.offset(
x = avatarCenterX + (AVATAR_SIZE_EXPANDED_OTHER - avatarSize) / 2, x =
y = avatarY avatarCenterX +
) (AVATAR_SIZE_EXPANDED_OTHER -
.size(avatarSize) avatarSize) / 2,
.clip(CircleShape) y = avatarY
.background(Color.White.copy(alpha = 0.15f)) )
.padding(2.dp) .size(avatarSize)
.clip(CircleShape), .clip(CircleShape)
contentAlignment = Alignment.Center .background(Color.White.copy(alpha = 0.15f))
.padding(2.dp)
.clip(CircleShape),
contentAlignment = Alignment.Center
) { ) {
AvatarImage( AvatarImage(
publicKey = publicKey, publicKey = publicKey,
avatarRepository = avatarRepository, avatarRepository = avatarRepository,
size = avatarSize - 4.dp, size = avatarSize - 4.dp,
isDarkTheme = isDarkTheme isDarkTheme = isDarkTheme
) )
} }
} }
@@ -396,38 +394,40 @@ private fun CollapsingOtherProfileHeader(
// 📝 TEXT BLOCK - Name + Verified + Online, always centered // 📝 TEXT BLOCK - Name + Verified + Online, always centered
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
Column( Column(
modifier = Modifier modifier =
.align(Alignment.TopCenter) Modifier.align(Alignment.TopCenter).offset(y = textY).graphicsLayer {
.offset(y = textY) val centerOffsetY =
.graphicsLayer { with(density) {
val centerOffsetY = with(density) { androidx.compose
androidx.compose.ui.unit.lerp(24.dp, 18.dp, collapseProgress).toPx() .ui
} .unit
translationY = -centerOffsetY .lerp(24.dp, 18.dp, collapseProgress)
}, .toPx()
horizontalAlignment = Alignment.CenterHorizontally }
translationY = -centerOffsetY
},
horizontalAlignment = Alignment.CenterHorizontally
) { ) {
// Name + Verified Badge // Name + Verified Badge
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
) { ) {
Text( Text(
text = name, text = name,
fontSize = nameFontSize, fontSize = nameFontSize,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
color = if (isColorLight(avatarColors.backgroundColor)) Color.Black else Color.White, color =
maxLines = 1, if (isColorLight(avatarColors.backgroundColor)) Color.Black
overflow = TextOverflow.Ellipsis, else Color.White,
textAlign = TextAlign.Center maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
) )
if (verified > 0) { if (verified > 0) {
Spacer(modifier = Modifier.width(4.dp)) Spacer(modifier = Modifier.width(4.dp))
VerifiedBadge( VerifiedBadge(verified = verified, size = (nameFontSize.value * 0.8f).toInt())
verified = verified,
size = (nameFontSize.value * 0.8f).toInt()
)
} }
} }
@@ -435,13 +435,16 @@ private fun CollapsingOtherProfileHeader(
// Online/Offline status // Online/Offline status
Text( Text(
text = if (isOnline) "online" else "offline", text = if (isOnline) "online" else "offline",
fontSize = onlineFontSize, fontSize = onlineFontSize,
color = if (isOnline) { color =
Color(0xFF4CAF50) if (isOnline) {
} else { Color(0xFF4CAF50)
if (isColorLight(avatarColors.backgroundColor)) Color.Black.copy(alpha = 0.6f) else Color.White.copy(alpha = 0.6f) } else {
} if (isColorLight(avatarColors.backgroundColor))
Color.Black.copy(alpha = 0.6f)
else Color.White.copy(alpha = 0.6f)
}
) )
} }
} }
@@ -451,43 +454,41 @@ private fun CollapsingOtherProfileHeader(
// 🚫 BLOCK/UNBLOCK ITEM // 🚫 BLOCK/UNBLOCK ITEM
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
@Composable @Composable
private fun TelegramBlockItem( private fun TelegramBlockItem(isBlocked: Boolean, onToggle: () -> Unit, isDarkTheme: Boolean) {
isBlocked: Boolean,
onToggle: () -> Unit,
isDarkTheme: Boolean
) {
val textColor = if (isDarkTheme) Color.White else Color.Black val textColor = if (isDarkTheme) Color.White else Color.Black
val iconColor = PrimaryBlue val iconColor = PrimaryBlue
Row( Row(
modifier = Modifier modifier =
.fillMaxWidth() Modifier.fillMaxWidth()
.clickable(onClick = onToggle) .clickable(onClick = onToggle)
.padding(horizontal = 16.dp, vertical = 14.dp), .padding(horizontal = 16.dp, vertical = 14.dp),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Icon( Icon(
imageVector = Icons.Outlined.Block, imageVector = Icons.Outlined.Block,
contentDescription = null, contentDescription = null,
tint = iconColor, tint = iconColor,
modifier = Modifier.size(24.dp) modifier = Modifier.size(24.dp)
) )
Spacer(modifier = Modifier.width(20.dp)) Spacer(modifier = Modifier.width(20.dp))
Column(modifier = Modifier.weight(1f)) { Column(modifier = Modifier.weight(1f)) {
Text( Text(
text = if (isBlocked) "Unblock User" else "Block User", text = if (isBlocked) "Unblock User" else "Block User",
fontSize = 16.sp, fontSize = 16.sp,
color = iconColor, color = iconColor,
fontWeight = FontWeight.Medium fontWeight = FontWeight.Medium
) )
Spacer(modifier = Modifier.height(2.dp)) Spacer(modifier = Modifier.height(2.dp))
Text( Text(
text = if (isBlocked) "Allow this user to message you" else "Prevent this user from messaging you", text =
fontSize = 13.sp, if (isBlocked) "Allow this user to message you"
color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666), else "Prevent this user from messaging you",
lineHeight = 16.sp fontSize = 13.sp,
color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666),
lineHeight = 16.sp
) )
} }
} }