Skip to content

Commit

Permalink
refactor: language selection
Browse files Browse the repository at this point in the history
fix: amnezia edit bug
closes #425
  • Loading branch information
zaneschepke committed Nov 23, 2024
1 parent a9d5994 commit f79f922
Show file tree
Hide file tree
Showing 14 changed files with 65 additions and 170 deletions.
4 changes: 3 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:theme="@style/Theme.WireguardAutoTunnel">
android:theme="@style/Theme.WireguardAutoTunnel"
android:configChanges="orientation|screenSize|keyboardHidden"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.zaneschepke.wireguardautotunnel

import android.app.Application
import android.content.Context
import android.os.StrictMode
import android.os.StrictMode.ThreadPolicy
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import com.zaneschepke.logcatter.LogReader
import com.zaneschepke.wireguardautotunnel.data.datastore.LocaleStorage
import com.zaneschepke.wireguardautotunnel.data.repository.AppStateRepository
import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
import com.zaneschepke.wireguardautotunnel.module.IoDispatcher
Expand All @@ -22,10 +22,6 @@ import javax.inject.Inject
@HiltAndroidApp
class WireGuardAutoTunnel : Application() {

val localeStorage: LocaleStorage by lazy {
LocaleStorage(this)
}

@Inject
@ApplicationScope
lateinit var applicationScope: CoroutineScope
Expand Down Expand Up @@ -56,6 +52,13 @@ class WireGuardAutoTunnel : Application() {
} else {
Timber.plant(ReleaseTree())
}
applicationScope.launch {
appStateRepository.getLocale()?.let {
val locale = LocaleUtil.getLocaleFromPrefCode(it)
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags(locale)
AppCompatDelegate.setApplicationLocales(appLocale)
}
}
if (!isRunningOnTv()) {
applicationScope.launch(ioDispatcher) {
if (appStateRepository.isLocalLogsEnabled()) {
Expand All @@ -66,10 +69,6 @@ class WireGuardAutoTunnel : Application() {
}
}

override fun attachBaseContext(base: Context) {
super.attachBaseContext(LocaleUtil.getLocalizedContext(base, LocaleStorage(base).getPreferredLocale()))
}

companion object {
lateinit var instance: WireGuardAutoTunnel
private set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class DataStoreManager(
val pinLockEnabled = booleanPreferencesKey("PIN_LOCK_ENABLED")
val tunnelStatsExpanded = booleanPreferencesKey("TUNNEL_STATS_EXPANDED")
val isLocalLogsEnabled = booleanPreferencesKey("LOCAL_LOGS_ENABLED")
val locale = stringPreferencesKey("LOCALE")
val theme = stringPreferencesKey("THEME")
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class GeneralState(
val isPinLockEnabled: Boolean = PIN_LOCK_ENABLED_DEFAULT,
val isTunnelStatsExpanded: Boolean = IS_TUNNEL_STATS_EXPANDED,
val isLocalLogsEnabled: Boolean = IS_LOGS_ENABLED_DEFAULT,
val locale: String? = null,
val theme: Theme = Theme.AUTOMATIC,
) {
companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,9 @@ interface AppStateRepository {

suspend fun setLocalLogsEnabled(enabled: Boolean)

suspend fun setLocale(localeTag: String)

suspend fun getLocale(): String?

val generalStateFlow: Flow<GeneralState>
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ class DataStoreAppStateRepository(
dataStoreManager.saveToDataStore(DataStoreManager.isLocalLogsEnabled, enabled)
}

override suspend fun setLocale(localeTag: String) {
dataStoreManager.saveToDataStore(DataStoreManager.locale, localeTag)
}

override suspend fun getLocale(): String? {
return dataStoreManager.getFromStore(DataStoreManager.locale)
}

override val generalStateFlow: Flow<GeneralState> =
dataStoreManager.preferencesFlow.map { prefs ->
prefs?.let { pref ->
Expand All @@ -93,6 +101,7 @@ class DataStoreAppStateRepository(
?: GeneralState.PIN_LOCK_ENABLED_DEFAULT,
isTunnelStatsExpanded = pref[DataStoreManager.tunnelStatsExpanded] ?: GeneralState.IS_TUNNEL_STATS_EXPANDED,
isLocalLogsEnabled = pref[DataStoreManager.isLocalLogsEnabled] ?: GeneralState.IS_LOGS_ENABLED_DEFAULT,
locale = pref[DataStoreManager.locale],
theme = getTheme(),
)
} catch (e: IllegalArgumentException) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.zaneschepke.wireguardautotunnel.ui

import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wireguard.android.backend.WgQuickBackend
Expand All @@ -15,6 +17,8 @@ import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelState
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarController
import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.LocaleUtil
import com.zaneschepke.wireguardautotunnel.util.LocaleUtil.OPTION_PHONE_LANGUAGE
import com.zaneschepke.wireguardautotunnel.util.StringValue
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
Expand Down Expand Up @@ -147,6 +151,14 @@ constructor(
}
}

fun onLocaleChange(localeTag: String) = viewModelScope.launch {
val locale = LocaleUtil.getLocaleFromPrefCode(localeTag)
val storageLocale = if (localeTag == OPTION_PHONE_LANGUAGE) OPTION_PHONE_LANGUAGE else locale
appDataRepository.appState.setLocale(storageLocale)
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags(locale)
AppCompatDelegate.setApplicationLocales(appLocale)
}

fun onToggleRestartAtBoot() = viewModelScope.launch {
with(uiState.value.settings) {
appDataRepository.settings.save(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.zaneschepke.wireguardautotunnel.ui

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.compose.setContent
Expand Down Expand Up @@ -35,8 +34,6 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
import com.zaneschepke.wireguardautotunnel.data.datastore.LocaleStorage
import com.zaneschepke.wireguardautotunnel.data.repository.AppStateRepository
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavBar
Expand All @@ -59,7 +56,6 @@ import com.zaneschepke.wireguardautotunnel.ui.screens.support.SupportScreen
import com.zaneschepke.wireguardautotunnel.ui.screens.support.logs.LogsScreen
import com.zaneschepke.wireguardautotunnel.ui.theme.WireguardAutoTunnelTheme
import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.LocaleUtil
import com.zaneschepke.wireguardautotunnel.util.extensions.requestAutoTunnelTileServiceUpdate
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
Expand All @@ -68,12 +64,6 @@ import kotlin.system.exitProcess
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

private val localeStorage: LocaleStorage by lazy {
(application as WireGuardAutoTunnel).localeStorage
}

private lateinit var oldPrefLocaleCode: String

@Inject
lateinit var appStateRepository: AppStateRepository

Expand Down Expand Up @@ -185,7 +175,7 @@ class MainActivity : AppCompatActivity() {
AppearanceScreen()
}
composable<Route.Language> {
LanguageScreen(localeStorage)
LanguageScreen(appUiState, viewModel)
}
composable<Route.Display> {
DisplayScreen(appUiState)
Expand Down Expand Up @@ -225,19 +215,4 @@ class MainActivity : AppCompatActivity() {
}
}
}

override fun attachBaseContext(newBase: Context) {
oldPrefLocaleCode = LocaleStorage(newBase).getPreferredLocale()
applyOverrideConfiguration(LocaleUtil.getLocalizedConfiguration(oldPrefLocaleCode))
super.attachBaseContext(newBase)
}

override fun onResume() {
val currentLocaleCode = LocaleStorage(this).getPreferredLocale()
if (oldPrefLocaleCode != currentLocaleCode) {
recreate() // locale is changed, restart the activity to update
oldPrefLocaleCode = currentLocaleCode
}
super.onResume()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.ui.theme.iconSize
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
import kotlin.let

@androidx.compose.runtime.Composable
fun IconSurfaceButton(title: String, onClick: () -> Unit, selected: Boolean, leadingIcon: ImageVector? = null, description: String? = null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ fun ConfigScreen(tunnelId: Int) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
var configType by remember { mutableStateOf<ConfigType?>(null) }
val derivedConfigType = remember {
derivedStateOf<ConfigType> {
configType ?: if (!uiState.hasAmneziaProperties()) ConfigType.WIREGUARD else ConfigType.AMNEZIA
derivedStateOf {
configType ?: if (!uiState.isAmneziaEnabled) ConfigType.WIREGUARD else ConfigType.AMNEZIA
}
}
val saved by viewModel.saved.collectAsStateWithLifecycle(null)
Expand Down Expand Up @@ -181,8 +181,8 @@ fun ConfigScreen(tunnelId: Int) {
)
}
},
) {
Column(Modifier.padding(it)) {
) { padding ->
Column(Modifier.padding(padding)) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
Expand Down Expand Up @@ -243,12 +243,12 @@ fun ConfigScreen(tunnelId: Int) {
.clickable { showAuthPrompt = true },
value = uiState.interfaceProxy.privateKey,
visualTransformation =
if ((tunnelId == Constants.MANUAL_TUNNEL_CONFIG_ID.toInt()) || isAuthenticated) {
if ((tunnelId == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated) {
VisualTransformation.None
} else {
PasswordVisualTransformation()
},
enabled = (tunnelId == Constants.MANUAL_TUNNEL_CONFIG_ID.toInt()) || isAuthenticated,
enabled = (tunnelId == Constants.MANUAL_TUNNEL_CONFIG_ID) || isAuthenticated,
onValueChange = { value -> viewModel.onPrivateKeyChange(value) },
trailingIcon = {
IconButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ data class ConfigUiState(
var tunnelName: String = "",
val isAmneziaEnabled: Boolean = false,
) {
fun hasAmneziaProperties(): Boolean {
return this.interfaceProxy.junkPacketCount != ""
}
companion object {
fun from(config: Config): ConfigUiState {
val proxyPeers = config.peers.map { PeerProxy.from(it) }
Expand Down Expand Up @@ -77,6 +74,7 @@ data class ConfigUiState(
return from(config).copy(
tunnelName = tunnel.name,
tunnel = tunnel,
isAmneziaEnabled = config.`interface`.junkPacketCount.isPresent,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,27 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.data.datastore.LocaleStorage
import com.zaneschepke.wireguardautotunnel.ui.Route
import com.zaneschepke.wireguardautotunnel.ui.AppUiState
import com.zaneschepke.wireguardautotunnel.ui.AppViewModel
import com.zaneschepke.wireguardautotunnel.ui.common.SelectedLabel
import com.zaneschepke.wireguardautotunnel.ui.common.button.SelectionItemButton
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.TopNavBar
import com.zaneschepke.wireguardautotunnel.util.LocaleUtil
import com.zaneschepke.wireguardautotunnel.util.extensions.navigateAndForget
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
import com.zaneschepke.wireguardautotunnel.util.extensions.scaledWidth
import timber.log.Timber
import java.text.Collator
import java.util.Locale

@Composable
fun LanguageScreen(localeStorage: LocaleStorage) {
val navController = LocalNavController.current

val context = LocalContext.current

fun LanguageScreen(appUiState: AppUiState, appViewModel: AppViewModel) {
val collator = Collator.getInstance(Locale.getDefault())

val currentLocale = remember { mutableStateOf(LocaleUtil.OPTION_PHONE_LANGUAGE) }

val locales = LocaleUtil.supportedLocales.map {
val tag = it.replace("_", "-")
Locale.forLanguageTag(tag)
Expand All @@ -54,39 +42,28 @@ fun LanguageScreen(localeStorage: LocaleStorage) {
locales.sortedWith(compareBy(collator) { it.getDisplayName(it) }).toList()
}

LaunchedEffect(Unit) {
currentLocale.value = localeStorage.getPreferredLocale()
}

fun onChangeLocale(locale: String) {
Timber.d("Setting preferred locale: $locale")
localeStorage.setPreferredLocale(locale)
LocaleUtil.applyLocalizedContext(context, locale)
navController.navigateAndForget(Route.Main)
}

Scaffold(
topBar = {
TopNavBar(stringResource(R.string.language))
},
) {
) { padding ->
LazyColumn(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
modifier =
Modifier
.fillMaxSize().padding(it)
.fillMaxSize().padding(padding)
.padding(horizontal = 24.dp.scaledWidth()).windowInsetsPadding(WindowInsets.navigationBars),
) {
item {
Box(modifier = Modifier.padding(top = 24.dp.scaledHeight())) {
SelectionItemButton(
buttonText = stringResource(R.string.automatic),
onClick = {
onChangeLocale(LocaleUtil.OPTION_PHONE_LANGUAGE)
appViewModel.onLocaleChange(LocaleUtil.OPTION_PHONE_LANGUAGE)
},
trailing = {
if (currentLocale.value == LocaleUtil.OPTION_PHONE_LANGUAGE) {
if (appUiState.generalState.locale == LocaleUtil.OPTION_PHONE_LANGUAGE) {
SelectedLabel()
}
},
Expand All @@ -96,13 +73,18 @@ fun LanguageScreen(localeStorage: LocaleStorage) {
}
items(sortedLocales, key = { it }) { locale ->
SelectionItemButton(
buttonText = locale.getDisplayLanguage(locale).capitalize(locale) +
if (locale.toLanguageTag().contains("-")) " (${locale.getDisplayCountry(locale).capitalize(locale)})" else "",
buttonText = locale.getDisplayLanguage(locale).replaceFirstChar { if (it.isLowerCase()) it.titlecase(locale) else it.toString() } +
if (locale.toLanguageTag().contains("-")) {
" (${locale.getDisplayCountry(locale)
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(locale) else it.toString() }})"
} else {
""
},
onClick = {
onChangeLocale(locale.toLanguageTag())
appViewModel.onLocaleChange(locale.toLanguageTag())
},
trailing = {
if (locale.toLanguageTag() == currentLocale.value) {
if (locale.toLanguageTag() == appUiState.generalState.locale) {
SelectedLabel()
}
},
Expand Down
Loading

0 comments on commit f79f922

Please sign in to comment.