diff --git a/base-core/src/main/java/com/funny/translation/theme/Theme.kt b/base-core/src/main/java/com/funny/translation/theme/Theme.kt index 564866d8..50b1672c 100644 --- a/base-core/src/main/java/com/funny/translation/theme/Theme.kt +++ b/base-core/src/main/java/com/funny/translation/theme/Theme.kt @@ -5,6 +5,7 @@ import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.SystemBarStyle import androidx.activity.enableEdgeToEdge +import androidx.annotation.StringRes import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme @@ -17,6 +18,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.MutableState import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.getValue import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext @@ -24,9 +26,11 @@ import com.funny.cmaterialcolors.MaterialColors import com.funny.data_saver.core.mutableDataSaverStateOf import com.funny.translation.AppConfig import com.funny.translation.BaseApplication +import com.funny.translation.core.R import com.funny.translation.helper.DataSaverUtils import com.funny.translation.helper.DateUtils import com.funny.translation.helper.DeviceUtils +import com.funny.translation.helper.string import com.funny.translation.helper.toastOnUi import com.kyant.monet.LocalTonalPalettes import com.kyant.monet.PaletteStyle @@ -150,9 +154,18 @@ sealed class ThemeType(val id: Int) { } } +enum class LightDarkMode(@StringRes val descId: Int) { + Light(R.string.always_light), Dark(R.string.always_dark), System(R.string.follow_system); + + override fun toString(): String { + return string(descId) + } +} + object ThemeConfig { private const val TAG = "ThemeConfig" - var sThemeType: MutableState = mutableDataSaverStateOf(DataSaverUtils, "theme_type", ThemeType.Default) + val sThemeType: MutableState = mutableDataSaverStateOf(DataSaverUtils, "theme_type", ThemeType.Default) + val lightDarkMode: MutableState = mutableDataSaverStateOf(DataSaverUtils, "light_dark_mode", LightDarkMode.System) fun updateThemeType(new: ThemeType){ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S && new == ThemeType.DynamicNative) { @@ -172,11 +185,27 @@ object ThemeConfig { sThemeType.value = new Log.d(TAG, "updateThemeType: $new") } + + fun updateLightDarkMode(new: LightDarkMode){ + lightDarkMode.value = new +// Log.d(TAG, "updateLightDarkMode: $new") + } +} + +@Composable +@ReadOnlyComposable +private fun calcDark(): Boolean { + val lightDarkMode by ThemeConfig.lightDarkMode + return when(lightDarkMode) { + LightDarkMode.Light -> false + LightDarkMode.Dark -> true + LightDarkMode.System -> isSystemInDarkTheme() + } } @Composable fun TransTheme( - dark: Boolean = isSystemInDarkTheme(), + dark: Boolean = calcDark(), hideStatusBar: Boolean = false, content: @Composable () -> Unit ) { @@ -196,18 +225,17 @@ fun TransTheme( val mContent = @Composable { // SystemBarSettings(hideStatusBar) - val darkTheme = isSystemInDarkTheme() val context = LocalContext.current as ComponentActivity val c = MaterialTheme.colorScheme.primaryContainer.toArgb() - DisposableEffect(darkTheme) { + DisposableEffect(dark) { context.enableEdgeToEdge( statusBarStyle = SystemBarStyle.auto( android.graphics.Color.TRANSPARENT, android.graphics.Color.TRANSPARENT, - ) { darkTheme }, + ) { dark }, navigationBarStyle = - if (darkTheme) SystemBarStyle.dark(transparent) - else SystemBarStyle.light(transparent, c), + if (dark) SystemBarStyle.dark(transparent) + else SystemBarStyle.light(transparent, c), ) onDispose {} } @@ -239,7 +267,7 @@ fun TransTheme( val ColorScheme.isLight: Boolean @Composable @ReadOnlyComposable - get() = !isSystemInDarkTheme() + get() = !calcDark() @Composable fun MonetTheme(color: Color, content: @Composable () -> Unit) { @@ -252,7 +280,7 @@ fun MonetTheme(color: Color, content: @Composable () -> Unit) { ) ) { MaterialTheme( - colorScheme = dynamicColorScheme(isDark = isSystemInDarkTheme()), + colorScheme = dynamicColorScheme(isDark = calcDark()), content = content ) } diff --git a/base-core/src/main/res/values/strings.xml b/base-core/src/main/res/values/strings.xml index f50f0086..552abfcc 100644 --- a/base-core/src/main/res/values/strings.xml +++ b/base-core/src/main/res/values/strings.xml @@ -38,4 +38,6 @@ 此语种暂不支持 您似乎没有注册过,请先注册账号吧~ 写入文件时发生错误 + 始终浅色 + 始终深色 \ No newline at end of file diff --git a/jet-setting-core/src/main/java/com/funny/jetsetting/core/JetSettingWidgets.kt b/jet-setting-core/src/main/java/com/funny/jetsetting/core/JetSettingWidgets.kt index b619c369..be1001cc 100644 --- a/jet-setting-core/src/main/java/com/funny/jetsetting/core/JetSettingWidgets.kt +++ b/jet-setting-core/src/main/java/com/funny/jetsetting/core/JetSettingWidgets.kt @@ -1,10 +1,12 @@ package com.funny.jetsetting.core +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Switch @@ -138,6 +140,7 @@ fun JetSettingDialog( imageVector: ImageVector? = null, resourceId: Int? = null, text: String, + description: String? = null, dialogTitle: String = stringResource(id = R.string.hint), confirmButtonAction: (() -> Unit)? = EmptyAction, confirmButtonText: String = stringResource(id = R.string.confirm), @@ -182,6 +185,7 @@ fun JetSettingDialog( JetSettingTile( modifier = modifier, text = text, + description = description, imageVector = imageVector, resourceId = resourceId, onClick = { @@ -195,6 +199,7 @@ fun JetSettingListDialog( modifier: Modifier = Modifier, list: ImmutableList, text: String, + description: String? = null, imageVector: ImageVector? = null, resourceId: Int? = null, selected: E, @@ -207,6 +212,7 @@ fun JetSettingListDialog( JetSettingDialog( modifier = modifier, text = text, + description = description, resourceId = resourceId, imageVector = imageVector, confirmButtonAction = confirmButtonAction, @@ -218,17 +224,14 @@ fun JetSettingListDialog( verticalArrangement = Arrangement.spacedBy(4.dp), ) { itemsIndexed(list) { i, item -> - SettingBaseItem( - modifier = Modifier.padding(vertical = 4.dp), - title = { + ListItem( + modifier = Modifier.clickable { updateSelected(item) }, + headlineContent = { Text(text = item.toString()) }, - action = { + trailingContent = { RadioButton(selected = selected == item, onClick = { updateSelected(item) }) }, - onClick = { - updateSelected(item) - } ) } } diff --git a/translate/src/main/java/com/funny/translation/translate/FunnyApplication.kt b/translate/src/main/java/com/funny/translation/translate/FunnyApplication.kt index 3cec8107..4a045ed3 100644 --- a/translate/src/main/java/com/funny/translation/translate/FunnyApplication.kt +++ b/translate/src/main/java/com/funny/translation/translate/FunnyApplication.kt @@ -17,6 +17,7 @@ import com.funny.translation.codeeditor.ui.editor.EditorSchemes import com.funny.translation.helper.DeviceUtils import com.funny.translation.helper.JsonX import com.funny.translation.sign.SignUtils +import com.funny.translation.theme.LightDarkMode import com.funny.translation.theme.ThemeType import com.funny.translation.translate.ui.TranslateScreen import com.funny.translation.translate.ui.long_text.EditablePrompt @@ -110,6 +111,7 @@ class FunnyApplication : BaseApplication() { registerTypeConverters(save = TranslateScreen.Saver, restore = TranslateScreen.Restorer) registerTypeConverters(save = ChatMemory.Saver, restore = ChatMemory.Restorer) registerTypeConverters(save = { JsonX.toJson(it) }, restore = { JsonX.fromJson(it) }) + registerTypeConverters(save = { it.name }, restore = { LightDarkMode.valueOf(it) }) } @RequiresApi(Build.VERSION_CODES.O) diff --git a/translate/src/main/java/com/funny/translation/translate/ui/settings/SettingsScreen.kt b/translate/src/main/java/com/funny/translation/translate/ui/settings/SettingsScreen.kt index cdc3ca11..eb61a1b0 100644 --- a/translate/src/main/java/com/funny/translation/translate/ui/settings/SettingsScreen.kt +++ b/translate/src/main/java/com/funny/translation/translate/ui/settings/SettingsScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DarkMode import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Sort import androidx.compose.material3.Checkbox @@ -63,6 +64,8 @@ import com.funny.translation.helper.LocaleUtils import com.funny.translation.helper.string import com.funny.translation.helper.toastOnUi import com.funny.translation.network.ServiceCreator +import com.funny.translation.theme.LightDarkMode +import com.funny.translation.theme.ThemeConfig import com.funny.translation.translate.Language import com.funny.translation.translate.LocalNavController import com.funny.translation.translate.R @@ -84,6 +87,9 @@ import org.burnoutcrew.reorderable.rememberReorderState import org.burnoutcrew.reorderable.reorderable private const val TAG = "SettingScreen" +private val languages = AppLanguage.values().toList().toImmutableList() +private val lightDarkModes = LightDarkMode.values().toList().toImmutableList() + @Composable fun SettingsScreen() { @@ -113,6 +119,8 @@ fun SettingsScreen() { // 设置应用显示的语言 // 跟随系统、简体中文、英语 SelectAppLanguage() + // 设置应用的深浅色模式 + SelectLightDarkMode() } SettingItemCategory( title = { @@ -234,13 +242,13 @@ fun SettingsScreen() { @Composable private fun SelectAppLanguage() { - val languages = AppLanguage.values().toList().toImmutableList() val context = LocalContext.current var tempLanguage by remember { mutableStateOf(LocaleUtils.getAppLanguage()) } JetSettingListDialog( list = languages, text = stringResource(id = R.string.app_language), + description = tempLanguage.description, resourceId = R.drawable.ic_language_select, selected = tempLanguage, updateSelected = { @@ -257,6 +265,22 @@ private fun SelectAppLanguage() { ) } +@Composable +private fun SelectLightDarkMode() { + var lightDarkMode by ThemeConfig.lightDarkMode + + JetSettingListDialog( + list = lightDarkModes, + text = stringResource(id = R.string.app_light_dark_mode), + description = stringResource(id = lightDarkMode.descId), + imageVector = Icons.Default.DarkMode, + selected = lightDarkMode, + updateSelected = { + lightDarkMode = it + } + ) +} + @Composable private fun DevSetBaseUrl() { var text by remember { diff --git a/translate/src/main/res/values/strings.xml b/translate/src/main/res/values/strings.xml index 9f65efb2..bd2fd4d7 100644 --- a/translate/src/main/res/values/strings.xml +++ b/translate/src/main/res/values/strings.xml @@ -327,4 +327,5 @@ 还原 无法解析的错误输出: Prompt指定了模型的任务,它能很大程度上影响翻译质量。如果有特殊的需求(比如语种、表达方式、专业领域等),建议指定、\n\n必须和外语类学习、翻译相关,修改时会进行判定。无论判定是否通过,均会扣除判定所用的点数,谨慎修改, + 深色模式 \ No newline at end of file