diff options
| author | David Göransson <david.goransson@mullvad.net> | 2024-08-07 18:49:46 +0200 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2024-08-21 11:52:30 +0200 |
| commit | 7e2015962384cd87af823570c9dab7f3fcaf49b7 (patch) | |
| tree | e8d81b1e8c3dca781a3e952ba406cfef26f7d32f /android/lib/shared/src | |
| parent | b905cd0204ee6481375b957ef0ef7516016f0345 (diff) | |
| download | mullvadvpn-7e2015962384cd87af823570c9dab7f3fcaf49b7.tar.xz mullvadvpn-7e2015962384cd87af823570c9dab7f3fcaf49b7.zip | |
Add support for translated location names
Diffstat (limited to 'android/lib/shared/src')
3 files changed, 105 insertions, 1 deletions
diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt index 6ea373e426..6725865905 100644 --- a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt +++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt @@ -3,14 +3,38 @@ package net.mullvad.mullvadvpn.lib.shared import arrow.core.Either import arrow.core.raise.either import arrow.core.raise.ensure +import kotlinx.coroutines.flow.combine +import mullvad_daemon.management_interface.location import net.mullvad.mullvadvpn.lib.daemon.grpc.ManagementService import net.mullvad.mullvadvpn.lib.model.ConnectError +import net.mullvad.mullvadvpn.lib.model.GeoIpLocation +import net.mullvad.mullvadvpn.lib.model.TunnelState +import net.mullvad.mullvadvpn.lib.model.location class ConnectionProxy( private val managementService: ManagementService, + private val translationRepository: RelayLocationTranslationRepository, private val vpnPermissionRepository: VpnPermissionRepository ) { - val tunnelState = managementService.tunnelState + val tunnelState = + combine(managementService.tunnelState, translationRepository.translations) { + tunnelState, + translations -> + tunnelState.translateLocations(translations) + } + + private fun TunnelState.translateLocations(translations: Map<String, String>): TunnelState { + return when (this) { + is TunnelState.Connecting -> copy(location = location?.translate(translations)) + is TunnelState.Disconnected -> copy(location = location?.translate(translations)) + is TunnelState.Disconnecting -> this + is TunnelState.Error -> this + is TunnelState.Connected -> copy(location = location?.translate(translations)) + } + } + + private fun GeoIpLocation.translate(translations: Map<String, String>): GeoIpLocation = + copy(city = translations[city] ?: city, country = translations[country] ?: country) suspend fun connect(): Either<ConnectError, Boolean> = either { ensure(vpnPermissionRepository.hasVpnPermission()) { ConnectError.NoVpnPermission } diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/LocaleRepository.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/LocaleRepository.kt new file mode 100644 index 0000000000..4e5628d214 --- /dev/null +++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/LocaleRepository.kt @@ -0,0 +1,19 @@ +package net.mullvad.mullvadvpn.lib.shared + +import android.content.res.Resources +import co.touchlab.kermit.Logger +import java.util.Locale +import kotlin.also +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +class LocaleRepository(val resources: Resources) { + private val _currentLocale = MutableStateFlow(getLocale()) + val currentLocale: StateFlow<Locale?> = _currentLocale + + private fun getLocale(): Locale? = resources.configuration.locales.get(0) + + fun refreshLocale() { + _currentLocale.value = getLocale().also { Logger.d("New locale: $it") } + } +} diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/RelayLocationTranslationRepository.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/RelayLocationTranslationRepository.kt new file mode 100644 index 0000000000..edaa0c1ebc --- /dev/null +++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/RelayLocationTranslationRepository.kt @@ -0,0 +1,61 @@ +package net.mullvad.mullvadvpn.lib.shared + +import android.content.Context +import android.content.res.XmlResourceParser +import co.touchlab.kermit.Logger +import java.util.Locale +import kotlin.collections.set +import kotlin.collections.toMap +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.withContext + +typealias Translations = Map<String, String> + +class RelayLocationTranslationRepository( + val context: Context, + val localeRepository: LocaleRepository, + externalScope: CoroutineScope = MainScope(), + val dispatcher: CoroutineDispatcher = Dispatchers.IO +) { + val translations: StateFlow<Translations> = + localeRepository.currentLocale + .filterNotNull() + .map { loadTranslations(it) } + .stateIn(externalScope, SharingStarted.Eagerly, emptyMap()) + + private suspend fun loadTranslations(locale: Locale): Translations = + withContext(dispatcher) { + Logger.d("Updating translations based on $locale") + if (locale.language == DEFAULT_LANGUAGE) emptyMap() + else { + // Load current translations + val xml = context.resources.getXml(R.xml.relay_locations) + xml.loadRelayTranslation() + } + } + + private fun XmlResourceParser.loadRelayTranslation(): Map<String, String> { + val translation = mutableMapOf<String, String>() + while (this.eventType != XmlResourceParser.END_DOCUMENT) { + if (this.eventType == XmlResourceParser.START_TAG && this.name == "string") { + val key = this.getAttributeValue(null, "name") + val value = this.nextText() + translation[key] = value + } + this.next() + } + return translation.toMap() + } + + companion object { + private const val DEFAULT_LANGUAGE = "en" + } +} |
