From 56deb1237384cbc65153e50aecf8b2cb96f66afd Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Thu, 10 Aug 2023 20:07:05 +0200 Subject: [PATCH] feat: Add in-app language picker --- .../main/java/app/myzel394/alibi/Constants.kt | 3 + .../atoms/InAppLanguagePicker.kt | 101 ++++++++++++++++++ .../alibi/ui/components/atoms/SettingsTile.kt | 4 + .../alibi/ui/screens/SettingsScreen.kt | 2 + app/src/main/res/values/strings.xml | 2 + 5 files changed, 112 insertions(+) create mode 100644 app/src/main/java/app/myzel394/alibi/Constants.kt create mode 100644 app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/InAppLanguagePicker.kt diff --git a/app/src/main/java/app/myzel394/alibi/Constants.kt b/app/src/main/java/app/myzel394/alibi/Constants.kt new file mode 100644 index 0000000..88c029e --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/Constants.kt @@ -0,0 +1,3 @@ +package app.myzel394.alibi + +val SUPPORTED_LOCALES = arrayOf("en-US", "zh-CN") \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/InAppLanguagePicker.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/InAppLanguagePicker.kt new file mode 100644 index 0000000..c7d4714 --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/atoms/InAppLanguagePicker.kt @@ -0,0 +1,101 @@ +package app.myzel394.alibi.ui.components.SettingsScreen.atoms + +import androidx.appcompat.app.AppCompatDelegate +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AudioFile +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material.icons.filled.ChevronRight +import androidx.compose.material.icons.filled.Circle +import androidx.compose.material.icons.filled.Translate +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.core.os.LocaleListCompat +import app.myzel394.alibi.R +import app.myzel394.alibi.SUPPORTED_LOCALES +import app.myzel394.alibi.db.AudioRecorderSettings +import app.myzel394.alibi.ui.components.atoms.SettingsTile +import app.myzel394.alibi.ui.utils.IconResource +import com.maxkeppeker.sheets.core.models.base.ButtonStyle +import com.maxkeppeker.sheets.core.models.base.Header +import com.maxkeppeker.sheets.core.models.base.IconSource +import com.maxkeppeker.sheets.core.models.base.SelectionButton +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.list.ListDialog +import com.maxkeppeler.sheets.list.models.ListOption +import com.maxkeppeler.sheets.list.models.ListSelection +import java.util.Locale + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun InAppLanguagePicker() { + val showDialog = rememberUseCaseState() + val locales = Locale.getAvailableLocales().filter { + val locale = it.language + + (if (it.country.isNotBlank()) "-${it.country}" else "") + + (if (it.variant.isNotBlank()) "-${it.variant}" else "") + + SUPPORTED_LOCALES.contains(locale) + } + + ListDialog( + state = showDialog, + header = Header.Default( + title = stringResource(R.string.ui_settings_language_title), + icon = IconSource( + painter = IconResource.fromImageVector(Icons.Default.Translate).asPainterResource(), + contentDescription = null, + ) + ), + selection = ListSelection.Single( + showRadioButtons = true, + options = IntRange(0, locales.size - 1).map {index -> + val locale = locales[index]!! + + ListOption( + titleText = locale.displayName, + subtitleText = locale.getDisplayName(Locale.ENGLISH), + ) + }.toList(), + positiveButton = SelectionButton( + icon = IconSource( + painter = IconResource.fromImageVector(Icons.Default.CheckCircle).asPainterResource(), + contentDescription = null, + ), + text = stringResource(android.R.string.ok), + type = ButtonStyle.TEXT, + ) + ) {index, _ -> + AppCompatDelegate.setApplicationLocales( + LocaleListCompat.forLanguageTags( + locales[index]!!.toLanguageTag(), + ), + ) + }, + ) + SettingsTile( + firstModifier = Modifier + .fillMaxHeight() + .clickable { + showDialog.show() + }, + title = stringResource(R.string.ui_settings_language_title), + leading = { + Icon( + Icons.Default.Translate, + contentDescription = null, + ) + }, + ) +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/atoms/SettingsTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/atoms/SettingsTile.kt index 7444d45..729995f 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/atoms/SettingsTile.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/atoms/SettingsTile.kt @@ -17,6 +17,8 @@ import androidx.compose.ui.unit.dp @Composable fun SettingsTile( + modifier: Modifier = Modifier, + firstModifier: Modifier = Modifier, title: String, description: String? = null, leading: @Composable () -> Unit = {}, @@ -27,8 +29,10 @@ fun SettingsTile( Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier + .then(firstModifier) .fillMaxWidth() .padding(16.dp) + .then(modifier), ) { leading() Spacer(modifier = Modifier.width(16.dp)) diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt index 463c4b7..a1db378 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt @@ -38,6 +38,7 @@ import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.ui.components.SettingsScreen.atoms.BitrateTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.EncoderTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ForceExactMaxDurationTile +import app.myzel394.alibi.ui.components.SettingsScreen.atoms.InAppLanguagePicker import app.myzel394.alibi.ui.components.SettingsScreen.atoms.IntervalDurationTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.MaxDurationTile import app.myzel394.alibi.ui.components.SettingsScreen.atoms.OutputFormatTile @@ -120,6 +121,7 @@ fun SettingsScreen( MaxDurationTile() IntervalDurationTile() ForceExactMaxDurationTile() + InAppLanguagePicker() AnimatedVisibility(visible = settings.showAdvancedSettings) { Column { Divider( diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 303afad..15ab739 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,4 +62,6 @@ Audio Recording has been paused An error occured Alibi encountered an error during recording. Would you like to try saving the recording? + Language + Change \ No newline at end of file