From 9e19cad535ab918da0851ef7f3e8588953cd3042 Mon Sep 17 00:00:00 2001 From: SanmerDev Date: Sat, 29 Jun 2024 17:09:59 +0800 Subject: [PATCH] Add `LanguageItem` --- .../ui/screens/settings/app/AppScreen.kt | 127 +++++++++++++++++- .../settings/app/items/DownloadPathItem.kt | 87 ------------ .../mrepo/utils/extensions/ContextExt.kt | 11 +- .../utils/extensions/LocaleListCompatExt.kt | 6 + app/src/main/res/drawable/world.xml | 36 +++++ app/src/main/res/values-zh-rCN/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 7 files changed, 179 insertions(+), 92 deletions(-) delete mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt create mode 100644 app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocaleListCompatExt.kt create mode 100644 app/src/main/res/drawable/world.xml diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/AppScreen.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/AppScreen.kt index ae652d8b..a1109f6f 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/AppScreen.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/AppScreen.kt @@ -1,35 +1,57 @@ package dev.sanmer.mrepo.ui.screens.settings.app +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.provider.Settings import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize 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.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import dev.sanmer.mrepo.R +import dev.sanmer.mrepo.app.Const +import dev.sanmer.mrepo.compat.BuildCompat import dev.sanmer.mrepo.datastore.model.WorkingMode.Companion.isRoot import dev.sanmer.mrepo.ui.component.NavigateUpTopBar +import dev.sanmer.mrepo.ui.component.SettingNormalItem import dev.sanmer.mrepo.ui.component.SettingSwitchItem +import dev.sanmer.mrepo.ui.component.TextFieldDialog import dev.sanmer.mrepo.ui.providable.LocalUserPreferences import dev.sanmer.mrepo.ui.screens.settings.app.items.AppThemeItem -import dev.sanmer.mrepo.ui.screens.settings.app.items.DownloadPathItem +import dev.sanmer.mrepo.utils.extensions.applicationLocale import dev.sanmer.mrepo.viewmodel.SettingsViewModel +import java.io.File +import java.util.Locale @Composable fun AppScreen( navController: NavController, viewModel: SettingsViewModel = hiltViewModel() ) { + val context = LocalContext.current val userPreferences = LocalUserPreferences.current val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() @@ -49,6 +71,10 @@ fun AppScreen( .fillMaxSize() .verticalScroll(rememberScrollState()) ) { + LanguageItem( + context = context + ) + AppThemeItem( themeColor = userPreferences.themeColor, darkMode = userPreferences.darkMode, @@ -74,6 +100,93 @@ fun AppScreen( } } +@SuppressLint("InlinedApi") +@Composable +private fun LanguageItem( + context: Context +) = SettingNormalItem( + icon = R.drawable.world, + title = stringResource(id = R.string.settings_language), + desc = context.applicationLocale?.localizedDisplayName ?: stringResource(id = R.string.settings_language_system), + onClick = { + context.startActivity( + Intent( + Settings.ACTION_APP_LOCALE_SETTINGS, + Uri.fromParts("package", context.packageName, null) + ) + ) + }, + enabled = BuildCompat.atLeastT +) + +@Composable +private fun DownloadPathItem( + downloadPath: String, + onChange: (String) -> Unit +) { + var edit by remember { mutableStateOf(false) } + if (edit) EditDialog( + path = downloadPath, + onClose = { edit = false }, + onConfirm = onChange + ) + + SettingNormalItem( + icon = R.drawable.files, + title = stringResource(id = R.string.settings_download_path), + desc = downloadPath, + onClick = { edit = true } + ) +} + +@Composable +private fun EditDialog( + path: String, + onClose: () -> Unit, + onConfirm: (String) -> Unit +) { + var name by remember { + mutableStateOf( + File(path).toRelativeString(Const.PUBLIC_DOWNLOADS) + ) + } + + TextFieldDialog( + shape = RoundedCornerShape(20.dp), + onDismissRequest = onClose, + title = { Text(text = stringResource(id = R.string.settings_download_path)) }, + confirmButton = { + TextButton( + onClick = { + onConfirm( + File(Const.PUBLIC_DOWNLOADS, name.trim()).path + ) + onClose() + }, + ) { + Text(text = stringResource(id = R.string.dialog_ok)) + } + }, + dismissButton = { + TextButton( + onClick = onClose + ) { + Text(text = stringResource(id = R.string.dialog_cancel)) + } + }, + launchKeyboard = false + ) { + OutlinedTextField( + textStyle = MaterialTheme.typography.bodyLarge, + value = name, + onValueChange = { name = it }, + shape = RoundedCornerShape(15.dp), + label = { Text(text = Const.PUBLIC_DOWNLOADS.absolutePath) }, + singleLine = true + ) + } +} + @Composable private fun TopBar( scrollBehavior: TopAppBarScrollBehavior, @@ -82,4 +195,14 @@ private fun TopBar( title = stringResource(id = R.string.settings_app), scrollBehavior = scrollBehavior, navController = navController -) \ No newline at end of file +) + +private val Locale.localizedDisplayName: String + get() = getDisplayName(this) + .replaceFirstChar { + if (it.isLowerCase()) { + it.titlecase(this) + } else { + it.toString() + } + } \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt b/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt deleted file mode 100644 index 858f7c8c..00000000 --- a/app/src/main/kotlin/dev/sanmer/mrepo/ui/screens/settings/app/items/DownloadPathItem.kt +++ /dev/null @@ -1,87 +0,0 @@ -package dev.sanmer.mrepo.ui.screens.settings.app.items - -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import dev.sanmer.mrepo.R -import dev.sanmer.mrepo.app.Const -import dev.sanmer.mrepo.ui.component.SettingNormalItem -import dev.sanmer.mrepo.ui.component.TextFieldDialog -import java.io.File - -@Composable -internal fun DownloadPathItem( - downloadPath: String, - onChange: (String) -> Unit -) { - var edit by remember { mutableStateOf(false) } - if (edit) EditDialog( - path = downloadPath, - onClose = { edit = false }, - onConfirm = onChange - ) - - SettingNormalItem( - icon = R.drawable.files, - title = stringResource(id = R.string.settings_download_path), - desc = downloadPath, - onClick = { edit = true } - ) -} - -@Composable -private fun EditDialog( - path: String, - onClose: () -> Unit, - onConfirm: (String) -> Unit -) { - var name by remember { - mutableStateOf( - File(path).toRelativeString(Const.PUBLIC_DOWNLOADS) - ) - } - - TextFieldDialog( - shape = RoundedCornerShape(20.dp), - onDismissRequest = onClose, - title = { Text(text = stringResource(id = R.string.settings_download_path)) }, - confirmButton = { - TextButton( - onClick = { - onConfirm( - File(Const.PUBLIC_DOWNLOADS, name.trim()).path - ) - onClose() - }, - ) { - Text(text = stringResource(id = R.string.dialog_ok)) - } - }, - dismissButton = { - TextButton( - onClick = onClose - ) { - Text(text = stringResource(id = R.string.dialog_cancel)) - } - }, - launchKeyboard = false - ) { - OutlinedTextField( - textStyle = MaterialTheme.typography.bodyLarge, - value = name, - onValueChange = { name = it }, - shape = RoundedCornerShape(15.dp), - label = { Text(text = Const.PUBLIC_DOWNLOADS.absolutePath) }, - singleLine = true - ) - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ContextExt.kt b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ContextExt.kt index 66309985..90205a98 100644 --- a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ContextExt.kt +++ b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/ContextExt.kt @@ -2,6 +2,7 @@ package dev.sanmer.mrepo.utils.extensions import android.content.Context import android.content.Intent +import androidx.core.app.LocaleManagerCompat import androidx.core.app.ShareCompat val Context.tmpDir get() = cacheDir.resolve("tmp") @@ -9,10 +10,14 @@ val Context.tmpDir get() = cacheDir.resolve("tmp") if (!exists()) mkdirs() } +val Context.applicationLocale + get() = LocaleManagerCompat.getApplicationLocales(applicationContext) + .toList().firstOrNull() + fun Context.openUrl(url: String) { - Intent.parseUri(url, Intent.URI_INTENT_SCHEME).apply { - startActivity(this) - } + startActivity( + Intent.parseUri(url, Intent.URI_INTENT_SCHEME) + ) } fun Context.shareText(text: String) { diff --git a/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocaleListCompatExt.kt b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocaleListCompatExt.kt new file mode 100644 index 00000000..c6973892 --- /dev/null +++ b/app/src/main/kotlin/dev/sanmer/mrepo/utils/extensions/LocaleListCompatExt.kt @@ -0,0 +1,6 @@ +package dev.sanmer.mrepo.utils.extensions + +import androidx.core.os.LocaleListCompat +import java.util.Locale + +fun LocaleListCompat.toList(): List = List(size()) { this[it]!! } \ No newline at end of file diff --git a/app/src/main/res/drawable/world.xml b/app/src/main/res/drawable/world.xml new file mode 100644 index 00000000..86574e73 --- /dev/null +++ b/app/src/main/res/drawable/world.xml @@ -0,0 +1,36 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index d23850ed..d9fb0e45 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -76,6 +76,8 @@ 功能受到限制 + 语言 + 系统默认 主题 更改主题配色和深色模式 下载路径 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4ddcbda..405127ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -77,6 +77,8 @@ Functionality is limited + Language + System default App Theme Change color scheme and night mode Download Path