feat: Implement collapsing header and block/unblock functionality in OtherProfileScreen
This commit is contained in:
@@ -1,25 +1,46 @@
|
|||||||
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.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
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.outlined.Block
|
import androidx.compose.material.icons.outlined.Block
|
||||||
import androidx.compose.material.icons.outlined.ContentCopy
|
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
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.input.nestedscroll.NestedScrollConnection
|
||||||
|
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
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 com.rosetta.messenger.network.SearchUser
|
import com.rosetta.messenger.network.SearchUser
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
// Collapsing header constants
|
||||||
|
private val EXPANDED_HEADER_HEIGHT_OTHER = 280.dp
|
||||||
|
private val COLLAPSED_HEADER_HEIGHT_OTHER = 64.dp
|
||||||
|
private val AVATAR_SIZE_EXPANDED_OTHER = 120.dp
|
||||||
|
private val AVATAR_SIZE_COLLAPSED_OTHER = 36.dp
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun OtherProfileScreen(
|
fun OtherProfileScreen(
|
||||||
user: SearchUser,
|
user: SearchUser,
|
||||||
@@ -31,182 +52,313 @@ fun OtherProfileScreen(
|
|||||||
val surfaceColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color(0xFFF2F2F7)
|
val surfaceColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color(0xFFF2F2F7)
|
||||||
val textColor = if (isDarkTheme) Color.White else Color.Black
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
val secondaryTextColor = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666)
|
val secondaryTextColor = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666)
|
||||||
|
val avatarColors = getAvatarColor(user.publicKey, isDarkTheme)
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
// Scroll state for collapsing header animation
|
||||||
|
val density = LocalDensity.current
|
||||||
|
val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
|
||||||
|
val expandedHeightPx = with(density) { (EXPANDED_HEADER_HEIGHT_OTHER + statusBarHeight).toPx() }
|
||||||
|
val collapsedHeightPx = with(density) { (COLLAPSED_HEADER_HEIGHT_OTHER + statusBarHeight).toPx() }
|
||||||
|
|
||||||
|
var scrollOffset by remember { mutableFloatStateOf(0f) }
|
||||||
|
val maxScrollOffset = expandedHeightPx - collapsedHeightPx
|
||||||
|
|
||||||
|
val collapseProgress by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
(scrollOffset / maxScrollOffset).coerceIn(0f, 1f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val nestedScrollConnection = remember {
|
||||||
|
object : NestedScrollConnection {
|
||||||
|
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||||
|
val delta = available.y
|
||||||
|
val newOffset = scrollOffset - delta
|
||||||
|
val consumed = when {
|
||||||
|
delta < 0 && scrollOffset < maxScrollOffset -> {
|
||||||
|
val consumed = (newOffset.coerceIn(0f, maxScrollOffset) - scrollOffset)
|
||||||
|
scrollOffset = newOffset.coerceIn(0f, maxScrollOffset)
|
||||||
|
-consumed
|
||||||
|
}
|
||||||
|
delta > 0 && scrollOffset > 0 -> {
|
||||||
|
val consumed = scrollOffset - newOffset.coerceIn(0f, maxScrollOffset)
|
||||||
|
scrollOffset = newOffset.coerceIn(0f, maxScrollOffset)
|
||||||
|
consumed
|
||||||
|
}
|
||||||
|
else -> 0f
|
||||||
|
}
|
||||||
|
return Offset(0f, consumed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle back gesture
|
// Handle back gesture
|
||||||
BackHandler { onBack() }
|
BackHandler { onBack() }
|
||||||
|
|
||||||
Column(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.verticalScroll(rememberScrollState())
|
.nestedScroll(nestedScrollConnection)
|
||||||
) {
|
) {
|
||||||
// Profile Card with avatar
|
// Scrollable content
|
||||||
ProfileCard(
|
LazyColumn(
|
||||||
name = user.title.ifEmpty { "Unknown User" },
|
|
||||||
username = user.username.ifEmpty { "" },
|
|
||||||
publicKey = user.publicKey,
|
|
||||||
isDarkTheme = isDarkTheme,
|
|
||||||
onBack = onBack,
|
|
||||||
hasChanges = false,
|
|
||||||
onSave = {}
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
|
|
||||||
// Username Section (if available)
|
|
||||||
if (user.username.isNotBlank()) {
|
|
||||||
Text(
|
|
||||||
text = "Username",
|
|
||||||
fontSize = 14.sp,
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.padding(bottom = 8.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
Surface(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
color = surfaceColor,
|
|
||||||
shape = RoundedCornerShape(12.dp)
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxSize()
|
||||||
.padding(16.dp),
|
.padding(top = with(density) { (expandedHeightPx - scrollOffset).toDp() })
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
) {
|
||||||
Text(
|
item {
|
||||||
text = "@${user.username}",
|
|
||||||
fontSize = 16.sp,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
IconButton(
|
|
||||||
onClick = { /* TODO: Copy to clipboard */ }
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.ContentCopy,
|
|
||||||
contentDescription = "Copy",
|
|
||||||
tint = secondaryTextColor,
|
|
||||||
modifier = Modifier.size(20.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = "Username for search user or send message.",
|
|
||||||
fontSize = 12.sp,
|
|
||||||
color = secondaryTextColor,
|
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp),
|
|
||||||
lineHeight = 16.sp
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// 📋 INFO SECTION
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
if (user.username.isNotBlank()) {
|
||||||
|
TelegramSectionTitle(title = "Info", isDarkTheme = isDarkTheme)
|
||||||
|
|
||||||
|
TelegramCopyField(
|
||||||
|
value = "@${user.username}",
|
||||||
|
fullValue = user.username,
|
||||||
|
label = "Username",
|
||||||
|
isDarkTheme = isDarkTheme
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public Key Section
|
// Public Key Section
|
||||||
Text(
|
TelegramSectionTitle(title = "Public Key", isDarkTheme = isDarkTheme)
|
||||||
text = "Public Key",
|
|
||||||
fontSize = 14.sp,
|
|
||||||
fontWeight = FontWeight.SemiBold,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.padding(bottom = 8.dp)
|
|
||||||
)
|
|
||||||
|
|
||||||
Surface(
|
TelegramCopyField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
value = user.publicKey.take(16) + "..." + user.publicKey.takeLast(6),
|
||||||
color = surfaceColor,
|
fullValue = user.publicKey,
|
||||||
shape = RoundedCornerShape(12.dp)
|
label = "Public Key",
|
||||||
) {
|
isDarkTheme = isDarkTheme
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = user.publicKey.take(20) + "..." + user.publicKey.takeLast(20),
|
|
||||||
fontSize = 12.sp,
|
|
||||||
color = textColor,
|
|
||||||
modifier = Modifier.weight(1f)
|
|
||||||
)
|
|
||||||
IconButton(
|
|
||||||
onClick = { /* TODO: Copy to clipboard */ }
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.ContentCopy,
|
|
||||||
contentDescription = "Copy",
|
|
||||||
tint = secondaryTextColor,
|
|
||||||
modifier = Modifier.size(20.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = "This is user public key. If user haven't set a @username yet, you can send message using public key.",
|
|
||||||
fontSize = 12.sp,
|
|
||||||
color = secondaryTextColor,
|
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp),
|
|
||||||
lineHeight = 16.sp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
// Block/Unblock Section
|
// ═══════════════════════════════════════════════════════════
|
||||||
Surface(
|
// 🚫 BLOCK SECTION
|
||||||
modifier = Modifier.fillMaxWidth(),
|
// ═══════════════════════════════════════════════════════════
|
||||||
color = surfaceColor,
|
TelegramSectionTitle(title = "Privacy", isDarkTheme = isDarkTheme)
|
||||||
shape = RoundedCornerShape(16.dp)
|
|
||||||
) {
|
|
||||||
Column {
|
|
||||||
if (isBlocked) {
|
|
||||||
ProfileNavigationItem(
|
|
||||||
icon = Icons.Outlined.Block,
|
|
||||||
iconBackground = Color(0xFF2E7D32), // green
|
|
||||||
title = "Unblock User",
|
|
||||||
subtitle = "Allow this user to message you",
|
|
||||||
onClick = {
|
|
||||||
isBlocked = false
|
|
||||||
// TODO: Implement actual unblock logic
|
|
||||||
},
|
|
||||||
isDarkTheme = isDarkTheme,
|
|
||||||
hideChevron = true,
|
|
||||||
textColor = Color(0xFF2E7D32)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
ProfileNavigationItem(
|
|
||||||
icon = Icons.Outlined.Block,
|
|
||||||
iconBackground = if (isDarkTheme) Color(0xFFFF8787) else Color(0xFFEF4444),
|
|
||||||
title = "Block this user",
|
|
||||||
subtitle = "Prevent this user from messaging you",
|
|
||||||
onClick = {
|
|
||||||
isBlocked = true
|
|
||||||
// TODO: Implement actual block logic
|
|
||||||
},
|
|
||||||
isDarkTheme = isDarkTheme,
|
|
||||||
hideChevron = true,
|
|
||||||
textColor = if (isDarkTheme) Color(0xFFFF8787) else Color(0xFFEF4444)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
TelegramBlockItem(
|
||||||
text = if (isBlocked) {
|
isBlocked = isBlocked,
|
||||||
"If you want the user to be able to send you messages again, you can unblock them. You can block them later."
|
onToggle = { isBlocked = !isBlocked },
|
||||||
} else {
|
isDarkTheme = isDarkTheme
|
||||||
"The person will no longer be able to message you if you block them. You can unblock them later."
|
|
||||||
},
|
|
||||||
fontSize = 12.sp,
|
|
||||||
color = secondaryTextColor,
|
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp),
|
|
||||||
lineHeight = 16.sp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(32.dp))
|
Spacer(modifier = Modifier.height(32.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// 🎨 COLLAPSING HEADER
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
CollapsingOtherProfileHeader(
|
||||||
|
name = user.title.ifEmpty { "Unknown User" },
|
||||||
|
username = user.username,
|
||||||
|
publicKey = user.publicKey,
|
||||||
|
avatarColors = avatarColors,
|
||||||
|
collapseProgress = collapseProgress,
|
||||||
|
onBack = onBack,
|
||||||
|
isDarkTheme = isDarkTheme
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// 🎯 COLLAPSING HEADER FOR OTHER PROFILE
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
@Composable
|
||||||
|
private fun CollapsingOtherProfileHeader(
|
||||||
|
name: String,
|
||||||
|
username: String,
|
||||||
|
publicKey: String,
|
||||||
|
avatarColors: AvatarColors,
|
||||||
|
collapseProgress: Float,
|
||||||
|
onBack: () -> Unit,
|
||||||
|
isDarkTheme: Boolean
|
||||||
|
) {
|
||||||
|
val density = LocalDensity.current
|
||||||
|
val configuration = LocalConfiguration.current
|
||||||
|
val screenWidthDp = configuration.screenWidthDp.dp
|
||||||
|
|
||||||
|
val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
|
||||||
|
|
||||||
|
val expandedHeight = EXPANDED_HEADER_HEIGHT_OTHER + statusBarHeight
|
||||||
|
val collapsedHeight = COLLAPSED_HEADER_HEIGHT_OTHER + statusBarHeight
|
||||||
|
|
||||||
|
val headerHeight = androidx.compose.ui.unit.lerp(expandedHeight, collapsedHeight, collapseProgress)
|
||||||
|
|
||||||
|
// Avatar animation
|
||||||
|
val avatarCenterX = (screenWidthDp - AVATAR_SIZE_EXPANDED_OTHER) / 2
|
||||||
|
val avatarStartY = statusBarHeight + 32.dp
|
||||||
|
val avatarEndY = statusBarHeight - 60.dp
|
||||||
|
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 avatarFontSize = androidx.compose.ui.unit.lerp(40.sp, 0.sp, collapseProgress)
|
||||||
|
|
||||||
|
// Text animation
|
||||||
|
val textExpandedX = screenWidthDp / 2
|
||||||
|
val textCollapsedX = 48.dp + 12.dp
|
||||||
|
val textX = androidx.compose.ui.unit.lerp(textExpandedX, textCollapsedX, collapseProgress)
|
||||||
|
|
||||||
|
val textExpandedY = statusBarHeight + 32.dp + AVATAR_SIZE_EXPANDED_OTHER + 48.dp
|
||||||
|
val textCollapsedY = statusBarHeight + (COLLAPSED_HEADER_HEIGHT_OTHER - 40.dp) / 2
|
||||||
|
val textY = androidx.compose.ui.unit.lerp(textExpandedY, textCollapsedY, collapseProgress)
|
||||||
|
|
||||||
|
val nameFontSize = androidx.compose.ui.unit.lerp(24.sp, 17.sp, collapseProgress)
|
||||||
|
val usernameFontSize = androidx.compose.ui.unit.lerp(15.sp, 13.sp, collapseProgress)
|
||||||
|
|
||||||
|
val headerColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color.White
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(headerHeight)
|
||||||
|
.background(headerColor)
|
||||||
|
) {
|
||||||
|
// Background color
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(headerColor)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Avatar
|
||||||
|
if (avatarSize > 0.dp) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.offset {
|
||||||
|
IntOffset(
|
||||||
|
with(density) { avatarCenterX.toPx().roundToInt() },
|
||||||
|
with(density) { avatarY.toPx().roundToInt() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.size(avatarSize)
|
||||||
|
.clip(CircleShape)
|
||||||
|
.background(avatarColors.backgroundColor),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
if (avatarFontSize.value > 0) {
|
||||||
|
Text(
|
||||||
|
text = getInitials(name),
|
||||||
|
fontSize = avatarFontSize,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = avatarColors.textColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name and username
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.offset {
|
||||||
|
IntOffset(
|
||||||
|
with(density) { textX.toPx().roundToInt() },
|
||||||
|
with(density) { textY.toPx().roundToInt() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.graphicsLayer {
|
||||||
|
transformOrigin = androidx.compose.ui.graphics.TransformOrigin(
|
||||||
|
pivotFractionX = if (collapseProgress > 0.5f) 0f else 0.5f,
|
||||||
|
pivotFractionY = 0.5f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = if (collapseProgress > 0.5f) Alignment.Start else Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = name,
|
||||||
|
fontSize = nameFontSize,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = if (isDarkTheme) Color.White else Color.Black,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
|
||||||
|
if (username.isNotEmpty() && collapseProgress < 0.9f) {
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = "@$username",
|
||||||
|
fontSize = usernameFontSize,
|
||||||
|
color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.graphicsLayer {
|
||||||
|
alpha = 1f - (collapseProgress * 2f).coerceIn(0f, 1f)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Back button
|
||||||
|
IconButton(
|
||||||
|
onClick = onBack,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = statusBarHeight)
|
||||||
|
.padding(start = 4.dp, top = 4.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = "Back",
|
||||||
|
tint = if (isDarkTheme) Color.White else Color.Black
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
// 🚫 BLOCK/UNBLOCK ITEM
|
||||||
|
// ═══════════════════════════════════════════════════════════
|
||||||
|
@Composable
|
||||||
|
private fun TelegramBlockItem(
|
||||||
|
isBlocked: Boolean,
|
||||||
|
onToggle: () -> Unit,
|
||||||
|
isDarkTheme: Boolean
|
||||||
|
) {
|
||||||
|
val textColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
|
val iconColor = if (isBlocked) {
|
||||||
|
if (isDarkTheme) Color(0xFF66BB6A) else Color(0xFF4CAF50)
|
||||||
|
} else {
|
||||||
|
if (isDarkTheme) Color(0xFFFF8787) else Color(0xFFEF4444)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable(onClick = onToggle)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 14.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.Block,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = iconColor,
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
|
|
||||||
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
Text(
|
||||||
|
text = if (isBlocked) "Unblock User" else "Block User",
|
||||||
|
fontSize = 16.sp,
|
||||||
|
color = iconColor,
|
||||||
|
fontWeight = FontWeight.Medium
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
|
Text(
|
||||||
|
text = if (isBlocked) "Allow this user to message you" else "Prevent this user from messaging you",
|
||||||
|
fontSize = 13.sp,
|
||||||
|
color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666),
|
||||||
|
lineHeight = 16.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user