From 39fd8318530a8faa0c6f97ccc363f126e5c9e8ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E5=88=BA=E8=9E=88?= Date: Tue, 12 Nov 2024 22:59:55 +0800 Subject: [PATCH] feat: about page --- app/build.gradle.kts | 6 +- .../main/kotlin/li/songe/gkd/ui/AboutPage.kt | 346 +++++++++++++++--- .../main/kotlin/li/songe/gkd/ui/AboutVm.kt | 9 + .../kotlin/li/songe/gkd/ui/AdvancedPage.kt | 97 ----- .../main/kotlin/li/songe/gkd/ui/AdvancedVm.kt | 3 - .../li/songe/gkd/ui/home/SettingsPage.kt | 71 ---- .../kotlin/li/songe/gkd/util/Constants.kt | 1 + .../main/kotlin/li/songe/gkd/util/SafeR.kt | 3 + .../main/res/drawable/ic_logo_animation.xml | 141 +++++++ app/src/main/res/values-night/colors.xml | 4 +- app/src/main/res/values/colors.xml | 6 +- gradle/libs.versions.toml | 3 + 12 files changed, 455 insertions(+), 235 deletions(-) create mode 100644 app/src/main/kotlin/li/songe/gkd/ui/AboutVm.kt create mode 100644 app/src/main/res/drawable/ic_logo_animation.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b4cff9a..80ec7d8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -59,7 +59,7 @@ android { applicationId = "li.songe.gkd" versionCode = 48 - versionName = "v1.9.1" + versionName = "1.9.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -153,6 +153,7 @@ android { freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi" freeCompilerArgs += "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api" freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi" + freeCompilerArgs += "-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi" } dependenciesInfo.includeInApk = false packagingOptions.resources.excludes += setOf( @@ -196,6 +197,9 @@ dependencies { implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.compose.ui) + implementation(libs.compose.ui.graphics) + implementation(libs.compose.animation) + implementation(libs.compose.animation.graphics) implementation(libs.compose.icons) implementation(libs.compose.preview) debugImplementation(libs.compose.tooling) diff --git a/app/src/main/kotlin/li/songe/gkd/ui/AboutPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/AboutPage.kt index fd014f4..f41211f 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/AboutPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/AboutPage.kt @@ -1,42 +1,188 @@ package li.songe.gkd.ui +import androidx.compose.animation.graphics.res.animatedVectorResource +import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter +import androidx.compose.animation.graphics.vector.AnimatedImageVector import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Share +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Card import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.compose.viewModel import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.update import li.songe.gkd.META +import li.songe.gkd.MainActivity +import li.songe.gkd.ui.component.RotatingLoadingIcon +import li.songe.gkd.ui.component.SettingItem +import li.songe.gkd.ui.component.TextMenu +import li.songe.gkd.ui.component.TextSwitch +import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.style.EmptyHeight import li.songe.gkd.ui.style.itemPadding +import li.songe.gkd.ui.style.titleItemPadding +import li.songe.gkd.util.ISSUES_URL import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.ProfileTransitions import li.songe.gkd.util.REPOSITORY_URL +import li.songe.gkd.util.SafeR +import li.songe.gkd.util.UpdateChannelOption +import li.songe.gkd.util.buildLogFile +import li.songe.gkd.util.checkUpdate +import li.songe.gkd.util.findOption import li.songe.gkd.util.format +import li.songe.gkd.util.launchAsFn +import li.songe.gkd.util.launchTry import li.songe.gkd.util.openUri +import li.songe.gkd.util.saveFileToDownloads +import li.songe.gkd.util.shareFile +import li.songe.gkd.util.storeFlow +import li.songe.gkd.util.throttle +import li.songe.gkd.util.toast @Destination(style = ProfileTransitions::class) @Composable fun AboutPage() { val navController = LocalNavController.current - val context = LocalContext.current + val context = LocalContext.current as MainActivity + val vm = viewModel() + val store by storeFlow.collectAsState() + + vm.uploadOptions.ShowDialog() + var showInfoDlg by remember { mutableStateOf(false) } + if (showInfoDlg) { + AlertDialog( + onDismissRequest = { showInfoDlg = false }, + title = { Text(text = "版本信息") }, + text = { + Column( + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Column { + Text(text = "构建渠道") + Text(text = META.channel) + } + Column { + Text(text = "版本代码") + Text(text = META.versionCode.toString()) + } + Column { + Text(text = "版本名称") + Text(text = META.versionName) + } + Column { + Text(text = "代码记录") + Text( + modifier = Modifier.clickable { context.openUri(META.commitUrl) }, + text = META.commitId.substring(0, 16), + color = MaterialTheme.colorScheme.primary, + style = LocalTextStyle.current.copy(textDecoration = TextDecoration.Underline), + ) + } + Column { + Text(text = "提交时间") + Text(text = META.commitTime.format("yyyy-MM-dd HH:mm:ss ZZ")) + } + } + }, + confirmButton = { + TextButton(onClick = { + showInfoDlg = false + }) { + Text(text = "关闭") + } + }, + ) + } + var showShareLogDlg by remember { mutableStateOf(false) } + if (showShareLogDlg) { + Dialog(onDismissRequest = { showShareLogDlg = false }) { + Card( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + shape = RoundedCornerShape(16.dp), + ) { + val modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + Text( + text = "分享到其他应用", modifier = Modifier + .clickable(onClick = throttle { + showShareLogDlg = false + context.mainVm.viewModelScope.launchTry(Dispatchers.IO) { + val logZipFile = buildLogFile() + context.shareFile(logZipFile, "分享日志文件") + } + }) + .then(modifier) + ) + Text( + text = "保存到下载", modifier = Modifier + .clickable(onClick = throttle { + showShareLogDlg = false + context.mainVm.viewModelScope.launchTry(Dispatchers.IO) { + val logZipFile = buildLogFile() + context.saveFileToDownloads(logZipFile) + } + }) + .then(modifier) + ) + Text( + text = "生成链接(需科学上网)", + modifier = Modifier + .clickable(onClick = throttle { + showShareLogDlg = false + vm.uploadOptions.startTask(getFile = { buildLogFile() }) + }) + .then(modifier) + ) + } + } + } val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() Scaffold( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), @@ -53,7 +199,17 @@ fun AboutPage() { ) } }, - title = { Text(text = "关于") } + title = { Text(text = "关于") }, + actions = { + IconButton(onClick = throttle(fn = { + showInfoDlg = true + })) { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = null, + ) + } + } ) } ) { contentPadding -> @@ -63,6 +219,25 @@ fun AboutPage() { .verticalScroll(rememberScrollState()) .padding(contentPadding), ) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + AnimatedLogoIcon( + modifier = Modifier + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + onClick = throttle { toast("你干嘛~ 哎呦~") } + ) + .fillMaxWidth(0.33f) + .aspectRatio(1f) + ) + Text(text = META.appName, style = MaterialTheme.typography.titleMedium) + Text(text = META.versionName, style = MaterialTheme.typography.bodyMedium) + Spacer(modifier = Modifier.height(32.dp)) + } + Column( modifier = Modifier .clickable { @@ -81,86 +256,139 @@ fun AboutPage() { color = MaterialTheme.colorScheme.primary, ) } - Column( - modifier = Modifier - .fillMaxWidth() - .itemPadding() - ) { - Text( - text = "版本代码", - style = MaterialTheme.typography.bodyLarge, - ) - Text( - text = META.versionCode.toString(), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - Column( - modifier = Modifier - .fillMaxWidth() - .itemPadding() - ) { - Text( - text = "版本名称", - style = MaterialTheme.typography.bodyLarge, - ) - Text( - text = META.versionName, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } Column( modifier = Modifier .clickable { - context.openUri(META.commitUrl) + context.openUri(ISSUES_URL) } .fillMaxWidth() .itemPadding() ) { Text( - text = "代码记录", + text = "问题反馈", style = MaterialTheme.typography.bodyLarge, ) Text( - text = META.commitId, + text = ISSUES_URL, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.primary, ) } - Column( - modifier = Modifier - .fillMaxWidth() - .itemPadding() - ) { + if (META.updateEnabled) { + val checkUpdating by context.mainVm.updateStatus.checkUpdatingFlow.collectAsState() Text( - text = "提交时间", - style = MaterialTheme.typography.bodyLarge, + text = "更新", + modifier = Modifier.titleItemPadding(), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.primary, ) - Text( - text = META.commitTime.format("yyyy-MM-dd HH:mm:ss ZZ"), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, + TextSwitch( + title = "自动更新", + subtitle = "自动检查更新", + checked = store.autoCheckAppUpdate, + onCheckedChange = { + storeFlow.value = store.copy( + autoCheckAppUpdate = it + ) + } ) + TextMenu( + title = "更新渠道", + option = UpdateChannelOption.allSubObject.findOption(store.updateChannel) + ) { + if (context.mainVm.updateStatus.checkUpdatingFlow.value) return@TextMenu + if (it.value == UpdateChannelOption.Beta.value) { + context.mainVm.viewModelScope.launchTry { + context.mainVm.dialogFlow.waitResult( + title = "版本渠道", + text = "测试版本渠道更新快\n但不稳定可能存在较多BUG\n请谨慎使用", + ) + storeFlow.update { s -> s.copy(updateChannel = it.value) } + } + } else { + storeFlow.update { s -> s.copy(updateChannel = it.value) } + } + } + + Row( + modifier = Modifier + .clickable( + onClick = throttle(fn = context.mainVm.viewModelScope.launchAsFn { + if (context.mainVm.updateStatus.checkUpdatingFlow.value) return@launchAsFn + val newVersion = context.mainVm.updateStatus.checkUpdate() + if (newVersion == null) { + toast("暂无更新") + } + }) + ) + .fillMaxWidth() + .itemPadding(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = "检查更新", + style = MaterialTheme.typography.bodyLarge, + ) + RotatingLoadingIcon(loading = checkUpdating) + } } - Column( - modifier = Modifier - .fillMaxWidth() - .itemPadding() - ) { - Text( - text = "构建渠道", - style = MaterialTheme.typography.bodyLarge, - ) - Text( - text = META.channel, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSurfaceVariant, + Text( + text = "日志", + modifier = Modifier.titleItemPadding(), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.primary, + ) + + TextSwitch( + title = "保存日志", + subtitle = "保存7天日志便于反馈问题", + checked = store.log2FileSwitch, + onCheckedChange = { + storeFlow.value = store.copy( + log2FileSwitch = it + ) + }) + + if (store.log2FileSwitch) { + SettingItem( + title = "导出日志", + imageVector = Icons.Default.Share, + onClick = { + showShareLogDlg = true + } ) } Spacer(modifier = Modifier.height(EmptyHeight)) } } +} + +@Composable +private fun AnimatedLogoIcon( + modifier: Modifier = Modifier +) { + val context = LocalContext.current as MainActivity + val enableDarkTheme by context.mainVm.enableDarkThemeFlow.collectAsState() + val darkTheme = enableDarkTheme ?: isSystemInDarkTheme() + var atEnd by remember { mutableStateOf(false) } + val animation = AnimatedImageVector.animatedVectorResource(id = SafeR.ic_logo_animation) + val painter = rememberAnimatedVectorPainter( + animation, + atEnd + ) + LaunchedEffect(Unit) { + while (true) { + atEnd = !atEnd + delay(animation.totalDuration.toLong()) + } + } + val colorRid = if (darkTheme) SafeR.better_white else SafeR.better_black + Icon( + modifier = modifier, + painter = painter, + contentDescription = null, + tint = colorResource(colorRid), + ) } \ No newline at end of file diff --git a/app/src/main/kotlin/li/songe/gkd/ui/AboutVm.kt b/app/src/main/kotlin/li/songe/gkd/ui/AboutVm.kt new file mode 100644 index 0000000..3bd8ad5 --- /dev/null +++ b/app/src/main/kotlin/li/songe/gkd/ui/AboutVm.kt @@ -0,0 +1,9 @@ +package li.songe.gkd.ui + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import li.songe.gkd.ui.component.UploadOptions + +class AboutVm : ViewModel() { + val uploadOptions = UploadOptions(viewModelScope) +} \ No newline at end of file diff --git a/app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt index 7b62c2f..4df8e02 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt @@ -15,16 +15,13 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.filled.Edit -import androidx.compose.material.icons.filled.Share import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Card import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LocalTextStyle @@ -51,7 +48,6 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.compose.viewModel import com.blankj.utilcode.util.LogUtils @@ -83,13 +79,9 @@ import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.titleItemPadding import li.songe.gkd.util.LocalNavController import li.songe.gkd.util.ProfileTransitions -import li.songe.gkd.util.buildLogFile import li.songe.gkd.util.launchAsFn -import li.songe.gkd.util.launchTry import li.songe.gkd.util.openUri import li.songe.gkd.util.privacyStoreFlow -import li.songe.gkd.util.saveFileToDownloads -import li.songe.gkd.util.shareFile import li.songe.gkd.util.storeFlow import li.songe.gkd.util.throttle import li.songe.gkd.util.toast @@ -104,8 +96,6 @@ fun AdvancedPage() { val store by storeFlow.collectAsState() val snapshotCount by vm.snapshotCountFlow.collectAsState() - vm.uploadOptions.ShowDialog() - var showEditPortDlg by remember { mutableStateOf(false) } @@ -165,55 +155,6 @@ fun AdvancedPage() { }) } - var showShareLogDlg by remember { - mutableStateOf(false) - } - if (showShareLogDlg) { - Dialog(onDismissRequest = { showShareLogDlg = false }) { - Card( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - shape = RoundedCornerShape(16.dp), - ) { - val modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - Text( - text = "分享到其他应用", modifier = Modifier - .clickable(onClick = throttle { - showShareLogDlg = false - vm.viewModelScope.launchTry(Dispatchers.IO) { - val logZipFile = buildLogFile() - context.shareFile(logZipFile, "分享日志文件") - } - }) - .then(modifier) - ) - Text( - text = "保存到下载", modifier = Modifier - .clickable(onClick = throttle { - showShareLogDlg = false - vm.viewModelScope.launchTry(Dispatchers.IO) { - val logZipFile = buildLogFile() - context.saveFileToDownloads(logZipFile) - } - }) - .then(modifier) - ) - Text( - text = "生成链接(需科学上网)", - modifier = Modifier - .clickable(onClick = throttle { - showShareLogDlg = false - vm.uploadOptions.startTask(getFile = { buildLogFile() }) - }) - .then(modifier) - ) - } - } - } - var showEditCookieDlg by remember { mutableStateOf(false) } if (showEditCookieDlg) { val privacyStore by privacyStoreFlow.collectAsState() @@ -540,44 +481,6 @@ fun AdvancedPage() { } ) - Text( - text = "日志", - modifier = Modifier.titleItemPadding(), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.primary, - ) - - TextSwitch( - title = "保存日志", - subtitle = "保存7天日志,帮助定位BUG", - checked = store.log2FileSwitch, - onCheckedChange = { - storeFlow.value = store.copy( - log2FileSwitch = it - ) - if (!it) { - context.mainVm.viewModelScope.launchTry(Dispatchers.IO) { - val logFiles = LogUtils.getLogFiles() - if (logFiles.isNotEmpty()) { - logFiles.forEach { f -> - f.delete() - } - toast("已删除全部日志") - } - } - } - }) - - if (store.log2FileSwitch) { - SettingItem( - title = "导出日志", - imageVector = Icons.Default.Share, - onClick = { - showShareLogDlg = true - } - ) - } - Text( text = "其它", modifier = Modifier.titleItemPadding(), diff --git a/app/src/main/kotlin/li/songe/gkd/ui/AdvancedVm.kt b/app/src/main/kotlin/li/songe/gkd/ui/AdvancedVm.kt index efe01f0..993cece 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/AdvancedVm.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/AdvancedVm.kt @@ -5,11 +5,8 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn import li.songe.gkd.db.DbSet -import li.songe.gkd.ui.component.UploadOptions class AdvancedVm : ViewModel() { val snapshotCountFlow = DbSet.snapshotDao.count().stateIn(viewModelScope, SharingStarted.Eagerly, 0) - - val uploadOptions = UploadOptions(viewModelScope) } \ No newline at end of file diff --git a/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt b/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt index bc6081c..e276e9a 100644 --- a/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt +++ b/app/src/main/kotlin/li/songe/gkd/ui/home/SettingsPage.kt @@ -33,34 +33,24 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.style.TextAlign -import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.compose.viewModel import com.ramcosta.composedestinations.generated.destinations.AboutPageDestination import com.ramcosta.composedestinations.generated.destinations.AdvancedPageDestination import com.ramcosta.composedestinations.utils.toDestinationsNavigator import kotlinx.coroutines.flow.update -import li.songe.gkd.META import li.songe.gkd.MainActivity -import li.songe.gkd.ui.component.RotatingLoadingIcon import li.songe.gkd.ui.component.SettingItem import li.songe.gkd.ui.component.TextMenu import li.songe.gkd.ui.component.TextSwitch import li.songe.gkd.ui.component.updateDialogOptions -import li.songe.gkd.ui.component.waitResult import li.songe.gkd.ui.style.EmptyHeight -import li.songe.gkd.ui.style.itemPadding import li.songe.gkd.ui.style.titleItemPadding import li.songe.gkd.ui.theme.supportDynamicColor import li.songe.gkd.util.DarkThemeOption import li.songe.gkd.util.LocalNavController -import li.songe.gkd.util.UpdateChannelOption -import li.songe.gkd.util.checkUpdate import li.songe.gkd.util.findOption -import li.songe.gkd.util.launchAsFn -import li.songe.gkd.util.launchTry import li.songe.gkd.util.storeFlow import li.songe.gkd.util.throttle -import li.songe.gkd.util.toast val settingsNav = BottomNavItem( label = "设置", icon = Icons.Outlined.Settings @@ -80,7 +70,6 @@ fun useSettingsPage(): ScaffoldExt { mutableStateOf(false) } - val checkUpdating by context.mainVm.updateStatus.checkUpdatingFlow.collectAsState() if (showToastInputDlg) { var value by remember { @@ -297,66 +286,6 @@ fun useSettingsPage(): ScaffoldExt { }) } - if (META.updateEnabled) { - Text( - text = "更新", - modifier = Modifier.titleItemPadding(), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.primary, - ) - - TextSwitch( - title = "自动更新", - subtitle = "打开应用时检测新版本", - checked = store.autoCheckAppUpdate, - onCheckedChange = { - storeFlow.value = store.copy( - autoCheckAppUpdate = it - ) - } - ) - - TextMenu( - title = "更新渠道", - option = UpdateChannelOption.allSubObject.findOption(store.updateChannel) - ) { - if (it.value == UpdateChannelOption.Beta.value) { - vm.viewModelScope.launchTry { - context.mainVm.dialogFlow.waitResult( - title = "版本渠道", - text = "测试版本渠道更新快\n但不稳定可能存在较多BUG\n请谨慎使用", - ) - storeFlow.update { s -> s.copy(updateChannel = it.value) } - } - } else { - storeFlow.update { s -> s.copy(updateChannel = it.value) } - } - } - - Row( - modifier = Modifier - .clickable( - onClick = throttle(fn = context.mainVm.viewModelScope.launchAsFn { - if (context.mainVm.updateStatus.checkUpdatingFlow.value) return@launchAsFn - val newVersion = context.mainVm.updateStatus.checkUpdate() - if (newVersion == null) { - toast("暂无更新") - } - }) - ) - .fillMaxWidth() - .itemPadding(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = "检查更新", - style = MaterialTheme.typography.bodyLarge, - ) - RotatingLoadingIcon(loading = checkUpdating) - } - } - Text( text = "其它", modifier = Modifier.titleItemPadding(), diff --git a/app/src/main/kotlin/li/songe/gkd/util/Constants.kt b/app/src/main/kotlin/li/songe/gkd/util/Constants.kt index c955ce4..4e7554a 100644 --- a/app/src/main/kotlin/li/songe/gkd/util/Constants.kt +++ b/app/src/main/kotlin/li/songe/gkd/util/Constants.kt @@ -9,6 +9,7 @@ const val SERVER_SCRIPT_URL = "https://registry.npmmirror.com/@gkd-kit/config/latest/files/dist/server.js" const val REPOSITORY_URL = "https://github.com/gkd-kit/gkd" +const val ISSUES_URL = "${REPOSITORY_URL}/issues" const val HOME_PAGE_URL = "https://gkd.li" diff --git a/app/src/main/kotlin/li/songe/gkd/util/SafeR.kt b/app/src/main/kotlin/li/songe/gkd/util/SafeR.kt index 4511f5f..04ee71e 100644 --- a/app/src/main/kotlin/li/songe/gkd/util/SafeR.kt +++ b/app/src/main/kotlin/li/songe/gkd/util/SafeR.kt @@ -12,4 +12,7 @@ object SafeR { val ic_page_info: Int = R.drawable.ic_page_info val ic_flash_on: Int = R.drawable.ic_flash_on val ic_flash_off: Int = R.drawable.ic_flash_off + val ic_logo_animation: Int = R.drawable.ic_logo_animation + val better_black: Int = R.color.better_black + val better_white: Int = R.color.better_white } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_logo_animation.xml b/app/src/main/res/drawable/ic_logo_animation.xml new file mode 100644 index 0000000..1ba593d --- /dev/null +++ b/app/src/main/res/drawable/ic_logo_animation.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 636aebb..ed11b9e 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -1,5 +1,5 @@ - #FCFCFC - #111 + @color/better_white + @color/better_black diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d0ce8c7..e8a96f5 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,5 +1,7 @@ - #111 - #FCFCFC + #FCFCFC + #111111 + @color/better_black + @color/better_white diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 924a65a..5bbc2eb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,6 +26,9 @@ ktor_client_content_negotiation = { module = "io.ktor:ktor-client-content-negoti ktor_serialization_kotlinx_json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } android_gradle = { module = "com.android.tools.build:gradle", version.ref = "android" } compose_ui = { module = "androidx.compose.ui:ui", version.ref = "compose" } +compose_ui_graphics = { module = "androidx.compose.ui:ui-graphics", version.ref = "compose" } +compose_animation = { module = "androidx.compose.animation:animation", version.ref = "compose" } +compose_animation_graphics = { module = "androidx.compose.animation:animation-graphics", version.ref = "compose" } compose_preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" } compose_tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" } compose_junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" }