From d0f6de1772c273009304ec4bd35b5f1ba365bcb8 Mon Sep 17 00:00:00 2001 From: k1ngsterr1 Date: Thu, 22 Jan 2026 18:50:47 +0500 Subject: [PATCH] feat: Add avatar menu functionality and improve header layout in OtherProfileScreen --- .../ui/settings/OtherProfileScreen.kt | 112 +++++++++++------- 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/rosetta/messenger/ui/settings/OtherProfileScreen.kt b/app/src/main/java/com/rosetta/messenger/ui/settings/OtherProfileScreen.kt index 7d01dfa..aa05b24 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/settings/OtherProfileScreen.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/settings/OtherProfileScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.outlined.Block import androidx.compose.material3.* import androidx.compose.runtime.* @@ -49,6 +50,7 @@ fun OtherProfileScreen( onBack: () -> Unit ) { var isBlocked by remember { mutableStateOf(false) } + var showAvatarMenu by remember { mutableStateOf(false) } val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFFFFFFF) val surfaceColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color(0xFFF2F2F7) val textColor = if (isDarkTheme) Color.White else Color.Black @@ -165,7 +167,9 @@ fun OtherProfileScreen( avatarColors = avatarColors, collapseProgress = collapseProgress, onBack = onBack, - isDarkTheme = isDarkTheme + isDarkTheme = isDarkTheme, + showAvatarMenu = showAvatarMenu, + onAvatarMenuChange = { showAvatarMenu = it } ) } } @@ -180,7 +184,9 @@ private fun CollapsingOtherProfileHeader( avatarColors: AvatarColors, collapseProgress: Float, onBack: () -> Unit, - isDarkTheme: Boolean + isDarkTheme: Boolean, + showAvatarMenu: Boolean, + onAvatarMenuChange: (Boolean) -> Unit ) { val density = LocalDensity.current val configuration = LocalConfiguration.current @@ -201,10 +207,8 @@ private fun CollapsingOtherProfileHeader( 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) + // Text animation - always centered + val textX = screenWidthDp / 2 // Always center val textExpandedY = statusBarHeight + 32.dp + AVATAR_SIZE_EXPANDED_OTHER + 48.dp val textCollapsedY = statusBarHeight + (COLLAPSED_HEADER_HEIGHT_OTHER - 40.dp) / 2 @@ -254,47 +258,40 @@ private fun CollapsingOtherProfileHeader( } } - // Name and username - Box( + // Name and username - always centered + Column( modifier = Modifier - .offset { - IntOffset( - with(density) { textX.toPx().roundToInt() }, - with(density) { textY.toPx().roundToInt() } - ) - } + .align(Alignment.TopCenter) + .offset(y = textY) .graphicsLayer { - transformOrigin = androidx.compose.ui.graphics.TransformOrigin( - pivotFractionX = if (collapseProgress > 0.5f) 0f else 0.5f, - pivotFractionY = 0.5f - ) - } + val centerOffsetY = with(density) { + androidx.compose.ui.unit.lerp(24.dp, 18.dp, collapseProgress).toPx() + } + translationY = -centerOffsetY + }, + horizontalAlignment = Alignment.CenterHorizontally ) { - 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 = name, - fontSize = nameFontSize, - fontWeight = FontWeight.Bold, - color = if (isDarkTheme) Color.White else Color.Black, + text = "@$username", + fontSize = usernameFontSize, + color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666), maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + modifier = Modifier.graphicsLayer { + alpha = 1f - (collapseProgress * 2f).coerceIn(0f, 1f) + } ) - - 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) - } - ) - } } } @@ -311,6 +308,39 @@ private fun CollapsingOtherProfileHeader( tint = if (isDarkTheme) Color.White else Color.Black ) } + + // Menu button (top right corner) + Box( + modifier = Modifier + .align(Alignment.TopEnd) + .padding(top = statusBarHeight) + .padding(end = 4.dp, top = 4.dp) + .size(48.dp), + contentAlignment = Alignment.Center + ) { + IconButton( + onClick = { onAvatarMenuChange(true) }, + modifier = Modifier.size(48.dp) + ) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = "Profile menu", + tint = if (isDarkTheme) Color.White else Color.Black, + modifier = Modifier.size(24.dp) + ) + } + + // Меню для установки фото профиля + com.rosetta.messenger.ui.chats.components.ProfilePhotoMenu( + expanded = showAvatarMenu, + onDismiss = { onAvatarMenuChange(false) }, + isDarkTheme = isDarkTheme, + onSetPhotoClick = { + onAvatarMenuChange(false) + // TODO: Реализовать выбор фото профиля + } + ) + } } }