From cf291b58ab84169ad3f2899a5d4e35cf52d39be8 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Tue, 8 Sep 2026 23:13:00 +0800 Subject: [PATCH] =?UTF-8?q?style(ui):=20=E5=88=97=E8=A1=A8=E9=A1=B9?= =?UTF-8?q?=E5=8A=A0=E5=8D=A1=E7=89=87=E5=AE=B9=E5=99=A8=EF=BC=9B=E7=99=BB?= =?UTF-8?q?=E5=87=BA=E7=A7=BB=E5=88=B0=E8=AE=BE=E7=BD=AE=E9=A1=B5=E5=BA=95?= =?UTF-8?q?=E9=83=A8=EF=BC=9B=E6=8C=89=E9=92=AE=E6=94=B9=E7=9F=A2=E9=87=8F?= =?UTF-8?q?=E5=9B=BE=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 PreferenceCard(BasicComponent 本身无背景/圆角);抽屉去掉登出、新建与删除改图标按钮;设置页返回改 ChevronBackward、底部新增登出图标。 --- .../top/yeij/cyrene/ui/chat/ChatHomeScreen.kt | 7 +- .../yeij/cyrene/ui/common/PreferenceCard.kt | 33 +++++ .../ui/sessions/SessionDrawerContent.kt | 75 +++++----- .../yeij/cyrene/ui/settings/SettingsScreen.kt | 133 ++++++++++-------- 4 files changed, 154 insertions(+), 94 deletions(-) create mode 100644 app/src/main/kotlin/top/yeij/cyrene/ui/common/PreferenceCard.kt diff --git a/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatHomeScreen.kt b/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatHomeScreen.kt index baea813..8cfb2db 100644 --- a/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatHomeScreen.kt +++ b/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatHomeScreen.kt @@ -36,7 +36,11 @@ fun ChatHomeScreen( BackHandler(enabled = drawerOpen) { drawerOpen = false } if (showSettings) { - SettingsScreen(container = container, onBack = { showSettings = false }) + SettingsScreen( + container = container, + onBack = { showSettings = false }, + onLogout = onLogout, + ) } else { MiuixDrawer( open = drawerOpen, @@ -63,7 +67,6 @@ fun ChatHomeScreen( drawerOpen = false showSettings = true }, - onLogout = onLogout, ) }, ) diff --git a/app/src/main/kotlin/top/yeij/cyrene/ui/common/PreferenceCard.kt b/app/src/main/kotlin/top/yeij/cyrene/ui/common/PreferenceCard.kt new file mode 100644 index 0000000..5b18b3b --- /dev/null +++ b/app/src/main/kotlin/top/yeij/cyrene/ui/common/PreferenceCard.kt @@ -0,0 +1,33 @@ +package top.yeij.cyrene.ui.common + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import top.yukonga.miuix.kmp.theme.MiuixTheme + +/** + * Miuix 的 `BasicComponent` / Preference 系列本身**没有背景与圆角**(只是可点击的 Column), + * 需要外面包一层卡片容器才能得到 MD3 的「小圆角卡片」外观。 + * + * 页面底色用 `surface`、卡片用 `surfaceContainer`:浅色下 #F7F7F7 对 #FFFFFF, + * 深色下 #000000 对 #242424,卡片因此能凸显出来。 + */ +@Composable +fun PreferenceCard( + modifier: Modifier = Modifier, + content: @Composable () -> Unit, +) { + Box( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .background(MiuixTheme.colorScheme.surfaceContainer), + ) { + content() + } +} diff --git a/app/src/main/kotlin/top/yeij/cyrene/ui/sessions/SessionDrawerContent.kt b/app/src/main/kotlin/top/yeij/cyrene/ui/sessions/SessionDrawerContent.kt index f62c67e..4ea359e 100644 --- a/app/src/main/kotlin/top/yeij/cyrene/ui/sessions/SessionDrawerContent.kt +++ b/app/src/main/kotlin/top/yeij/cyrene/ui/sessions/SessionDrawerContent.kt @@ -23,12 +23,18 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog +import top.yeij.cyrene.ui.common.PreferenceCard import top.yukonga.miuix.kmp.basic.BasicComponent +import top.yukonga.miuix.kmp.basic.Icon +import top.yukonga.miuix.kmp.basic.IconButton import top.yukonga.miuix.kmp.basic.Text import top.yukonga.miuix.kmp.basic.TextButton +import top.yukonga.miuix.kmp.icon.MiuixIcons +import top.yukonga.miuix.kmp.icon.extended.Add +import top.yukonga.miuix.kmp.icon.extended.Delete import top.yukonga.miuix.kmp.theme.MiuixTheme -/** 侧边栏内容:会话列表 + IoT/设置占位 + 登出。列表项统一用 Miuix 的 MD3 圆角卡片。 */ +/** 侧边栏内容:会话列表 + IoT/设置入口。列表项为 MD3 小圆角卡片。 */ @Composable fun ColumnScope.SessionDrawerContent( state: SessionsUiState, @@ -37,7 +43,6 @@ fun ColumnScope.SessionDrawerContent( onDelete: (SessionItem) -> Unit, onOpenIot: () -> Unit, onOpenSettings: () -> Unit, - onLogout: () -> Unit, ) { var pendingDelete by remember { mutableStateOf(null) } @@ -53,11 +58,13 @@ fun ColumnScope.SessionDrawerContent( Row( modifier = Modifier .fillMaxWidth() - .padding(start = 20.dp, end = 12.dp, bottom = 4.dp), + .padding(start = 20.dp, end = 8.dp, bottom = 4.dp), verticalAlignment = Alignment.CenterVertically, ) { Text("会话", style = MiuixTheme.textStyles.subtitle, modifier = Modifier.weight(1f)) - TextButton("新建", onClick = onCreate) + IconButton(onClick = onCreate) { + Icon(imageVector = MiuixIcons.Add, contentDescription = "新建会话") + } } LazyColumn( @@ -91,11 +98,9 @@ fun ColumnScope.SessionDrawerContent( } Spacer(Modifier.height(12.dp)) - DrawerAction("IoT(规划中)", onOpenIot) + PreferenceCard { BasicComponent(title = "IoT(规划中)", onClick = onOpenIot) } Spacer(Modifier.height(8.dp)) - DrawerAction("App 设置", onOpenSettings) - Spacer(Modifier.height(8.dp)) - DrawerAction("登出", onLogout) + PreferenceCard { BasicComponent(title = "App 设置", onClick = onOpenSettings) } Spacer(Modifier.height(16.dp)) pendingDelete?.let { target -> @@ -119,35 +124,31 @@ private fun SessionRow( onClick: () -> Unit, onDelete: () -> Unit, ) { - BasicComponent( - title = session.title, - onClick = onClick, - endActions = { - if (active) { - Text( - text = "✓", - style = MiuixTheme.textStyles.main, - color = MiuixTheme.colorScheme.primary, - modifier = Modifier.padding(horizontal = 6.dp), - ) - } - if (!session.isMain) { - Text( - text = "删除", - style = MiuixTheme.textStyles.footnote1, - color = MiuixTheme.colorScheme.error, - modifier = Modifier - .clickable(onClick = onDelete) - .padding(horizontal = 8.dp, vertical = 4.dp), - ) - } - }, - ) -} - -@Composable -private fun DrawerAction(label: String, onClick: () -> Unit) { - BasicComponent(title = label, onClick = onClick) + PreferenceCard { + BasicComponent( + title = session.title, + onClick = onClick, + endActions = { + if (active) { + Text( + text = "✓", + style = MiuixTheme.textStyles.main, + color = MiuixTheme.colorScheme.primary, + modifier = Modifier.padding(horizontal = 4.dp), + ) + } + if (!session.isMain) { + IconButton(onClick = onDelete) { + Icon( + imageVector = MiuixIcons.Delete, + contentDescription = "删除会话", + tint = MiuixTheme.colorScheme.error, + ) + } + } + }, + ) + } } @Composable diff --git a/app/src/main/kotlin/top/yeij/cyrene/ui/settings/SettingsScreen.kt b/app/src/main/kotlin/top/yeij/cyrene/ui/settings/SettingsScreen.kt index cd9249e..af064df 100644 --- a/app/src/main/kotlin/top/yeij/cyrene/ui/settings/SettingsScreen.kt +++ b/app/src/main/kotlin/top/yeij/cyrene/ui/settings/SettingsScreen.kt @@ -1,5 +1,6 @@ package top.yeij.cyrene.ui.settings +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -21,11 +22,16 @@ import top.yeij.cyrene.BuildConfig import top.yeij.cyrene.app.AppContainer import top.yeij.cyrene.core.prefs.AppPrefs import top.yeij.cyrene.core.prefs.ThemeMode +import top.yeij.cyrene.ui.common.PreferenceCard import top.yukonga.miuix.kmp.basic.BasicComponent +import top.yukonga.miuix.kmp.basic.Icon +import top.yukonga.miuix.kmp.basic.IconButton import top.yukonga.miuix.kmp.basic.Scaffold import top.yukonga.miuix.kmp.basic.SmallTopAppBar import top.yukonga.miuix.kmp.basic.Text -import top.yukonga.miuix.kmp.basic.TextButton +import top.yukonga.miuix.kmp.icon.MiuixIcons +import top.yukonga.miuix.kmp.icon.extended.Back +import top.yukonga.miuix.kmp.icon.extended.ChevronBackward import top.yukonga.miuix.kmp.preference.SwitchPreference import top.yukonga.miuix.kmp.theme.MiuixTheme @@ -33,6 +39,7 @@ import top.yukonga.miuix.kmp.theme.MiuixTheme fun SettingsScreen( container: AppContainer, onBack: () -> Unit, + onLogout: () -> Unit = {}, ) { val prefs by container.appSettings.data.collectAsState(initial = AppPrefs()) val scope = rememberCoroutineScope() @@ -42,7 +49,11 @@ fun SettingsScreen( topBar = { SmallTopAppBar( title = "App 设置", - navigationIcon = { TextButton("返回", onClick = onBack) }, + navigationIcon = { + IconButton(onClick = onBack) { + Icon(imageVector = MiuixIcons.ChevronBackward, contentDescription = "返回") + } + }, ) }, ) { padding -> @@ -54,44 +65,77 @@ fun SettingsScreen( ) { SectionTitle("外观") ThemeMode.entries.forEach { mode -> - ThemeOption( - label = mode.label(), - selected = prefs.themeMode == mode, - onClick = { scope.launch { settings.setThemeMode(mode) } }, - ) + PreferenceCard { + BasicComponent( + title = mode.label(), + onClick = { scope.launch { settings.setThemeMode(mode) } }, + endActions = { + if (prefs.themeMode == mode) { + Text( + text = "✓", + style = MiuixTheme.textStyles.main, + color = MiuixTheme.colorScheme.primary, + ) + } + }, + ) + } Spacer(Modifier.height(8.dp)) } SectionTitle("聊天") - SwitchPreference( - title = "显示旁白", - summary = "以灰斜体小字显示 / ", - checked = prefs.showNarration, - onCheckedChange = { scope.launch { settings.setShowNarration(it) } }, - ) - Spacer(Modifier.height(8.dp)) - SwitchPreference( - title = "思维链默认展开", - summary = "流式期间展开思维链,结束后自动折叠", - checked = prefs.thinkingExpanded, - onCheckedChange = { scope.launch { settings.setThinkingExpanded(it) } }, - ) - - SectionTitle("关于") - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp, vertical = 14.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - Text("版本", style = MiuixTheme.textStyles.main, modifier = Modifier.weight(1f)) - Text( - text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})", - style = MiuixTheme.textStyles.footnote1, - color = MiuixTheme.colorScheme.onSurfaceVariantSummary, + PreferenceCard { + SwitchPreference( + title = "显示旁白", + summary = "以灰斜体小字显示 / ", + checked = prefs.showNarration, + onCheckedChange = { scope.launch { settings.setShowNarration(it) } }, ) } - Spacer(Modifier.height(24.dp)) + Spacer(Modifier.height(8.dp)) + PreferenceCard { + SwitchPreference( + title = "思维链默认展开", + summary = "流式期间展开思维链,结束后自动折叠", + checked = prefs.thinkingExpanded, + onCheckedChange = { scope.launch { settings.setThinkingExpanded(it) } }, + ) + } + + SectionTitle("关于") + PreferenceCard { + BasicComponent( + title = "版本", + summary = null, + endActions = { + Text( + text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})", + style = MiuixTheme.textStyles.footnote1, + color = MiuixTheme.colorScheme.onSurfaceVariantSummary, + ) + }, + ) + } + + Spacer(Modifier.height(32.dp)) + PreferenceCard { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + IconButton(onClick = onLogout) { + Icon( + imageVector = MiuixIcons.Back, + contentDescription = "登出", + tint = MiuixTheme.colorScheme.error, + ) + } + } + } + Spacer(Modifier.height(32.dp)) } } } @@ -106,27 +150,6 @@ private fun SectionTitle(text: String) { ) } -@Composable -private fun ThemeOption( - label: String, - selected: Boolean, - onClick: () -> Unit, -) { - BasicComponent( - title = label, - onClick = onClick, - endActions = { - if (selected) { - Text( - text = "✓", - style = MiuixTheme.textStyles.main, - color = MiuixTheme.colorScheme.primary, - ) - } - }, - ) -} - private fun ThemeMode.label(): String = when (this) { ThemeMode.System -> "跟随系统" ThemeMode.Light -> "浅色"