Add dropdown with auto translate language excludes to app settings

Persist changes to settings

TODO:
Load actually excluded languages
Optimise code
Improve UI
This commit is contained in:
David Kaspar
2025-06-16 15:52:46 +02:00
parent f536abb22a
commit 0495dc88fc
5 changed files with 113 additions and 1 deletions
@@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.R
data class Settings( data class Settings(
val theme: ThemeType = ThemeType.SYSTEM, val theme: ThemeType = ThemeType.SYSTEM,
val preferredLanguage: String? = null, val preferredLanguage: String? = null,
val dontTranslateFrom: Set<String> = emptySet(),
val automaticallyShowImages: ConnectivityType = ConnectivityType.ALWAYS, val automaticallyShowImages: ConnectivityType = ConnectivityType.ALWAYS,
val automaticallyStartPlayback: ConnectivityType = ConnectivityType.ALWAYS, val automaticallyStartPlayback: ConnectivityType = ConnectivityType.ALWAYS,
val automaticallyShowUrlPreview: ConnectivityType = ConnectivityType.ALWAYS, val automaticallyShowUrlPreview: ConnectivityType = ConnectivityType.ALWAYS,
@@ -52,6 +52,7 @@ class SharedPreferencesViewModel : ViewModel() {
sharedPrefs.theme = savedSettings.theme sharedPrefs.theme = savedSettings.theme
sharedPrefs.language = savedSettings.preferredLanguage sharedPrefs.language = savedSettings.preferredLanguage
sharedPrefs.dontTranslateFrom = savedSettings.dontTranslateFrom
sharedPrefs.automaticallyShowImages = savedSettings.automaticallyShowImages sharedPrefs.automaticallyShowImages = savedSettings.automaticallyShowImages
sharedPrefs.automaticallyStartPlayback = savedSettings.automaticallyStartPlayback sharedPrefs.automaticallyStartPlayback = savedSettings.automaticallyStartPlayback
sharedPrefs.automaticallyShowUrlPreview = savedSettings.automaticallyShowUrlPreview sharedPrefs.automaticallyShowUrlPreview = savedSettings.automaticallyShowUrlPreview
@@ -82,6 +83,22 @@ class SharedPreferencesViewModel : ViewModel() {
} }
} }
fun addDontTranslateFrom(languageCode: String) {
val newSet = sharedPrefs.dontTranslateFrom.plus(languageCode)
if (newSet != sharedPrefs.dontTranslateFrom) {
sharedPrefs.dontTranslateFrom = newSet
saveSharedSettings()
}
}
fun removeDontTranslateFrom(languageCode: String) {
val newSet = sharedPrefs.dontTranslateFrom.minus(languageCode)
if (newSet != sharedPrefs.dontTranslateFrom) {
sharedPrefs.dontTranslateFrom = newSet
saveSharedSettings()
}
}
fun updateLanguageInTheUI() { fun updateLanguageInTheUI() {
if (sharedPrefs.language != null) { if (sharedPrefs.language != null) {
viewModelScope.launch(Dispatchers.Main) { viewModelScope.launch(Dispatchers.Main) {
@@ -188,6 +205,7 @@ class SharedPreferencesViewModel : ViewModel() {
Settings( Settings(
sharedPrefs.theme, sharedPrefs.theme,
sharedPrefs.language, sharedPrefs.language,
sharedPrefs.dontTranslateFrom,
sharedPrefs.automaticallyShowImages, sharedPrefs.automaticallyShowImages,
sharedPrefs.automaticallyStartPlayback, sharedPrefs.automaticallyStartPlayback,
sharedPrefs.automaticallyShowUrlPreview, sharedPrefs.automaticallyShowUrlPreview,
@@ -38,7 +38,7 @@ import com.vitorpamplona.amethyst.model.ThemeType
class SharedSettingsState { class SharedSettingsState {
var theme by mutableStateOf(ThemeType.SYSTEM) var theme by mutableStateOf(ThemeType.SYSTEM)
var language by mutableStateOf<String?>(null) var language by mutableStateOf<String?>(null)
var dontTranslateFrom by mutableStateOf<Set<String>>(emptySet())
var automaticallyShowImages by mutableStateOf(ConnectivityType.ALWAYS) var automaticallyShowImages by mutableStateOf(ConnectivityType.ALWAYS)
var automaticallyStartPlayback by mutableStateOf(ConnectivityType.ALWAYS) var automaticallyStartPlayback by mutableStateOf(ConnectivityType.ALWAYS)
var automaticallyShowUrlPreview by mutableStateOf(ConnectivityType.ALWAYS) var automaticallyShowUrlPreview by mutableStateOf(ConnectivityType.ALWAYS)
@@ -32,10 +32,22 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -77,6 +89,7 @@ import kotlinx.collections.immutable.toImmutableMap
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException import org.xmlpull.v1.XmlPullParserException
import java.io.IOException import java.io.IOException
import java.util.Locale as JavaLocale
fun Context.getLocaleListFromXml(): LocaleListCompat { fun Context.getLocaleListFromXml(): LocaleListCompat {
val tagsList = mutableListOf<CharSequence>() val tagsList = mutableListOf<CharSequence>()
@@ -233,6 +246,10 @@ fun SettingsScreen(sharedPreferencesViewModel: SharedPreferencesViewModel) {
Spacer(modifier = HalfVertSpacer) Spacer(modifier = HalfVertSpacer)
DontTranslateFromSetting(sharedPreferencesViewModel, languageEntries)
Spacer(modifier = HalfVertSpacer)
SettingsRow( SettingsRow(
R.string.theme, R.string.theme,
R.string.theme_description, R.string.theme_description,
@@ -322,6 +339,78 @@ fun SettingsScreen(sharedPreferencesViewModel: SharedPreferencesViewModel) {
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DontTranslateFromSetting(
sharedPreferencesViewModel: SharedPreferencesViewModel,
languageEntries: ImmutableMap<String, String>,
) {
var expanded by remember { mutableStateOf(false) }
val selectedLanguages = sharedPreferencesViewModel.sharedPrefs.dontTranslateFrom
Column {
SettingsRow(
name = R.string.dont_translate_from,
description = R.string.dont_translate_from_description,
) {
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = !expanded },
) {
OutlinedTextField(
value = stringRes(R.string.add_a_language),
onValueChange = {},
readOnly = true,
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
modifier = Modifier.menuAnchor(),
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
) {
languageEntries.forEach { (displayName, languageCode) ->
if (!selectedLanguages.contains(languageCode)) {
DropdownMenuItem(
text = { Text(text = displayName) },
onClick = {
sharedPreferencesViewModel.addDontTranslateFrom(languageCode)
expanded = false
},
)
}
}
}
}
}
selectedLanguages.forEach { languageCode ->
val displayName =
languageEntries.entries.find { it.value == languageCode }?.key
?: JavaLocale.forLanguageTag(languageCode).displayName
Row(
verticalAlignment = Alignment.CenterVertically,
modifier =
Modifier
.fillMaxWidth()
.padding(vertical = Size10dp),
) {
Text(
text = displayName,
modifier = Modifier.weight(1f),
)
IconButton(onClick = { sharedPreferencesViewModel.removeDontTranslateFrom(languageCode) }) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = stringRes(R.string.remove),
tint = MaterialTheme.colorScheme.onSurface,
)
}
}
}
}
}
@Composable @Composable
fun SettingsRow( fun SettingsRow(
name: Int, name: Int,
+4
View File
@@ -1178,4 +1178,8 @@
<string name="share_image">Share image…</string> <string name="share_image">Share image…</string>
<string name="search_by_hashtag">Search hashtag: #%1$s</string> <string name="search_by_hashtag">Search hashtag: #%1$s</string>
<string name="dont_translate_from">Don\'t Translate From</string>
<string name="dont_translate_from_description">Languages selected here will not be translated</string>
<string name="add_a_language">Add a language</string>
</resources> </resources>