111/app/src/main/java/com/example/smarthome/ui/SettingsScreen.kt
2025-11-28 13:21:09 +08:00

602 lines
20 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.example.smarthome.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
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.draw.shadow
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import com.example.smarthome.data.BackgroundManager
import com.example.smarthome.data.LanguageManager
import com.example.smarthome.data.tr
@Composable
fun SettingsScreen(onBack: () -> Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF121212))
.padding(16.dp)
) {
// 顶部栏
SettingsTopBar(onBack = onBack)
Spacer(modifier = Modifier.height(24.dp))
// 设置内容
SettingsContentList()
}
}
@Composable
fun SettingsContentList() {
val context = LocalContext.current
val currentLang by LanguageManager.currentLanguage.collectAsState()
var showLanguageDialog by remember { mutableStateOf(false) }
// 语言选择对话框
if (showLanguageDialog) {
LanguageSelectDialog(
currentLanguage = currentLang,
onLanguageSelect = { lang ->
LanguageManager.setLanguage(context, lang)
showLanguageDialog = false
},
onDismiss = { showLanguageDialog = false }
)
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
item { SettingsSection(title = tr("settings_account")) {
SettingsItem(
title = tr("settings_profile"),
subtitle = tr("settings_profile_desc"),
onClick = { }
)
SettingsItem(
title = tr("settings_security"),
subtitle = tr("settings_security_desc"),
onClick = { }
)
}}
item { SettingsSection(title = tr("settings_device")) {
var autoConnect by remember { mutableStateOf(true) }
SettingsSwitchItem(
title = tr("settings_auto_connect"),
subtitle = tr("settings_auto_connect_desc"),
checked = autoConnect,
onCheckedChange = { autoConnect = it }
)
var notifications by remember { mutableStateOf(true) }
SettingsSwitchItem(
title = tr("settings_notifications"),
subtitle = tr("settings_notifications_desc"),
checked = notifications,
onCheckedChange = { notifications = it }
)
}}
item { SettingsSection(title = tr("settings_display")) {
BackgroundSelector()
val selectedBg by BackgroundManager.selectedBackground.collectAsState()
// 深色模式根据当前背景是否为暗色来判断
val isDarkMode = BackgroundManager.backgrounds.getOrNull(selectedBg)?.isDark ?: false
SettingsSwitchItem(
title = tr("settings_dark_mode"),
subtitle = tr("settings_dark_mode_desc"),
checked = isDarkMode,
onCheckedChange = { dark ->
// 切换深色/浅色模式时自动更换背景
if (dark) {
BackgroundManager.setBackground(context, 2) // 紫金绸
} else {
BackgroundManager.setBackground(context, 0) // 丝绸白
}
}
)
SettingsItem(
title = tr("settings_language"),
subtitle = currentLang.nativeName,
onClick = { showLanguageDialog = true }
)
}}
item { SettingsSection(title = tr("settings_about")) {
SettingsItem(
title = tr("settings_version"),
subtitle = "v1.0.0",
onClick = { }
)
SettingsItem(
title = tr("settings_privacy"),
subtitle = tr("settings_privacy_desc"),
onClick = { }
)
SettingsItem(
title = tr("settings_terms"),
subtitle = tr("settings_terms_desc"),
onClick = { }
)
}}
item {
Spacer(modifier = Modifier.height(16.dp))
LogoutButton(onClick = {
com.example.smarthome.data.UserManager.logout(context)
})
}
}
}
@Composable
fun LanguageSelectDialog(
currentLanguage: LanguageManager.Language,
onLanguageSelect: (LanguageManager.Language) -> Unit,
onDismiss: () -> Unit
) {
Dialog(onDismissRequest = onDismiss) {
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(20.dp))
.background(Color(0xFF1E1E2E))
.padding(20.dp)
) {
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
Text(
text = tr("select_language"),
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = Color.White
)
Spacer(modifier = Modifier.height(8.dp))
LanguageManager.Language.entries.forEach { lang ->
val isSelected = lang == currentLanguage
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.background(
if (isSelected) Color(0xFF6C63FF).copy(alpha = 0.3f)
else Color(0xFF2A2A3E)
)
.border(
width = if (isSelected) 2.dp else 0.dp,
color = if (isSelected) Color(0xFF6C63FF) else Color.Transparent,
shape = RoundedCornerShape(12.dp)
)
.clickable { onLanguageSelect(lang) }
.padding(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
text = lang.nativeName,
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
if (lang.displayName != lang.nativeName) {
Text(
text = lang.displayName,
fontSize = 12.sp,
color = Color(0xFF9AA0A6)
)
}
}
if (isSelected) {
Text(text = "", color = Color(0xFF6C63FF), fontSize = 18.sp)
}
}
}
}
Spacer(modifier = Modifier.height(8.dp))
// 取消按钮
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.background(Color(0xFF3A3A4E))
.clickable { onDismiss() }
.padding(14.dp),
contentAlignment = Alignment.Center
) {
Text(
text = tr("cancel"),
color = Color.White,
fontSize = 14.sp
)
}
}
}
}
}
@Composable
fun SettingsTopBar(onBack: () -> Unit) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.size(40.dp)
.clip(RoundedCornerShape(12.dp))
.background(Color(0x50121212))
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) { onBack() },
contentAlignment = Alignment.Center
) {
Text(text = "", color = Color.White, fontSize = 20.sp)
}
Text(
text = tr("settings_title"),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
color = Color.White
)
}
}
}
@Composable
fun SettingsSection(title: String, content: @Composable ColumnScope.() -> Unit) {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
text = title,
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
color = Color(0xFF9AA0A6),
modifier = Modifier.padding(horizontal = 4.dp)
)
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(24.dp))
.background(Color(0x50121212))
.padding(8.dp)
) {
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
content()
}
}
}
}
@Composable
fun SettingsItem(
title: String,
subtitle: String,
onClick: () -> Unit
) {
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(Color(0x33121212))
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) { onClick() }
.padding(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = title,
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
Text(
text = subtitle,
fontSize = 13.sp,
color = Color(0xFF9AA0A6)
)
}
Text(
text = "",
fontSize = 24.sp,
color = Color(0xFF9AA0A6)
)
}
}
}
@Composable
fun SettingsSwitchItem(
title: String,
subtitle: String,
checked: Boolean,
onCheckedChange: (Boolean) -> Unit
) {
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(Color(0x33121212))
.padding(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = title,
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
Text(
text = subtitle,
fontSize = 13.sp,
color = Color(0xFF9AA0A6)
)
}
CustomSwitch(
checked = checked,
onCheckedChange = onCheckedChange
)
}
}
}
@Composable
fun CustomSwitch(
checked: Boolean,
onCheckedChange: (Boolean) -> Unit
) {
Box(
modifier = Modifier
.size(52.dp, 30.dp)
.clip(RoundedCornerShape(15.dp))
.background(
if (checked) {
Brush.linearGradient(
listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))
)
} else {
Brush.linearGradient(
listOf(Color(0x33222222), Color(0x33222222))
)
}
)
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) { onCheckedChange(!checked) }
.padding(3.dp)
) {
Box(
modifier = Modifier
.size(24.dp)
.clip(RoundedCornerShape(12.dp))
.background(Color.White)
.align(if (checked) Alignment.CenterEnd else Alignment.CenterStart)
)
}
}
@Composable
fun LogoutButton(onClick: () -> Unit) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.shadow(8.dp, RoundedCornerShape(24.dp))
.clip(RoundedCornerShape(24.dp))
.background(
Brush.linearGradient(
listOf(Color(0xFFFF6B6B), Color(0xFFFF5252))
)
)
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) { onClick() },
contentAlignment = Alignment.Center
) {
Text(
text = tr("settings_logout"),
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
color = Color.White
)
}
}
@Composable
fun SettingsContent() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
// 顶部标题
Text(
text = "设置",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
color = Color.White,
modifier = Modifier.padding(bottom = 24.dp)
)
// 设置内容
SettingsContentList()
}
}
@Composable
fun BackgroundSelector() {
val context = LocalContext.current
val selectedBackground by BackgroundManager.selectedBackground.collectAsState()
val interactionSources = remember {
BackgroundManager.backgrounds.map { MutableInteractionSource() }
}
Column(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(Color(0x33121212))
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
text = "背景壁纸",
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = Color.White
)
Text(
text = "选择您喜欢的背景图片",
fontSize = 13.sp,
color = Color(0xFF9AA0A6)
)
Spacer(modifier = Modifier.height(4.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
BackgroundManager.backgrounds.forEachIndexed { index, bg ->
val isSelected = selectedBackground == bg.id
Column(
modifier = Modifier.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.clip(RoundedCornerShape(10.dp))
.then(
if (isSelected) {
Modifier.border(
width = 2.dp,
brush = Brush.linearGradient(
listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))
),
shape = RoundedCornerShape(10.dp)
)
} else Modifier
)
.clickable(
indication = null,
interactionSource = interactionSources[index]
) {
BackgroundManager.setBackground(context, bg.id)
}
) {
Image(
painter = painterResource(id = bg.thumbId),
contentDescription = bg.name,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
if (isSelected) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 0.3f)),
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.size(20.dp)
.clip(RoundedCornerShape(10.dp))
.background(
Brush.linearGradient(
listOf(Color(0xFFA9F0FF), Color(0xFFB89CFF))
)
),
contentAlignment = Alignment.Center
) {
Text(
text = "",
color = Color.White,
fontSize = 12.sp,
fontWeight = FontWeight.Bold
)
}
}
}
}
Text(
text = bg.name,
fontSize = 11.sp,
fontWeight = if (isSelected) FontWeight.Medium else FontWeight.Normal,
color = if (isSelected) Color(0xFFA9F0FF) else Color(0xFF9AA0A6)
)
}
}
}
}
}