Refactor: Move language setting from per-account to global settings

This change moves the language preference from being an individual account setting to a global application-wide setting.

The `language` property has been removed from the `Account` model and added to the `AmberSettings` model. All related logic for saving, loading, and applying the language preference has been updated to reflect this new global scope.

The application now loads and applies the language setting on startup.
This commit is contained in:
greenart7c3
2025-10-17 07:07:17 -03:00
parent 8f8a8dbc1f
commit b465745d1a
7 changed files with 15 additions and 17 deletions
@@ -4,7 +4,9 @@ import android.app.Application
import android.content.Intent
import android.net.NetworkCapabilities
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import androidx.compose.runtime.mutableStateOf
import androidx.core.os.LocaleListCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
@@ -246,6 +248,11 @@ class Amber : Application(), LifecycleObserver {
LocalPreferences.switchToAccount(this@Amber, LocalPreferences.allSavedAccounts(this@Amber).first().npub)
}
settings = LocalPreferences.loadSettingsFromEncryptedStorage()
settings.language?.let {
AppCompatDelegate.setApplicationLocales(
LocaleListCompat.forLanguageTags(it),
)
}
LocalPreferences.reloadApp()
fixRejectedPermissions()
fixAcceptedPermissions()
@@ -32,7 +32,6 @@ private enum class PrefKeys(val key: String) {
NOSTR_PRIVKEY("nostr_privkey"),
NOSTR_PUBKEY("nostr_pubkey"),
ACCOUNT_NAME("account_name"),
LANGUAGE_PREFS("languagePreferences"),
SIGN_POLICY("default_sign_policy"),
SEED_WORDS("seed_words"),
PROFILE_URL("profile_url"),
@@ -56,6 +55,7 @@ private enum class SettingsKeys(val key: String) {
PROXY_PORT("proxy_port"),
BATERRY_OPTIMIZATION("battery_optimization"),
KILL_SWITCH("kill_switch"),
LANGUAGE_PREFS("languagePreferences"),
}
@Immutable
@@ -139,6 +139,7 @@ object LocalPreferences {
putBoolean(SettingsKeys.USE_PROXY.key, settings.useProxy)
putInt(SettingsKeys.PROXY_PORT.key, settings.proxyPort)
putBoolean(SettingsKeys.KILL_SWITCH.key, settings.killSwitch.value)
putString(SettingsKeys.LANGUAGE_PREFS.key, settings.language)
}
}
}
@@ -220,6 +221,7 @@ object LocalPreferences {
useProxy = getBoolean(SettingsKeys.USE_PROXY.key, false),
proxyPort = getInt(SettingsKeys.PROXY_PORT.key, 9050),
killSwitch = MutableStateFlow(getBoolean(SettingsKeys.KILL_SWITCH.key, false)),
language = getString(SettingsKeys.LANGUAGE_PREFS.key, null),
)
}
}
@@ -406,7 +408,6 @@ object LocalPreferences {
account.signer.keyPair.pubKey.let { putString(PrefKeys.NOSTR_PUBKEY.key, it.toHexKey()) }
putString(PrefKeys.ACCOUNT_NAME.key, account.name.value)
putString(PrefKeys.PROFILE_URL.key, account.picture.value)
putString(PrefKeys.LANGUAGE_PREFS.key, account.language)
putInt(PrefKeys.SIGN_POLICY.key, account.signPolicy)
putBoolean(PrefKeys.DID_BACKUP.key, account.didBackup)
}
@@ -498,7 +499,6 @@ object LocalPreferences {
val privKey = DataStoreAccess.getEncryptedKey(context, npub, DataStoreAccess.NOSTR_PRIVKEY)
val name = getString(PrefKeys.ACCOUNT_NAME.key, "") ?: ""
val picture = getString(PrefKeys.PROFILE_URL.key, "") ?: ""
val language = getString(PrefKeys.LANGUAGE_PREFS.key, null)
val signPolicy = getInt(PrefKeys.SIGN_POLICY.key, 1)
val savedSeedWords = DataStoreAccess.getEncryptedKey(context, npub, DataStoreAccess.SEED_WORDS)
val seedWords = savedSeedWords?.split(" ")?.toSet() ?: emptySet()
@@ -509,7 +509,6 @@ object LocalPreferences {
signer = NostrSignerInternal(KeyPair(privKey = privKey?.hexToByteArray(), pubKey = pubKey.hexToByteArray())),
name = MutableStateFlow(name),
picture = MutableStateFlow(picture),
language = language,
signPolicy = signPolicy,
seedWords = seedWords,
didBackup = didBackup,
@@ -16,7 +16,6 @@ class Account(
val signer: NostrSignerInternal,
val name: MutableStateFlow<String>,
val picture: MutableStateFlow<String>,
var language: String?,
var signPolicy: Int,
var seedWords: Set<String>,
var didBackup: Boolean,
@@ -27,4 +27,5 @@ data class AmberSettings(
val useProxy: Boolean = false,
val proxyPort: Int = 9050,
val killSwitch: MutableStateFlow<Boolean> = MutableStateFlow(false),
var language: String? = null,
)
@@ -163,7 +163,6 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
signer = NostrSignerInternal(KeyPair(Hex.decode(newKey))),
name = MutableStateFlow(""),
picture = MutableStateFlow(""),
language = null,
signPolicy = signPolicy,
seedWords = emptySet(),
didBackup = true,
@@ -173,7 +172,6 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
signer = NostrSignerInternal(KeyPair(privKey = key.bechToBytes())),
name = MutableStateFlow(""),
picture = MutableStateFlow(""),
language = null,
signPolicy = signPolicy,
seedWords = emptySet(),
didBackup = true,
@@ -184,7 +182,6 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
signer = NostrSignerInternal(keyPair),
name = MutableStateFlow(""),
picture = MutableStateFlow(""),
language = null,
signPolicy = signPolicy,
seedWords = key.split(" ").toSet(),
didBackup = true,
@@ -194,7 +191,6 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
signer = NostrSignerInternal(KeyPair(Hex.decode(key))),
name = MutableStateFlow(""),
picture = MutableStateFlow(""),
language = null,
signPolicy = signPolicy,
seedWords = emptySet(),
didBackup = true,
@@ -226,7 +222,6 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
NostrSignerInternal(keyPair),
name = MutableStateFlow(name),
picture = MutableStateFlow(""),
language = null,
signPolicy = signPolicy,
seedWords = seedWords,
didBackup = false,
@@ -14,7 +14,6 @@ import androidx.core.os.LocaleListCompat
import com.greenart7c3.nostrsigner.Amber
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.models.Account
import com.greenart7c3.nostrsigner.ui.components.TitleExplainer
import java.io.IOException
import kotlinx.collections.immutable.ImmutableMap
@@ -27,12 +26,11 @@ import org.xmlpull.v1.XmlPullParserException
@Composable
fun LanguageScreen(
modifier: Modifier = Modifier,
account: Account,
) {
val context = LocalContext.current
val languageEntries = remember { context.getLangPreferenceDropdownEntries() }
val languageList = remember { languageEntries.keys.map { TitleExplainer(it) }.toImmutableList() }
val languageIndex = getLanguageIndex(languageEntries, account.language)
val languageIndex = getLanguageIndex(languageEntries, Amber.instance.settings.language)
Column(
modifier = modifier
@@ -49,10 +47,10 @@ fun LanguageScreen(
languageIndex,
) {
Amber.instance.applicationIOScope.launch {
account.language = languageEntries[languageList[it].title]
LocalPreferences.saveToEncryptedStorage(context, account)
Amber.instance.settings.language = languageEntries[languageList[it].title]
LocalPreferences.saveSettingsToEncryptedStorage(Amber.instance.settings)
AppCompatDelegate.setApplicationLocales(
LocaleListCompat.forLanguageTags(account.language),
LocaleListCompat.forLanguageTags(Amber.instance.settings.language),
)
}
}
@@ -501,7 +501,6 @@ fun MainScreen(
.padding(padding)
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account = account,
)
},
)