feat: Add avatar menu functionality and improve header layout in OtherProfileScreen
This commit is contained in:
@@ -11,6 +11,7 @@ import androidx.compose.foundation.shape.CircleShape
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
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.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.*
|
||||||
@@ -49,6 +50,7 @@ fun OtherProfileScreen(
|
|||||||
onBack: () -> Unit
|
onBack: () -> Unit
|
||||||
) {
|
) {
|
||||||
var isBlocked by remember { mutableStateOf(false) }
|
var isBlocked by remember { mutableStateOf(false) }
|
||||||
|
var showAvatarMenu by remember { mutableStateOf(false) }
|
||||||
val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFFFFFFF)
|
val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFFFFFFF)
|
||||||
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
|
||||||
@@ -165,7 +167,9 @@ fun OtherProfileScreen(
|
|||||||
avatarColors = avatarColors,
|
avatarColors = avatarColors,
|
||||||
collapseProgress = collapseProgress,
|
collapseProgress = collapseProgress,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
isDarkTheme = isDarkTheme
|
isDarkTheme = isDarkTheme,
|
||||||
|
showAvatarMenu = showAvatarMenu,
|
||||||
|
onAvatarMenuChange = { showAvatarMenu = it }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,7 +184,9 @@ private fun CollapsingOtherProfileHeader(
|
|||||||
avatarColors: AvatarColors,
|
avatarColors: AvatarColors,
|
||||||
collapseProgress: Float,
|
collapseProgress: Float,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
isDarkTheme: Boolean
|
isDarkTheme: Boolean,
|
||||||
|
showAvatarMenu: Boolean,
|
||||||
|
onAvatarMenuChange: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val configuration = LocalConfiguration.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 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
|
// Text animation - always centered
|
||||||
val textExpandedX = screenWidthDp / 2
|
val textX = screenWidthDp / 2 // Always center
|
||||||
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 textExpandedY = statusBarHeight + 32.dp + AVATAR_SIZE_EXPANDED_OTHER + 48.dp
|
||||||
val textCollapsedY = statusBarHeight + (COLLAPSED_HEADER_HEIGHT_OTHER - 40.dp) / 2
|
val textCollapsedY = statusBarHeight + (COLLAPSED_HEADER_HEIGHT_OTHER - 40.dp) / 2
|
||||||
@@ -254,47 +258,40 @@ private fun CollapsingOtherProfileHeader(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name and username
|
// Name and username - always centered
|
||||||
Box(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.offset {
|
.align(Alignment.TopCenter)
|
||||||
IntOffset(
|
.offset(y = textY)
|
||||||
with(density) { textX.toPx().roundToInt() },
|
|
||||||
with(density) { textY.toPx().roundToInt() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.graphicsLayer {
|
.graphicsLayer {
|
||||||
transformOrigin = androidx.compose.ui.graphics.TransformOrigin(
|
val centerOffsetY = with(density) {
|
||||||
pivotFractionX = if (collapseProgress > 0.5f) 0f else 0.5f,
|
androidx.compose.ui.unit.lerp(24.dp, 18.dp, collapseProgress).toPx()
|
||||||
pivotFractionY = 0.5f
|
}
|
||||||
)
|
translationY = -centerOffsetY
|
||||||
}
|
},
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Column(
|
Text(
|
||||||
horizontalAlignment = if (collapseProgress > 0.5f) Alignment.Start else Alignment.CenterHorizontally
|
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(
|
||||||
text = name,
|
text = "@$username",
|
||||||
fontSize = nameFontSize,
|
fontSize = usernameFontSize,
|
||||||
fontWeight = FontWeight.Bold,
|
color = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666),
|
||||||
color = if (isDarkTheme) Color.White else Color.Black,
|
|
||||||
maxLines = 1,
|
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
|
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: Реализовать выбор фото профиля
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user