mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Kmp strings cleanup (#3669)
This commit is contained in:
parent
bde7c47931
commit
57ef889caa
6 changed files with 341 additions and 209 deletions
|
|
@ -29,7 +29,10 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||
import androidx.appcompat.app.AppCompatActivity.RESULT_OK
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
|
@ -42,7 +45,13 @@ import androidx.compose.material.icons.rounded.LocationOn
|
|||
import androidx.compose.material.icons.rounded.Memory
|
||||
import androidx.compose.material.icons.rounded.Output
|
||||
import androidx.compose.material.icons.rounded.WavingHand
|
||||
import androidx.compose.material3.AlertDialogDefaults
|
||||
import androidx.compose.material3.BasicAlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -53,16 +62,15 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.rememberMultiplePermissionsState
|
||||
import com.meshtastic.core.strings.getString
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.common.gpsDisabled
|
||||
import org.meshtastic.core.database.DatabaseConstants
|
||||
|
|
@ -95,7 +103,6 @@ import org.meshtastic.core.strings.theme_system
|
|||
import org.meshtastic.core.ui.component.DropDownPreference
|
||||
import org.meshtastic.core.ui.component.ListItem
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.MultipleChoiceAlertDialog
|
||||
import org.meshtastic.core.ui.component.SwitchListItem
|
||||
import org.meshtastic.core.ui.component.TitledCard
|
||||
import org.meshtastic.core.ui.theme.MODE_DYNAMIC
|
||||
|
|
@ -106,7 +113,7 @@ import org.meshtastic.feature.settings.radio.RadioConfigViewModel
|
|||
import org.meshtastic.feature.settings.radio.component.EditDeviceProfileDialog
|
||||
import org.meshtastic.feature.settings.radio.component.PacketResponseStateDialog
|
||||
import org.meshtastic.feature.settings.util.LanguageUtils
|
||||
import org.meshtastic.feature.settings.util.LanguageUtils.getLanguageMap
|
||||
import org.meshtastic.feature.settings.util.LanguageUtils.languageMap
|
||||
import org.meshtastic.proto.ClientOnlyProtos.DeviceProfile
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
|
@ -260,7 +267,6 @@ fun SettingsScreen(
|
|||
onNavigate = onNavigate,
|
||||
)
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
|
||||
TitledCard(title = stringResource(Res.string.app_settings), modifier = Modifier.padding(top = 16.dp)) {
|
||||
|
|
@ -470,39 +476,54 @@ private fun AppVersionButton(
|
|||
|
||||
@Composable
|
||||
private fun LanguagePickerDialog(onDismiss: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val choices = remember {
|
||||
context
|
||||
.getLanguageMap()
|
||||
.map { (languageTag, languageName) -> languageName to { LanguageUtils.setAppLocale(languageTag) } }
|
||||
.toMap()
|
||||
SettingsDialog(title = stringResource(Res.string.preferences_language), onDismiss = onDismiss) {
|
||||
languageMap().forEach { (languageTag, languageName) ->
|
||||
ListItem(text = languageName, trailingIcon = null) {
|
||||
LanguageUtils.setAppLocale(languageTag)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MultipleChoiceAlertDialog(
|
||||
title = stringResource(Res.string.preferences_language),
|
||||
message = "",
|
||||
choices = choices,
|
||||
onDismissRequest = onDismiss,
|
||||
)
|
||||
private enum class ThemeOption(val label: StringResource, val mode: Int) {
|
||||
DYNAMIC(label = Res.string.dynamic, mode = MODE_DYNAMIC),
|
||||
LIGHT(label = Res.string.theme_light, mode = AppCompatDelegate.MODE_NIGHT_NO),
|
||||
DARK(label = Res.string.theme_dark, mode = AppCompatDelegate.MODE_NIGHT_YES),
|
||||
SYSTEM(label = Res.string.theme_system, mode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM),
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ThemePickerDialog(onClickTheme: (Int) -> Unit, onDismiss: () -> Unit) {
|
||||
val resources = LocalResources.current
|
||||
val themeMap = remember {
|
||||
mapOf(
|
||||
resources.getString(Res.string.dynamic) to MODE_DYNAMIC,
|
||||
resources.getString(Res.string.theme_light) to AppCompatDelegate.MODE_NIGHT_NO,
|
||||
resources.getString(Res.string.theme_dark) to AppCompatDelegate.MODE_NIGHT_YES,
|
||||
resources.getString(Res.string.theme_system) to AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM,
|
||||
)
|
||||
.mapValues { (_, value) -> { onClickTheme(value) } }
|
||||
SettingsDialog(title = stringResource(Res.string.choose_theme), onDismiss = onDismiss) {
|
||||
ThemeOption.entries.forEach { option ->
|
||||
ListItem(text = stringResource(option.label), trailingIcon = null) {
|
||||
onClickTheme(option.mode)
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun SettingsDialog(title: String, onDismiss: () -> Unit, content: @Composable ColumnScope.() -> Unit) {
|
||||
BasicAlertDialog(onDismissRequest = onDismiss) {
|
||||
Surface(
|
||||
modifier = Modifier.wrapContentWidth().wrapContentHeight(),
|
||||
shape = MaterialTheme.shapes.large,
|
||||
color = AlertDialogDefaults.containerColor,
|
||||
tonalElevation = AlertDialogDefaults.TonalElevation,
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 16.dp, top = 16.dp, end = 16.dp, bottom = 8.dp),
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
|
||||
Column(modifier = Modifier.verticalScroll(rememberScrollState())) { content() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MultipleChoiceAlertDialog(
|
||||
title = stringResource(Res.string.choose_theme),
|
||||
message = "",
|
||||
choices = themeMap,
|
||||
onDismissRequest = onDismiss,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,12 @@
|
|||
|
||||
package org.meshtastic.feature.settings.util
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import com.meshtastic.core.strings.getString
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.strings.Res
|
||||
import org.meshtastic.core.strings.fr_HT
|
||||
import org.meshtastic.core.strings.preferences_system_default
|
||||
|
|
@ -47,33 +49,38 @@ object LanguageUtils {
|
|||
|
||||
/** Using locales_config.xml, maps language tags to their localized language names (e.g.: "en" -> "English") */
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
fun Context.getLanguageMap(): Map<String, String> {
|
||||
val languageTags = buildList {
|
||||
add(SYSTEM_DEFAULT)
|
||||
@Composable
|
||||
fun languageMap(): Map<String, String> {
|
||||
val resources = LocalResources.current
|
||||
val languageTags =
|
||||
remember(resources) {
|
||||
buildList {
|
||||
add(SYSTEM_DEFAULT)
|
||||
|
||||
try {
|
||||
resources.getXml(org.meshtastic.feature.settings.R.xml.locales_config).use { parser ->
|
||||
while (parser.eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (parser.eventType == XmlPullParser.START_TAG && parser.name == "locale") {
|
||||
val languageTag =
|
||||
parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name")
|
||||
languageTag?.let { add(it) }
|
||||
try {
|
||||
resources.getXml(org.meshtastic.feature.settings.R.xml.locales_config).use { parser ->
|
||||
while (parser.eventType != XmlPullParser.END_DOCUMENT) {
|
||||
if (parser.eventType == XmlPullParser.START_TAG && parser.name == "locale") {
|
||||
val languageTag =
|
||||
parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name")
|
||||
languageTag?.let { add(it) }
|
||||
}
|
||||
parser.next()
|
||||
}
|
||||
}
|
||||
parser.next()
|
||||
} catch (e: Exception) {
|
||||
Timber.e("Error parsing locale_config.xml: ${e.message}")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e("Error parsing locale_config.xml: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
return languageTags.associateWith { languageTag ->
|
||||
when (languageTag) {
|
||||
SYSTEM_DEFAULT -> getString(Res.string.preferences_system_default)
|
||||
"fr-HT" -> getString(Res.string.fr_HT)
|
||||
"pt-BR" -> getString(Res.string.pt_BR)
|
||||
"zh-CN" -> getString(Res.string.zh_CN)
|
||||
"zh-TW" -> getString(Res.string.zh_TW)
|
||||
SYSTEM_DEFAULT -> stringResource(Res.string.preferences_system_default)
|
||||
"fr-HT" -> stringResource(Res.string.fr_HT)
|
||||
"pt-BR" -> stringResource(Res.string.pt_BR)
|
||||
"zh-CN" -> stringResource(Res.string.zh_CN)
|
||||
"zh-TW" -> stringResource(Res.string.zh_TW)
|
||||
else -> {
|
||||
Locale.forLanguageTag(languageTag).let { locale ->
|
||||
locale.getDisplayLanguage(locale).replaceFirstChar { char ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue