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/app | |
| parent | b905cd0204ee6481375b957ef0ef7516016f0345 (diff) | |
| download | mullvadvpn-7e2015962384cd87af823570c9dab7f3fcaf49b7.tar.xz mullvadvpn-7e2015962384cd87af823570c9dab7f3fcaf49b7.zip | |
Add support for translated location names
Diffstat (limited to 'android/app')
7 files changed, 70 insertions, 7 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index ecde2e9132..f8c92c9849 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -337,6 +337,7 @@ dependencies { implementation(libs.androidx.lifecycle.viewmodel) implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.arrow) + implementation(libs.arrow.optics) implementation(libs.arrow.resilience) implementation(libs.compose.constrainlayout) implementation(libs.compose.foundation) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9247112466..28d6a17ed1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -106,5 +106,11 @@ <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider> + <receiver android:name=".receiver.LocaleChangedBroadcastReceiver" + android:exported="false"> + <intent-filter> + <action android:name="android.intent.action.LOCALE_CHANGED" /> + </intent-filter> + </receiver> </application> </manifest> diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt index 6af9ff57cb..e4722094f9 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt @@ -11,6 +11,8 @@ import net.mullvad.mullvadvpn.lib.model.BuildVersion import net.mullvad.mullvadvpn.lib.shared.AccountRepository import net.mullvad.mullvadvpn.lib.shared.ConnectionProxy import net.mullvad.mullvadvpn.lib.shared.DeviceRepository +import net.mullvad.mullvadvpn.lib.shared.LocaleRepository +import net.mullvad.mullvadvpn.lib.shared.RelayLocationTranslationRepository import net.mullvad.mullvadvpn.lib.shared.VpnPermissionRepository import org.koin.android.ext.koin.androidContext import org.koin.core.qualifier.named @@ -32,5 +34,7 @@ val appModule = module { single { AccountRepository(get(), get(), MainScope()) } single { DeviceRepository(get()) } single { VpnPermissionRepository(androidContext()) } - single { ConnectionProxy(get(), get()) } + single { ConnectionProxy(get(), get(), get()) } + single { LocaleRepository(get()) } + single { RelayLocationTranslationRepository(get(), get(), MainScope()) } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt index 6494cbb167..929d1e3b99 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt @@ -117,7 +117,7 @@ val uiModule = module { single { MullvadProblemReport(get()) } single { RelayOverridesRepository(get()) } single { CustomListsRepository(get()) } - single { RelayListRepository(get()) } + single { RelayListRepository(get(), get()) } single { RelayListFilterRepository(get()) } single { VoucherRepository(get(), get()) } single { SplitTunnelingRepository(get()) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/LocaleChangedBroadcastReceiver.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/LocaleChangedBroadcastReceiver.kt new file mode 100644 index 0000000000..8969ffd14c --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/LocaleChangedBroadcastReceiver.kt @@ -0,0 +1,18 @@ +package net.mullvad.mullvadvpn.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import net.mullvad.mullvadvpn.lib.shared.LocaleRepository +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +class LocaleChangedBroadcastReceiver : BroadcastReceiver(), KoinComponent { + private val localeRepository by inject<LocaleRepository>() + + override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action == Intent.ACTION_LOCALE_CHANGED) { + localeRepository.refreshLocale() + } + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt index ea017339f6..6d308e3b26 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt @@ -55,3 +55,6 @@ fun List<RelayItem.Location.Country>.getRelayItemsByCodes( ): List<RelayItem.Location> = this.filter { codes.contains(it.id) } + this.flatMap { it.descendants() }.filter { codes.contains(it.id) } + +fun <T : RelayItem> List<T>.sortedByName() = + this.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt index ce41b57c4c..69a35c406b 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt @@ -1,11 +1,15 @@ package net.mullvad.mullvadvpn.repository +import arrow.optics.Every +import arrow.optics.copy +import arrow.optics.dsl.every import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -17,18 +21,45 @@ import net.mullvad.mullvadvpn.lib.model.RelayItem import net.mullvad.mullvadvpn.lib.model.RelayItemId import net.mullvad.mullvadvpn.lib.model.WireguardConstraints import net.mullvad.mullvadvpn.lib.model.WireguardEndpointData +import net.mullvad.mullvadvpn.lib.model.cities +import net.mullvad.mullvadvpn.lib.model.name +import net.mullvad.mullvadvpn.lib.shared.RelayLocationTranslationRepository import net.mullvad.mullvadvpn.relaylist.findByGeoLocationId +import net.mullvad.mullvadvpn.relaylist.sortedByName class RelayListRepository( private val managementService: ManagementService, + private val translationRepository: RelayLocationTranslationRepository, dispatcher: CoroutineDispatcher = Dispatchers.IO ) { val relayList: StateFlow<List<RelayItem.Location.Country>> = - managementService.relayCountries.stateIn( - CoroutineScope(dispatcher), - SharingStarted.WhileSubscribed(), - emptyList() - ) + combine(managementService.relayCountries, translationRepository.translations) { + countries, + translations -> + countries.translateRelays(translations) + } + .stateIn(CoroutineScope(dispatcher), SharingStarted.WhileSubscribed(), emptyList()) + + private fun List<RelayItem.Location.Country>.translateRelays( + translations: Map<String, String> + ): List<RelayItem.Location.Country> { + if (translations.isEmpty()) { + return this + } + + return Every.list<RelayItem.Location.Country>() + .modify(this) { + it.copy { + RelayItem.Location.Country.name set translations.getOrDefault(it.name, it.name) + RelayItem.Location.Country.cities.every(Every.list()).name transform + { cityName -> + translations.getOrDefault(cityName, cityName) + } + RelayItem.Location.Country.cities transform { cities -> cities.sortedByName() } + } + } + .sortedByName() + } val wireguardEndpointData: StateFlow<WireguardEndpointData> = managementService.wireguardEndpointData.stateIn( |
