merge: W8 — 设置页「版本」行可点进「关于」页(含作者署名)

This commit is contained in:
AskaEth committed 2026-10-04 18:35:11 +08:00
commit f24877d53b
4 files changed
+138 -2

No files matched your search

@@ -15,6 +15,7 @@ import top.yeij.cyrene.ui.admin.AdminHomeScreen
import top.yeij.cyrene.ui.common.MiuixDrawer
import top.yeij.cyrene.ui.sessions.SessionDrawerContent
import top.yeij.cyrene.ui.sessions.SessionsViewModel
import top.yeij.cyrene.ui.settings.AboutScreen
import top.yeij.cyrene.ui.settings.SettingsScreen
/**
@@ -33,9 +34,13 @@ fun ChatHomeScreen(
var drawerOpen by remember { mutableStateOf(false) }
var showSettings by remember { mutableStateOf(false) }
var showAdmin by remember { mutableStateOf(false) }
var showAbout by remember { mutableStateOf(false) }
BackHandler(enabled = showAdmin) { showAdmin = false }
BackHandler(enabled = showSettings) { showSettings = false }
// 「关于」嵌在设置页里,所以两个条件必须**互斥**:在关于页时设置页的处理器关掉,
// 返回才只退一层(关于 → 设置),不会一步跳回聊天。
BackHandler(enabled = showAbout) { showAbout = false }
BackHandler(enabled = showSettings && !showAbout) { showSettings = false }
BackHandler(enabled = drawerOpen) { drawerOpen = false }
when {
@@ -44,10 +49,13 @@ fun ChatHomeScreen(
onBack = { showAdmin = false },
)
showAbout -> AboutScreen(onBack = { showAbout = false })
showSettings -> SettingsScreen(
container = container,
onBack = { showSettings = false },
onLogout = onLogout,
onOpenAbout = { showAbout = true },
)
else -> MiuixDrawer(
@@ -0,0 +1,96 @@
package top.yeij.cyrene.ui.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import top.yeij.cyrene.BuildConfig
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.icon.MiuixIcons
import top.yukonga.miuix.kmp.icon.extended.ChevronBackward
import top.yukonga.miuix.kmp.theme.MiuixTheme
/**
* 「关于」页:只有名称、版本、简介、作者这四项。
*
* 这四项分别来自本端常量与 `BuildConfig`(由 `app/build.gradle.kts` 生成),**不写死版本号**;
* 页面里刻意不放任何链接 / 邮箱 / 版权年份——没有人提供过这些信息,编不得。
*
* 与设置页同为聊天之上的独立层级:自己带 `Scaffold`,返回落到设置页(层级见 `ChatHomeScreen`)。
*/
@Composable
fun AboutScreen(onBack: () -> Unit) {
Scaffold(
topBar = {
SmallTopAppBar(
title = "关于",
navigationIcon = {
IconButton(onClick = onBack) {
Icon(imageVector = MiuixIcons.ChevronBackward, contentDescription = "返回")
}
},
)
},
) { padding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(Modifier.height(40.dp))
Text("Cyrene", style = MiuixTheme.textStyles.title1)
Spacer(Modifier.height(4.dp))
Text(
text = "Cyrene v2 后端的 Android 客户端",
style = MiuixTheme.textStyles.footnote1,
color = MiuixTheme.colorScheme.onSurfaceVariantSummary,
modifier = Modifier.padding(horizontal = 24.dp),
)
Spacer(Modifier.height(32.dp))
AboutRow(title = "版本", value = versionText(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE))
Spacer(Modifier.height(8.dp))
AboutRow(title = "作者", value = "AskaEth")
Spacer(Modifier.height(32.dp))
}
}
}
@Composable
private fun AboutRow(title: String, value: String) {
PreferenceCard {
BasicComponent(
title = title,
endActions = {
Text(
text = value,
style = MiuixTheme.textStyles.footnote1,
color = MiuixTheme.colorScheme.onSurfaceVariantSummary,
)
},
)
}
}
/**
* 版本号的显示文本(纯函数):设置页的「版本」行与关于页共用同一份输出,格式不会各写各的。
*
* 值一律来自 `BuildConfig`(AGP 按 `build.gradle.kts` 的 `versionName` / `versionCode` 生成),
* 两处都不写死版本号,发版只需改构建文件。
*/
internal fun versionText(versionName: String, versionCode: Int): String = "$versionName ($versionCode)"
@@ -33,6 +33,7 @@ import top.yukonga.miuix.kmp.basic.Text
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.icon.extended.ChevronForward
import top.yukonga.miuix.kmp.preference.SwitchPreference
import top.yukonga.miuix.kmp.theme.MiuixTheme
@@ -41,6 +42,7 @@ fun SettingsScreen(
container: AppContainer,
onBack: () -> Unit,
onLogout: () -> Unit = {},
onOpenAbout: () -> Unit = {},
) {
val prefs by container.appSettings.data.collectAsState(initial = AppPrefs())
val scope = rememberCoroutineScope()
@@ -129,12 +131,19 @@ fun SettingsScreen(
BasicComponent(
title = "版本",
summary = null,
onClick = onOpenAbout,
endActions = {
Text(
text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})",
text = versionText(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE),
style = MiuixTheme.textStyles.footnote1,
color = MiuixTheme.colorScheme.onSurfaceVariantSummary,
)
Icon(
imageVector = MiuixIcons.ChevronForward,
contentDescription = null,
modifier = Modifier.padding(start = 6.dp),
tint = MiuixTheme.colorScheme.onSurfaceVariantSummary,
)
},
)
}
@@ -0,0 +1,23 @@
package top.yeij.cyrene.ui.settings
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* 版本文本的格式(纯函数):设置页的「版本」行与关于页共用同一份输出。
*
* 这里钉的是**格式**,不是某个具体版本号——值来自 `BuildConfig`,发版只改构建文件。
*/
class VersionTextTest {
@Test
fun `version name is followed by the code in parentheses`() {
assertEquals("0.1.0 (1)", versionText("0.1.0", 1))
}
@Test
fun `both inputs are rendered verbatim, so the label tracks the build config`() {
assertEquals("2.3.4 (567)", versionText("2.3.4", 567))
assertEquals("1.0.0-beta (42)", versionText("1.0.0-beta", 42))
}
}