style(ui): 列表项加卡片容器;登出移到设置页底部;按钮改矢量图标
新增 PreferenceCard(BasicComponent 本身无背景/圆角);抽屉去掉登出、新建与删除改图标按钮;设置页返回改 ChevronBackward、底部新增登出图标。
This commit is contained in:
1 parent
df2a26701c
commit
cf291b58ab
4 files changed
+116
-56
No files matched your search
@@ -36,7 +36,11 @@ fun ChatHomeScreen(
|
|||||||
BackHandler(enabled = drawerOpen) { drawerOpen = false }
|
BackHandler(enabled = drawerOpen) { drawerOpen = false }
|
||||||
|
|
||||||
if (showSettings) {
|
if (showSettings) {
|
||||||
SettingsScreen(container = container, onBack = { showSettings = false })
|
SettingsScreen(
|
||||||
|
container = container,
|
||||||
|
onBack = { showSettings = false },
|
||||||
|
onLogout = onLogout,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
MiuixDrawer(
|
MiuixDrawer(
|
||||||
open = drawerOpen,
|
open = drawerOpen,
|
||||||
@@ -63,7 +67,6 @@ fun ChatHomeScreen(
|
|||||||
drawerOpen = false
|
drawerOpen = false
|
||||||
showSettings = true
|
showSettings = true
|
||||||
},
|
},
|
||||||
onLogout = onLogout,
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,12 +23,18 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
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.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.Text
|
||||||
import top.yukonga.miuix.kmp.basic.TextButton
|
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
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
|
|
||||||
/** 侧边栏内容:会话列表 + IoT/设置占位 + 登出。列表项统一用 Miuix 的 MD3 圆角卡片。 */
|
/** 侧边栏内容:会话列表 + IoT/设置入口。列表项为 MD3 小圆角卡片。 */
|
||||||
@Composable
|
@Composable
|
||||||
fun ColumnScope.SessionDrawerContent(
|
fun ColumnScope.SessionDrawerContent(
|
||||||
state: SessionsUiState,
|
state: SessionsUiState,
|
||||||
@@ -37,7 +43,6 @@ fun ColumnScope.SessionDrawerContent(
|
|||||||
onDelete: (SessionItem) -> Unit,
|
onDelete: (SessionItem) -> Unit,
|
||||||
onOpenIot: () -> Unit,
|
onOpenIot: () -> Unit,
|
||||||
onOpenSettings: () -> Unit,
|
onOpenSettings: () -> Unit,
|
||||||
onLogout: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
var pendingDelete by remember { mutableStateOf<SessionItem?>(null) }
|
var pendingDelete by remember { mutableStateOf<SessionItem?>(null) }
|
||||||
|
|
||||||
@@ -53,11 +58,13 @@ fun ColumnScope.SessionDrawerContent(
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(start = 20.dp, end = 12.dp, bottom = 4.dp),
|
.padding(start = 20.dp, end = 8.dp, bottom = 4.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text("会话", style = MiuixTheme.textStyles.subtitle, modifier = Modifier.weight(1f))
|
Text("会话", style = MiuixTheme.textStyles.subtitle, modifier = Modifier.weight(1f))
|
||||||
TextButton("新建", onClick = onCreate)
|
IconButton(onClick = onCreate) {
|
||||||
|
Icon(imageVector = MiuixIcons.Add, contentDescription = "新建会话")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
@@ -91,11 +98,9 @@ fun ColumnScope.SessionDrawerContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(12.dp))
|
Spacer(Modifier.height(12.dp))
|
||||||
DrawerAction("IoT(规划中)", onOpenIot)
|
PreferenceCard { BasicComponent(title = "IoT(规划中)", onClick = onOpenIot) }
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
DrawerAction("App 设置", onOpenSettings)
|
PreferenceCard { BasicComponent(title = "App 设置", onClick = onOpenSettings) }
|
||||||
Spacer(Modifier.height(8.dp))
|
|
||||||
DrawerAction("登出", onLogout)
|
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
|
|
||||||
pendingDelete?.let { target ->
|
pendingDelete?.let { target ->
|
||||||
@@ -119,6 +124,7 @@ private fun SessionRow(
|
|||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onDelete: () -> Unit,
|
onDelete: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
PreferenceCard {
|
||||||
BasicComponent(
|
BasicComponent(
|
||||||
title = session.title,
|
title = session.title,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
@@ -128,26 +134,21 @@ private fun SessionRow(
|
|||||||
text = "✓",
|
text = "✓",
|
||||||
style = MiuixTheme.textStyles.main,
|
style = MiuixTheme.textStyles.main,
|
||||||
color = MiuixTheme.colorScheme.primary,
|
color = MiuixTheme.colorScheme.primary,
|
||||||
modifier = Modifier.padding(horizontal = 6.dp),
|
modifier = Modifier.padding(horizontal = 4.dp),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!session.isMain) {
|
if (!session.isMain) {
|
||||||
Text(
|
IconButton(onClick = onDelete) {
|
||||||
text = "删除",
|
Icon(
|
||||||
style = MiuixTheme.textStyles.footnote1,
|
imageVector = MiuixIcons.Delete,
|
||||||
color = MiuixTheme.colorScheme.error,
|
contentDescription = "删除会话",
|
||||||
modifier = Modifier
|
tint = MiuixTheme.colorScheme.error,
|
||||||
.clickable(onClick = onDelete)
|
|
||||||
.padding(horizontal = 8.dp, vertical = 4.dp),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun DrawerAction(label: String, onClick: () -> Unit) {
|
|
||||||
BasicComponent(title = label, onClick = onClick)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package top.yeij.cyrene.ui.settings
|
package top.yeij.cyrene.ui.settings
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
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.app.AppContainer
|
||||||
import top.yeij.cyrene.core.prefs.AppPrefs
|
import top.yeij.cyrene.core.prefs.AppPrefs
|
||||||
import top.yeij.cyrene.core.prefs.ThemeMode
|
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.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.Scaffold
|
||||||
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
|
import top.yukonga.miuix.kmp.basic.SmallTopAppBar
|
||||||
import top.yukonga.miuix.kmp.basic.Text
|
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.preference.SwitchPreference
|
||||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||||
|
|
||||||
@@ -33,6 +39,7 @@ import top.yukonga.miuix.kmp.theme.MiuixTheme
|
|||||||
fun SettingsScreen(
|
fun SettingsScreen(
|
||||||
container: AppContainer,
|
container: AppContainer,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
|
onLogout: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val prefs by container.appSettings.data.collectAsState(initial = AppPrefs())
|
val prefs by container.appSettings.data.collectAsState(initial = AppPrefs())
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -42,7 +49,11 @@ fun SettingsScreen(
|
|||||||
topBar = {
|
topBar = {
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
title = "App 设置",
|
title = "App 设置",
|
||||||
navigationIcon = { TextButton("返回", onClick = onBack) },
|
navigationIcon = {
|
||||||
|
IconButton(onClick = onBack) {
|
||||||
|
Icon(imageVector = MiuixIcons.ChevronBackward, contentDescription = "返回")
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { padding ->
|
) { padding ->
|
||||||
@@ -54,44 +65,77 @@ fun SettingsScreen(
|
|||||||
) {
|
) {
|
||||||
SectionTitle("外观")
|
SectionTitle("外观")
|
||||||
ThemeMode.entries.forEach { mode ->
|
ThemeMode.entries.forEach { mode ->
|
||||||
ThemeOption(
|
PreferenceCard {
|
||||||
label = mode.label(),
|
BasicComponent(
|
||||||
selected = prefs.themeMode == mode,
|
title = mode.label(),
|
||||||
onClick = { scope.launch { settings.setThemeMode(mode) } },
|
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))
|
Spacer(Modifier.height(8.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionTitle("聊天")
|
SectionTitle("聊天")
|
||||||
|
PreferenceCard {
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
title = "显示旁白",
|
title = "显示旁白",
|
||||||
summary = "以灰斜体小字显示 <action> / <narration>",
|
summary = "以灰斜体小字显示 <action> / <narration>",
|
||||||
checked = prefs.showNarration,
|
checked = prefs.showNarration,
|
||||||
onCheckedChange = { scope.launch { settings.setShowNarration(it) } },
|
onCheckedChange = { scope.launch { settings.setShowNarration(it) } },
|
||||||
)
|
)
|
||||||
|
}
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
PreferenceCard {
|
||||||
SwitchPreference(
|
SwitchPreference(
|
||||||
title = "思维链默认展开",
|
title = "思维链默认展开",
|
||||||
summary = "流式期间展开思维链,结束后自动折叠",
|
summary = "流式期间展开思维链,结束后自动折叠",
|
||||||
checked = prefs.thinkingExpanded,
|
checked = prefs.thinkingExpanded,
|
||||||
onCheckedChange = { scope.launch { settings.setThinkingExpanded(it) } },
|
onCheckedChange = { scope.launch { settings.setThinkingExpanded(it) } },
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
SectionTitle("关于")
|
SectionTitle("关于")
|
||||||
Row(
|
PreferenceCard {
|
||||||
modifier = Modifier
|
BasicComponent(
|
||||||
.fillMaxWidth()
|
title = "版本",
|
||||||
.padding(horizontal = 20.dp, vertical = 14.dp),
|
summary = null,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
endActions = {
|
||||||
) {
|
|
||||||
Text("版本", style = MiuixTheme.textStyles.main, modifier = Modifier.weight(1f))
|
|
||||||
Text(
|
Text(
|
||||||
text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})",
|
text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})",
|
||||||
style = MiuixTheme.textStyles.footnote1,
|
style = MiuixTheme.textStyles.footnote1,
|
||||||
color = MiuixTheme.colorScheme.onSurfaceVariantSummary,
|
color = MiuixTheme.colorScheme.onSurfaceVariantSummary,
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Spacer(Modifier.height(24.dp))
|
|
||||||
|
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) {
|
private fun ThemeMode.label(): String = when (this) {
|
||||||
ThemeMode.System -> "跟随系统"
|
ThemeMode.System -> "跟随系统"
|
||||||
ThemeMode.Light -> "浅色"
|
ThemeMode.Light -> "浅色"
|
||||||
|
|||||||
Reference in new issue
Block a user