refactor: Clean up OnboardingScreen code for improved readability and maintainability
This commit is contained in:
@@ -0,0 +1,505 @@
|
||||
package com.rosetta.messenger.ui.settings
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material.icons.outlined.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsScreen(
|
||||
isDarkTheme: Boolean,
|
||||
accountName: String,
|
||||
accountPhone: String,
|
||||
accountPublicKey: String,
|
||||
onBack: () -> Unit,
|
||||
onToggleTheme: () -> Unit,
|
||||
onProfileClick: () -> Unit = {},
|
||||
onPrivacySecurityClick: () -> Unit = {},
|
||||
onNotificationsClick: () -> Unit = {},
|
||||
onDataStorageClick: () -> Unit = {},
|
||||
onChatSettingsClick: () -> Unit = {},
|
||||
onLanguageClick: () -> Unit = {},
|
||||
onHelpClick: () -> Unit = {},
|
||||
onAboutClick: () -> Unit = {}
|
||||
) {
|
||||
// Цвета в зависимости от темы
|
||||
val backgroundColor = if (isDarkTheme) Color(0xFF0F0F0F) else Color.White
|
||||
val surfaceColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFF5F5F5)
|
||||
val textColor = if (isDarkTheme) Color.White else Color(0xFF1A1A1A)
|
||||
val secondaryTextColor = if (isDarkTheme) Color(0xFF999999) else Color(0xFF666666)
|
||||
val dividerColor = if (isDarkTheme) Color(0xFF2A2A2A) else Color(0xFFE8E8E8)
|
||||
val iconTintColor = if (isDarkTheme) Color(0xFF999999) else Color(0xFF666666)
|
||||
|
||||
Column(modifier = Modifier.fillMaxSize().background(backgroundColor)) {
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 🎨 TOP BAR
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = "Settings",
|
||||
color = textColor,
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.ArrowBack,
|
||||
contentDescription = "Back",
|
||||
tint = textColor
|
||||
)
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors(containerColor = backgroundColor)
|
||||
)
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 📱 CONTENT
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 👤 PROFILE SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
Surface(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.clickable(onClick = onProfileClick),
|
||||
color = surfaceColor
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Avatar
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.size(64.dp).clip(CircleShape).background(PrimaryBlue),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = getInitials(accountName),
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = Color.White
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
|
||||
// Name and Phone
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = accountName,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = textColor
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(text = accountPhone, fontSize = 14.sp, color = secondaryTextColor)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(
|
||||
text = accountPublicKey.take(12) + "...",
|
||||
fontSize = 12.sp,
|
||||
color = secondaryTextColor.copy(alpha = 0.7f)
|
||||
)
|
||||
}
|
||||
|
||||
// Arrow
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = null,
|
||||
tint = iconTintColor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 🎨 APPEARANCE SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "Appearance", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsToggleItem(
|
||||
icon =
|
||||
if (isDarkTheme) Icons.Outlined.DarkMode
|
||||
else Icons.Outlined.LightMode,
|
||||
title = "Dark Mode",
|
||||
subtitle = if (isDarkTheme) "Enabled" else "Disabled",
|
||||
isChecked = isDarkTheme,
|
||||
onToggle = onToggleTheme,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 🔐 PRIVACY & SECURITY SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "Privacy & Security", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Lock,
|
||||
title = "Privacy Settings",
|
||||
subtitle = "Control who can see your info",
|
||||
onClick = onPrivacySecurityClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Security,
|
||||
title = "Security",
|
||||
subtitle = "Passcode, 2FA, sessions",
|
||||
onClick = onPrivacySecurityClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Block,
|
||||
title = "Blocked Users",
|
||||
subtitle = "Manage blocked contacts",
|
||||
onClick = onPrivacySecurityClick,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 🔔 NOTIFICATIONS SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "Notifications & Sounds", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Notifications,
|
||||
title = "Notifications",
|
||||
subtitle = "Messages, groups, channels",
|
||||
onClick = onNotificationsClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.VolumeUp,
|
||||
title = "Sounds",
|
||||
subtitle = "Notification sounds",
|
||||
onClick = onNotificationsClick,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 💾 DATA & STORAGE SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "Data & Storage", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Storage,
|
||||
title = "Storage Usage",
|
||||
subtitle = "Clear cache, manage data",
|
||||
onClick = onDataStorageClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.DataUsage,
|
||||
title = "Network Usage",
|
||||
subtitle = "Mobile and Wi-Fi",
|
||||
onClick = onDataStorageClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.DownloadForOffline,
|
||||
title = "Auto-Download",
|
||||
subtitle = "Photos, videos, files",
|
||||
onClick = onDataStorageClick,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 💬 CHAT SETTINGS SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "Chat Settings", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.ChatBubbleOutline,
|
||||
title = "Chat Background",
|
||||
subtitle = "Set wallpaper for chats",
|
||||
onClick = onChatSettingsClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.TextFields,
|
||||
title = "Message Text Size",
|
||||
subtitle = "Adjust text size in chats",
|
||||
onClick = onChatSettingsClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.EmojiEmotions,
|
||||
title = "Stickers & Emojis",
|
||||
subtitle = "Manage sticker packs",
|
||||
onClick = onChatSettingsClick,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 🌐 GENERAL SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "General", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Language,
|
||||
title = "Language",
|
||||
subtitle = "English",
|
||||
onClick = onLanguageClick,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// ℹ️ SUPPORT SECTION
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
SettingsSectionTitle(title = "Support", isDarkTheme = isDarkTheme)
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp),
|
||||
color = surfaceColor,
|
||||
shape = RoundedCornerShape(16.dp)
|
||||
) {
|
||||
Column {
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.HelpOutline,
|
||||
title = "Help Center",
|
||||
subtitle = "FAQ and support",
|
||||
onClick = onHelpClick,
|
||||
isDarkTheme = isDarkTheme,
|
||||
showDivider = true
|
||||
)
|
||||
SettingsNavigationItem(
|
||||
icon = Icons.Outlined.Info,
|
||||
title = "About",
|
||||
subtitle = "Version 1.0.0",
|
||||
onClick = onAboutClick,
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
// 📦 HELPER COMPONENTS
|
||||
// ═════════════════════════════════════════════════════════════
|
||||
|
||||
@Composable
|
||||
private fun SettingsSectionTitle(title: String, isDarkTheme: Boolean) {
|
||||
val textColor = if (isDarkTheme) Color(0xFF666666) else Color(0xFF999999)
|
||||
|
||||
Text(
|
||||
text = title.uppercase(),
|
||||
fontSize = 13.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = textColor,
|
||||
modifier = Modifier.padding(horizontal = 32.dp, vertical = 8.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SettingsNavigationItem(
|
||||
icon: ImageVector,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
onClick: () -> Unit,
|
||||
isDarkTheme: Boolean,
|
||||
showDivider: Boolean = false
|
||||
) {
|
||||
val textColor = if (isDarkTheme) Color.White else Color(0xFF1A1A1A)
|
||||
val secondaryTextColor = if (isDarkTheme) Color(0xFF999999) else Color(0xFF666666)
|
||||
val iconTintColor = if (isDarkTheme) Color(0xFF999999) else Color(0xFF666666)
|
||||
val dividerColor = if (isDarkTheme) Color(0xFF2A2A2A) else Color(0xFFE8E8E8)
|
||||
|
||||
Column {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Icon
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = iconTintColor,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
|
||||
// Title and Subtitle
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(text = title, fontSize = 16.sp, color = textColor)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(text = subtitle, fontSize = 13.sp, color = secondaryTextColor)
|
||||
}
|
||||
|
||||
// Arrow
|
||||
Icon(
|
||||
imageVector = Icons.Default.ChevronRight,
|
||||
contentDescription = null,
|
||||
tint = iconTintColor.copy(alpha = 0.5f),
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
|
||||
if (showDivider) {
|
||||
Divider(
|
||||
color = dividerColor,
|
||||
thickness = 0.5.dp,
|
||||
modifier = Modifier.padding(start = 56.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SettingsToggleItem(
|
||||
icon: ImageVector,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
isChecked: Boolean,
|
||||
onToggle: () -> Unit,
|
||||
isDarkTheme: Boolean
|
||||
) {
|
||||
val textColor = if (isDarkTheme) Color.White else Color(0xFF1A1A1A)
|
||||
val secondaryTextColor = if (isDarkTheme) Color(0xFF999999) else Color(0xFF666666)
|
||||
val iconTintColor = if (isDarkTheme) Color(0xFF999999) else Color(0xFF666666)
|
||||
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.clickable(onClick = onToggle)
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
// Icon
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = iconTintColor,
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
|
||||
// Title and Subtitle
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(text = title, fontSize = 16.sp, color = textColor)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(text = subtitle, fontSize = 13.sp, color = secondaryTextColor)
|
||||
}
|
||||
|
||||
// Toggle Switch
|
||||
Switch(
|
||||
checked = isChecked,
|
||||
onCheckedChange = { onToggle() },
|
||||
colors =
|
||||
SwitchDefaults.colors(
|
||||
checkedThumbColor = Color.White,
|
||||
checkedTrackColor = PrimaryBlue,
|
||||
uncheckedThumbColor = Color.White,
|
||||
uncheckedTrackColor =
|
||||
if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFCCCCCC)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getInitials(name: String): String {
|
||||
if (name.isBlank()) return "?"
|
||||
val parts = name.trim().split(" ").filter { it.isNotEmpty() }
|
||||
return when {
|
||||
parts.isEmpty() -> "?"
|
||||
parts.size == 1 -> parts[0].take(2).uppercase()
|
||||
else -> (parts[0].first().toString() + parts[1].first().toString()).uppercase()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user