diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/components/ChatDetailComponents.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/components/ChatDetailComponents.kt index d6fbc6c..178a3c1 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/components/ChatDetailComponents.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/components/ChatDetailComponents.kt @@ -770,6 +770,35 @@ fun ProfilePhotoMenu( } } +/** Other user profile menu with block option */ +@Composable +fun OtherProfileMenu( + expanded: Boolean, + onDismiss: () -> Unit, + isDarkTheme: Boolean, + isBlocked: Boolean, + onBlockClick: () -> Unit +) { + DropdownMenu( + expanded = expanded, + onDismissRequest = onDismiss, + modifier = Modifier.width(220.dp), + properties = PopupProperties( + focusable = true, + dismissOnBackPress = true, + dismissOnClickOutside = true + ) + ) { + ProfilePhotoMenuItem( + icon = if (isBlocked) Icons.Default.CheckCircle else Icons.Default.Block, + text = if (isBlocked) "Unblock User" else "Block User", + onClick = onBlockClick, + tintColor = if (isBlocked) Color(0xFF4CAF50) else Color(0xFFFF3B30), + textColor = if (isBlocked) Color(0xFF4CAF50) else Color(0xFFFF3B30) + ) + } +} + @Composable private fun ProfilePhotoMenuItem( icon: ImageVector, 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 aa05b24..7f7bff4 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 @@ -29,6 +29,7 @@ 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.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp @@ -140,19 +141,6 @@ fun OtherProfileScreen( isDarkTheme = isDarkTheme ) - Spacer(modifier = Modifier.height(24.dp)) - - // ═══════════════════════════════════════════════════════════ - // 🚫 BLOCK SECTION - // ═══════════════════════════════════════════════════════════ - TelegramSectionTitle(title = "Privacy", isDarkTheme = isDarkTheme) - - TelegramBlockItem( - isBlocked = isBlocked, - onToggle = { isBlocked = !isBlocked }, - isDarkTheme = isDarkTheme - ) - Spacer(modifier = Modifier.height(32.dp)) } } @@ -169,7 +157,9 @@ fun OtherProfileScreen( onBack = onBack, isDarkTheme = isDarkTheme, showAvatarMenu = showAvatarMenu, - onAvatarMenuChange = { showAvatarMenu = it } + onAvatarMenuChange = { showAvatarMenu = it }, + isBlocked = isBlocked, + onBlockToggle = { isBlocked = !isBlocked } ) } } @@ -186,7 +176,9 @@ private fun CollapsingOtherProfileHeader( onBack: () -> Unit, isDarkTheme: Boolean, showAvatarMenu: Boolean, - onAvatarMenuChange: (Boolean) -> Unit + onAvatarMenuChange: (Boolean) -> Unit, + isBlocked: Boolean, + onBlockToggle: () -> Unit ) { val density = LocalDensity.current val configuration = LocalConfiguration.current @@ -208,108 +200,47 @@ private fun CollapsingOtherProfileHeader( val avatarFontSize = androidx.compose.ui.unit.lerp(40.sp, 0.sp, 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 + val textCollapsedY = statusBarHeight + COLLAPSED_HEADER_HEIGHT_OTHER / 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 + val nameFontSize = androidx.compose.ui.unit.lerp(24.sp, 18.sp, collapseProgress) + val onlineFontSize = androidx.compose.ui.unit.lerp(14.sp, 13.sp, collapseProgress) Box( modifier = Modifier .fillMaxWidth() .height(headerHeight) - .background(headerColor) + .drawBehind { + drawRect(avatarColors.backgroundColor) + } ) { - // Background color + // ═══════════════════════════════════════════════════════════ + // 🔙 BACK BUTTON + // ═══════════════════════════════════════════════════════════ 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 - always centered - Column( - modifier = Modifier - .align(Alignment.TopCenter) - .offset(y = textY) - .graphicsLayer { - val centerOffsetY = with(density) { - androidx.compose.ui.unit.lerp(24.dp, 18.dp, collapseProgress).toPx() - } - translationY = -centerOffsetY - }, - horizontalAlignment = Alignment.CenterHorizontally + .padding(top = statusBarHeight) + .padding(start = 4.dp, top = 4.dp) + .size(48.dp), + contentAlignment = Alignment.Center ) { - 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) - } + IconButton( + onClick = onBack, + modifier = Modifier.size(48.dp) + ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Back", + tint = Color.White, + modifier = Modifier.size(24.dp) ) } } - // 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 - ) - } - - // Menu button (top right corner) + // ═══════════════════════════════════════════════════════════ + // ⋮ MENU BUTTON (top right corner) + // ═══════════════════════════════════════════════════════════ Box( modifier = Modifier .align(Alignment.TopEnd) @@ -325,22 +256,88 @@ private fun CollapsingOtherProfileHeader( Icon( imageVector = Icons.Default.MoreVert, contentDescription = "Profile menu", - tint = if (isDarkTheme) Color.White else Color.Black, + tint = Color.White, modifier = Modifier.size(24.dp) ) } - // Меню для установки фото профиля - com.rosetta.messenger.ui.chats.components.ProfilePhotoMenu( + // Меню с блокировкой пользователя + com.rosetta.messenger.ui.chats.components.OtherProfileMenu( expanded = showAvatarMenu, onDismiss = { onAvatarMenuChange(false) }, isDarkTheme = isDarkTheme, - onSetPhotoClick = { + isBlocked = isBlocked, + onBlockClick = { onAvatarMenuChange(false) - // TODO: Реализовать выбор фото профиля + onBlockToggle() } ) } + + // ═══════════════════════════════════════════════════════════ + // 👤 AVATAR - shrinks and moves up + // ═══════════════════════════════════════════════════════════ + if (avatarSize > 1.dp) { + Box( + modifier = Modifier + .offset( + x = avatarCenterX + (AVATAR_SIZE_EXPANDED_OTHER - avatarSize) / 2, + y = avatarY + ) + .size(avatarSize) + .clip(CircleShape) + .background(Color.White.copy(alpha = 0.15f)) + .padding(2.dp) + .clip(CircleShape) + .background(avatarColors.backgroundColor), + contentAlignment = Alignment.Center + ) { + if (avatarFontSize > 1.sp) { + Text( + text = getInitials(name), + fontSize = avatarFontSize, + fontWeight = FontWeight.Bold, + color = avatarColors.textColor + ) + } + } + } + + // ═══════════════════════════════════════════════════════════ + // 📝 TEXT BLOCK - Name + Online, always centered + // ═══════════════════════════════════════════════════════════ + Column( + modifier = Modifier + .align(Alignment.TopCenter) + .offset(y = textY) + .graphicsLayer { + val centerOffsetY = with(density) { + androidx.compose.ui.unit.lerp(24.dp, 18.dp, collapseProgress).toPx() + } + translationY = -centerOffsetY + }, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = name, + fontSize = nameFontSize, + fontWeight = FontWeight.SemiBold, + color = Color.White, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.widthIn(max = 220.dp), + textAlign = TextAlign.Center + ) + + Spacer(modifier = Modifier.height(2.dp)) + + // Online text - always centered + Text( + text = "online", + fontSize = onlineFontSize, + color = Color(0xFF4CAF50) + ) + } } }