summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2024-09-06 15:26:01 +0200
committerAlbin <albin@mullvad.net>2024-09-06 15:26:01 +0200
commit17788c6ab46aef57eddc87f7eefd5a1f65a4683c (patch)
treee5b0efdd66bdc77ee6b4ff16d3a23db854f5a213 /android
parentb0b7db0926b7e78f1e320e2cf206c45989a02c93 (diff)
parentfca422d5f58e66ad8fc364b2ae3d393d3c9ec5e3 (diff)
downloadmullvadvpn-17788c6ab46aef57eddc87f7eefd5a1f65a4683c.tar.xz
mullvadvpn-17788c6ab46aef57eddc87f7eefd5a1f65a4683c.zip
Merge branch 'add-android-daita-droid-1192'
Diffstat (limited to 'android')
-rw-r--r--android/app/build.gradle.kts10
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/data/DummyRelayItems.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/FilterChip.kt37
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationInfo.kt50
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaConfirmationDialog.kt101
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaInfoDialog.kt35
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayItemPreviewData.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt7
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt1
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt34
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt31
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt16
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt9
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt9
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt3
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/CustomListLocationsViewModelTest.kt1
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt7
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt7
-rw-r--r--android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt10
-rw-r--r--android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt14
-rw-r--r--android/lib/daemon-grpc/src/test/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparatorTest.kt20
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt2
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItem.kt1
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetDaitaSettingsError.kt5
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt2
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelEndpoint.kt1
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelState.kt8
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardRelayEndpointData.kt3
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardTunnelOptions.kt6
-rw-r--r--android/lib/resource/src/main/res/values-da/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-de/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-es/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-fi/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-fr/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-it/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-ja/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-ko/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-my/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-nb/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-nl/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-pl/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-pt/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-ru/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-sv/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-th/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-tr/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-zh-rCN/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values-zh-rTW/strings.xml5
-rw-r--r--android/lib/resource/src/main/res/values/strings.xml6
-rw-r--r--android/lib/resource/src/main/res/values/strings_non_translatable.xml2
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/FileResourceExtractor.kt23
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt18
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ContextExtensions.kt23
59 files changed, 562 insertions, 84 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index f8c92c9849..f5e4c22d6b 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -20,6 +20,7 @@ plugins {
val repoRootPath = rootProject.projectDir.absoluteFile.parentFile.absolutePath
val extraAssetsDirectory = "${project.buildDir}/extraAssets"
val relayListPath = "$extraAssetsDirectory/relays.json"
+val maybenotMachinesDirectory = "$extraAssetsDirectory/maybenot_machines"
val defaultChangelogAssetsDirectory = "$repoRootPath/android/src/main/play/release-notes/"
val extraJniDirectory = "${project.buildDir}/extraJni"
@@ -239,6 +240,7 @@ android {
// Ensure all relevant assemble tasks depend on our ensure tasks.
tasks.get("assemble$capitalizedVariantName").apply {
dependsOn(tasks.get("ensureRelayListExist"))
+ dependsOn(tasks.get("ensureMaybenotMachinesExist"))
dependsOn(tasks.get("ensureJniDirectoryExist"))
dependsOn(tasks.get("ensureValidVersionCode"))
}
@@ -283,6 +285,14 @@ tasks.register("ensureRelayListExist") {
}
}
+tasks.register("ensureMaybenotMachinesExist") {
+ doLast {
+ if (!file(maybenotMachinesDirectory).exists()) {
+ throw GradleException("Missing maybenot machines: $maybenotMachinesDirectory")
+ }
+ }
+}
+
tasks.register("ensureJniDirectoryExist") {
doLast {
if (!file(extraJniDirectory).exists()) {
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/data/DummyRelayItems.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/data/DummyRelayItems.kt
index 3cea5e5c68..a073bc60ff 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/data/DummyRelayItems.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/data/DummyRelayItems.kt
@@ -22,6 +22,7 @@ private val DUMMY_RELAY_1 =
active = true,
provider =
Provider(providerId = ProviderId("PROVIDER RENTED"), ownership = Ownership.Rented),
+ daita = false,
)
private val DUMMY_RELAY_2 =
RelayItem.Location.Relay(
@@ -33,6 +34,7 @@ private val DUMMY_RELAY_2 =
active = true,
provider =
Provider(providerId = ProviderId("PROVIDER OWNED"), ownership = Ownership.MullvadOwned),
+ daita = false,
)
private val DUMMY_RELAY_CITY_1 =
RelayItem.Location.City(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt
index a94846dacf..d3e233c67b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt
@@ -57,6 +57,7 @@ fun FilterRow(
is FilterChip.Ownership ->
OwnershipFilterChip(it.ownership, onRemoveOwnershipFilter)
is FilterChip.Provider -> ProviderFilterChip(it.count, onRemoveProviderFilter)
+ is FilterChip.Daita -> DaitaFilterChip()
}
}
}
@@ -67,6 +68,7 @@ fun ProviderFilterChip(providers: Int, onRemoveClick: () -> Unit) {
MullvadFilterChip(
text = stringResource(id = R.string.number_of_providers, providers),
onRemoveClick = onRemoveClick,
+ enabled = true,
)
}
@@ -75,6 +77,16 @@ fun OwnershipFilterChip(ownership: Ownership, onRemoveClick: () -> Unit) {
MullvadFilterChip(
text = stringResource(ownership.stringResources()),
onRemoveClick = onRemoveClick,
+ enabled = true,
+ )
+}
+
+@Composable
+fun DaitaFilterChip() {
+ MullvadFilterChip(
+ text = stringResource(id = R.string.setting_chip, stringResource(id = R.string.daita)),
+ onRemoveClick = {},
+ enabled = false,
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/FilterChip.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/FilterChip.kt
index 4761c15c9d..94e1c7853a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/FilterChip.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/FilterChip.kt
@@ -19,11 +19,24 @@ import net.mullvad.mullvadvpn.lib.theme.shape.chipShape
@Preview
@Composable
-private fun PreviewMullvadFilterChip() {
+private fun PreviewEnabledMullvadFilterChip() {
AppTheme {
MullvadFilterChip(
text = stringResource(id = R.string.number_of_providers),
onRemoveClick = {},
+ enabled = true,
+ )
+ }
+}
+
+@Preview
+@Composable
+private fun PreviewDisabledMullvadFilterChip() {
+ AppTheme {
+ MullvadFilterChip(
+ text = stringResource(id = R.string.number_of_providers),
+ onRemoveClick = {},
+ enabled = false,
)
}
}
@@ -36,30 +49,38 @@ fun MullvadFilterChip(
iconColor: Color = MaterialTheme.colorScheme.onPrimary,
text: String,
onRemoveClick: () -> Unit,
+ enabled: Boolean,
) {
InputChip(
+ enabled = enabled,
shape = MaterialTheme.shapes.chipShape,
colors =
FilterChipDefaults.filterChipColors(
containerColor = containerColor,
+ disabledContainerColor = containerColor,
labelColor = labelColor,
+ disabledLabelColor = labelColor,
iconColor = iconColor,
),
border =
FilterChipDefaults.filterChipBorder(
borderColor = borderColor,
+ disabledBorderColor = borderColor,
enabled = true,
selected = false,
),
selected = false,
onClick = onRemoveClick,
label = { Text(text = text, style = MaterialTheme.typography.labelMedium) },
- trailingIcon = {
- Icon(
- painter = painterResource(id = R.drawable.icon_close),
- contentDescription = null,
- modifier = Modifier.size(Dimens.smallIconSize),
- )
- },
+ trailingIcon =
+ if (enabled) {
+ {
+ Icon(
+ painter = painterResource(id = R.drawable.icon_close),
+ contentDescription = null,
+ modifier = Modifier.size(Dimens.smallIconSize),
+ )
+ }
+ } else null,
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationInfo.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationInfo.kt
index f9c0f26862..3fbd40c537 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationInfo.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationInfo.kt
@@ -33,6 +33,7 @@ private fun PreviewLocationInfo() {
isVisible = true,
isExpanded = true,
location = null,
+ isUsingDaita = false,
inAddress = null,
outAddress = "",
)
@@ -48,6 +49,7 @@ fun LocationInfo(
isVisible: Boolean,
isExpanded: Boolean,
location: GeoIpLocation?,
+ isUsingDaita: Boolean,
inAddress: Triple<String, Int, TransportProtocol>?,
outAddress: String,
) {
@@ -61,15 +63,12 @@ fun LocationInfo(
.then(modifier)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
- Text(
- text = location?.hostname ?: "",
- color =
- if (isExpanded) {
- colorExpanded
- } else {
- colorCollapsed
- },
- style = MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.SemiBold),
+ RelayHostname(
+ hostname = location?.hostname,
+ isUsingDaita = isUsingDaita,
+ isExpanded = isExpanded,
+ colorExpanded = colorExpanded,
+ colorCollapsed = colorCollapsed,
)
Chevron(
isExpanded = isExpanded,
@@ -119,3 +118,36 @@ fun LocationInfo(
)
}
}
+
+@Composable
+private fun RelayHostname(
+ hostname: String?,
+ isUsingDaita: Boolean,
+ isExpanded: Boolean,
+ colorExpanded: Color,
+ colorCollapsed: Color,
+) {
+ val hostnameTitle =
+ when {
+ hostname != null && isUsingDaita -> {
+ stringResource(
+ id = R.string.connected_using_daita,
+ hostname,
+ stringResource(id = R.string.daita),
+ )
+ }
+ hostname != null -> hostname
+ else -> ""
+ }
+
+ Text(
+ text = hostnameTitle,
+ color =
+ if (isExpanded) {
+ colorExpanded
+ } else {
+ colorCollapsed
+ },
+ style = MaterialTheme.typography.labelLarge.copy(fontWeight = FontWeight.SemiBold),
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaConfirmationDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaConfirmationDialog.kt
new file mode 100644
index 0000000000..a5237a0ca5
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaConfirmationDialog.kt
@@ -0,0 +1,101 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.lifecycle.compose.dropUnlessResumed
+import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.RootGraph
+import com.ramcosta.composedestinations.result.EmptyResultBackNavigator
+import com.ramcosta.composedestinations.result.ResultBackNavigator
+import com.ramcosta.composedestinations.spec.DestinationStyle
+import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.button.PrimaryButton
+import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
+import net.mullvad.mullvadvpn.lib.theme.AppTheme
+import net.mullvad.mullvadvpn.lib.theme.Dimens
+import net.mullvad.mullvadvpn.lib.theme.color.AlphaScrollbar
+
+@Preview
+@Composable
+private fun PreviewDaitaConfirmationDialog() {
+ AppTheme { DaitaConfirmation(EmptyResultBackNavigator()) }
+}
+
+@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
+@Composable
+fun DaitaConfirmation(navigator: ResultBackNavigator<Boolean>) {
+ AlertDialog(
+ onDismissRequest = dropUnlessResumed { navigator.navigateBack(false) },
+ icon = {
+ Icon(
+ modifier = Modifier.fillMaxWidth().height(Dimens.dialogIconHeight),
+ painter = painterResource(id = R.drawable.icon_alert),
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.onSurface,
+ )
+ },
+ text = {
+ val scrollState = rememberScrollState()
+ Column(
+ Modifier.drawVerticalScrollbar(
+ scrollState,
+ MaterialTheme.colorScheme.onPrimary.copy(alpha = AlphaScrollbar),
+ )
+ .verticalScroll(scrollState),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Text(
+ text = stringResource(id = R.string.daita_relay_subset_warning),
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.bodySmall,
+ modifier = Modifier.fillMaxWidth(),
+ )
+
+ Spacer(modifier = Modifier.height(Dimens.verticalSpace))
+
+ Text(
+ text =
+ stringResource(
+ id = R.string.daita_warning,
+ stringResource(id = R.string.daita),
+ ),
+ color = MaterialTheme.colorScheme.onSurface,
+ style = MaterialTheme.typography.bodySmall,
+ modifier = Modifier.fillMaxWidth(),
+ )
+ }
+ },
+ confirmButton = {
+ Column(verticalArrangement = Arrangement.spacedBy(Dimens.buttonSpacing)) {
+ PrimaryButton(
+ modifier = Modifier.fillMaxWidth(),
+ text = stringResource(R.string.enable_anyway),
+ onClick = { navigator.navigateBack(true) },
+ )
+
+ PrimaryButton(
+ modifier = Modifier.fillMaxWidth(),
+ text = stringResource(R.string.back),
+ onClick = dropUnlessResumed { navigator.navigateBack(false) },
+ )
+ }
+ },
+ containerColor = MaterialTheme.colorScheme.surface,
+ titleContentColor = MaterialTheme.colorScheme.onSurface,
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaInfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaInfoDialog.kt
new file mode 100644
index 0000000000..a7e2b0b78e
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DaitaInfoDialog.kt
@@ -0,0 +1,35 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.lifecycle.compose.dropUnlessResumed
+import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.RootGraph
+import com.ramcosta.composedestinations.navigation.DestinationsNavigator
+import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
+import com.ramcosta.composedestinations.spec.DestinationStyle
+import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.lib.theme.AppTheme
+
+@Preview
+@Composable
+private fun PreviewDaitaInfoDialog() {
+ AppTheme { DaitaInfo(EmptyDestinationsNavigator) }
+}
+
+@Destination<RootGraph>(style = DestinationStyle.Dialog::class)
+@Composable
+fun DaitaInfo(navigator: DestinationsNavigator) {
+ InfoDialog(
+ message =
+ stringResource(
+ id = R.string.daita_info,
+ stringResource(id = R.string.daita),
+ stringResource(id = R.string.daita_full),
+ ),
+ additionalInfo =
+ stringResource(id = R.string.daita_warning, stringResource(id = R.string.daita)),
+ onDismiss = dropUnlessResumed { navigator.navigateUp() },
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayItemPreviewData.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayItemPreviewData.kt
index 70d707c10c..0af4199f40 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayItemPreviewData.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayItemPreviewData.kt
@@ -51,11 +51,13 @@ private fun generateRelayItemRelay(
cityCode: GeoLocationId.City,
hostName: String,
active: Boolean = true,
+ daita: Boolean = true,
) =
RelayItem.Location.Relay(
id = GeoLocationId.Hostname(city = cityCode, code = hostName),
active = active,
provider = Provider(ProviderId("Provider"), Ownership.MullvadOwned),
+ daita = daita,
)
private fun String.generateCountryCode() =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt
index a8981e612e..b6ca18c91a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt
@@ -18,14 +18,14 @@ object TunnelStatePreviewData {
fun generateConnectingState(featureIndicators: Int, quantumResistant: Boolean) =
TunnelState.Connecting(
- endpoint = generateTunnelEndpoint(quantumResistant = quantumResistant),
+ endpoint = generateTunnelEndpoint(quantumResistant = quantumResistant, daita = false),
location = generateLocation(),
featureIndicators = generateFeatureIndicators(featureIndicators),
)
fun generateConnectedState(featureIndicators: Int, quantumResistant: Boolean) =
TunnelState.Connected(
- endpoint = generateTunnelEndpoint(quantumResistant = quantumResistant),
+ endpoint = generateTunnelEndpoint(quantumResistant = quantumResistant, daita = true),
location = generateLocation(),
featureIndicators = generateFeatureIndicators(featureIndicators),
)
@@ -39,7 +39,7 @@ object TunnelStatePreviewData {
)
}
-private fun generateTunnelEndpoint(quantumResistant: Boolean): TunnelEndpoint =
+private fun generateTunnelEndpoint(quantumResistant: Boolean, daita: Boolean): TunnelEndpoint =
TunnelEndpoint(
endpoint = generateEndpoint(TransportProtocol.Udp),
quantumResistant = quantumResistant,
@@ -48,6 +48,7 @@ private fun generateTunnelEndpoint(quantumResistant: Boolean): TunnelEndpoint =
endpoint = generateEndpoint(TransportProtocol.Tcp),
ObfuscationType.Udp2Tcp,
),
+ daita = daita,
)
private fun generateEndpoint(transportProtocol: TransportProtocol) =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
index c5b2be56ed..c9ee962eb1 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
@@ -356,6 +356,7 @@ private fun ConnectionInfo(state: ConnectUiState) {
isVisible = state.showLocationInfo,
isExpanded = expanded,
location = state.location,
+ isUsingDaita = state.tunnelState.isUsingDaita(),
inAddress = state.inAddress,
outAddress = state.outAddress,
modifier =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt
index 1bccbaa713..c130d6d61c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt
@@ -36,6 +36,8 @@ import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.generated.destinations.AutoConnectAndLockdownModeDestination
import com.ramcosta.composedestinations.generated.destinations.ContentBlockersInfoDestination
import com.ramcosta.composedestinations.generated.destinations.CustomDnsInfoDestination
+import com.ramcosta.composedestinations.generated.destinations.DaitaConfirmationDestination
+import com.ramcosta.composedestinations.generated.destinations.DaitaInfoDestination
import com.ramcosta.composedestinations.generated.destinations.DnsDestination
import com.ramcosta.composedestinations.generated.destinations.LocalNetworkSharingInfoDestination
import com.ramcosta.composedestinations.generated.destinations.MalwareInfoDestination
@@ -147,6 +149,7 @@ fun VpnSettings(
dnsDialogResult: ResultRecipient<DnsDestination, DnsDialogResult>,
customWgPortResult: ResultRecipient<WireguardCustomPortDestination, Port?>,
mtuDialogResult: ResultRecipient<MtuDestination, Boolean>,
+ daitaConfirmationDialogResult: ResultRecipient<DaitaConfirmationDestination, Boolean>,
) {
val vm = koinViewModel<VpnSettingsViewModel>()
val state by vm.uiState.collectAsStateWithLifecycle()
@@ -176,6 +179,12 @@ fun VpnSettings(
}
}
+ daitaConfirmationDialogResult.OnNavResultValue { doEnableDaita ->
+ if (doEnableDaita) {
+ vm.onToggleDaita(true)
+ }
+ }
+
val snackbarHostState = remember { SnackbarHostState() }
val context = LocalContext.current
CollectSideEffectWithLifecycle(vm.uiSideEffect) {
@@ -224,6 +233,9 @@ fun VpnSettings(
},
navigateToLocalNetworkSharingInfo =
dropUnlessResumed { navigator.navigate(LocalNetworkSharingInfoDestination) },
+ navigateToDaitaInfo = dropUnlessResumed { navigator.navigate(DaitaInfoDestination) },
+ navigateToDaitaConfirmation =
+ dropUnlessResumed { navigator.navigate(DaitaConfirmationDestination) },
navigateToServerIpOverrides =
dropUnlessResumed { navigator.navigate(ServerIpOverridesDestination) },
onToggleBlockTrackers = vm::onToggleBlockTrackers,
@@ -231,6 +243,7 @@ fun VpnSettings(
onToggleBlockMalware = vm::onToggleBlockMalware,
onToggleAutoConnect = vm::onToggleAutoConnect,
onToggleLocalNetworkSharing = vm::onToggleLocalNetworkSharing,
+ onDisableDaita = { vm.onToggleDaita(false) },
onToggleBlockAdultContent = vm::onToggleBlockAdultContent,
onToggleBlockGambling = vm::onToggleBlockGambling,
onToggleBlockSocialMedia = vm::onToggleBlockSocialMedia,
@@ -273,6 +286,8 @@ fun VpnSettingsScreen(
navigateUdp2TcpInfo: () -> Unit = {},
navigateToWireguardPortInfo: (availablePortRanges: List<PortRange>) -> Unit = {},
navigateToLocalNetworkSharingInfo: () -> Unit = {},
+ navigateToDaitaInfo: () -> Unit = {},
+ navigateToDaitaConfirmation: () -> Unit = {},
navigateToWireguardPortDialog: () -> Unit = {},
navigateToServerIpOverrides: () -> Unit = {},
onToggleBlockTrackers: (Boolean) -> Unit = {},
@@ -280,6 +295,7 @@ fun VpnSettingsScreen(
onToggleBlockMalware: (Boolean) -> Unit = {},
onToggleAutoConnect: (Boolean) -> Unit = {},
onToggleLocalNetworkSharing: (Boolean) -> Unit = {},
+ onDisableDaita: () -> Unit = {},
onToggleBlockAdultContent: (Boolean) -> Unit = {},
onToggleBlockGambling: (Boolean) -> Unit = {},
onToggleBlockSocialMedia: (Boolean) -> Unit = {},
@@ -497,8 +513,24 @@ fun VpnSettingsScreen(
)
}
- itemWithDivider {
+ item {
+ Spacer(modifier = Modifier.height(Dimens.cellLabelVerticalPadding))
+ HeaderSwitchComposeCell(
+ title = stringResource(id = R.string.daita),
+ isToggled = state.isDaitaEnabled,
+ onCellClicked = { enable ->
+ if (enable) {
+ navigateToDaitaConfirmation()
+ } else {
+ onDisableDaita()
+ }
+ },
+ onInfoClicked = navigateToDaitaInfo,
+ )
Spacer(modifier = Modifier.height(Dimens.cellLabelVerticalPadding))
+ }
+
+ itemWithDivider {
InformationComposeCell(
title = stringResource(id = R.string.wireguard_port_title),
onInfoClicked = { navigateToWireguardPortInfo(state.availablePortRanges) },
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt
index 4fa2fbb1eb..d8245792a3 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt
@@ -22,6 +22,8 @@ sealed interface FilterChip {
data class Ownership(val ownership: ModelOwnership) : FilterChip
data class Provider(val count: Int) : FilterChip
+
+ data object Daita : FilterChip
}
enum class RelayListItemContentType {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt
index 0eaf1695a7..b57de21bc5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt
@@ -13,6 +13,7 @@ data class VpnSettingsUiState(
val mtu: Mtu?,
val isAutoConnectEnabled: Boolean,
val isLocalNetworkSharingEnabled: Boolean,
+ val isDaitaEnabled: Boolean,
val isCustomDnsEnabled: Boolean,
val customDnsItems: List<CustomDnsItem>,
val contentBlockersOptions: DefaultDnsOptions,
@@ -31,6 +32,7 @@ data class VpnSettingsUiState(
mtu: Mtu? = null,
isAutoConnectEnabled: Boolean = false,
isLocalNetworkSharingEnabled: Boolean = false,
+ isDaitaEnabled: Boolean = false,
isCustomDnsEnabled: Boolean = false,
customDnsItems: List<CustomDnsItem> = emptyList(),
contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
@@ -46,6 +48,7 @@ data class VpnSettingsUiState(
mtu,
isAutoConnectEnabled,
isLocalNetworkSharingEnabled,
+ isDaitaEnabled,
isCustomDnsEnabled,
customDnsItems,
contentBlockersOptions,
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 1f1a489684..6b909d394d 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
@@ -134,10 +134,10 @@ val uiModule = module {
single { CustomListActionUseCase(get(), get()) }
single { SelectedLocationTitleUseCase(get(), get()) }
single { AvailableProvidersUseCase(get()) }
- single { FilterCustomListsRelayItemUseCase(get(), get()) }
+ single { FilterCustomListsRelayItemUseCase(get(), get(), get()) }
single { CustomListsRelayItemUseCase(get(), get()) }
single { CustomListRelayItemsUseCase(get(), get()) }
- single { FilteredRelayListUseCase(get(), get()) }
+ single { FilteredRelayListUseCase(get(), get(), get()) }
single { LastKnownLocationUseCase(get()) }
single { InAppNotificationController(get(), get(), get(), get(), MainScope()) }
@@ -184,7 +184,9 @@ val uiModule = module {
viewModel { DnsDialogViewModel(get(), get(), get()) }
viewModel { LoginViewModel(get(), get(), get()) }
viewModel { PrivacyDisclaimerViewModel(get(), IS_PLAY_BUILD) }
- viewModel { SelectLocationViewModel(get(), get(), get(), get(), get(), get(), get(), get()) }
+ viewModel {
+ SelectLocationViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get())
+ }
viewModel { SettingsViewModel(get(), get(), IS_PLAY_BUILD) }
viewModel { SplashViewModel(get(), get(), get(), get()) }
viewModel { VoucherDialogViewModel(get()) }
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt
index c87a9548c5..5d6e48a3f7 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt
@@ -53,27 +53,28 @@ private fun RelayItem.Location.hasProvider(providersConstraint: Constraint<Provi
true
}
-fun RelayItem.CustomList.filterOnOwnershipAndProvider(
+fun RelayItem.CustomList.filter(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>,
+ isDaitaEnabled: Boolean,
): RelayItem.CustomList {
val newLocations =
locations.mapNotNull {
when (it) {
- is RelayItem.Location.Country ->
- it.filterOnOwnershipAndProvider(ownership, providers)
- is RelayItem.Location.City -> it.filterOnOwnershipAndProvider(ownership, providers)
- is RelayItem.Location.Relay -> it.filterOnOwnershipAndProvider(ownership, providers)
+ is RelayItem.Location.Country -> it.filter(ownership, providers, isDaitaEnabled)
+ is RelayItem.Location.City -> it.filter(ownership, providers, isDaitaEnabled)
+ is RelayItem.Location.Relay -> it.filter(ownership, providers, isDaitaEnabled)
}
}
return copy(locations = newLocations)
}
-fun RelayItem.Location.Country.filterOnOwnershipAndProvider(
+fun RelayItem.Location.Country.filter(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>,
+ isDaitaEnabled: Boolean,
): RelayItem.Location.Country? {
- val cities = cities.mapNotNull { it.filterOnOwnershipAndProvider(ownership, providers) }
+ val cities = cities.mapNotNull { it.filter(ownership, providers, isDaitaEnabled) }
return if (cities.isNotEmpty()) {
this.copy(cities = cities)
} else {
@@ -81,11 +82,12 @@ fun RelayItem.Location.Country.filterOnOwnershipAndProvider(
}
}
-private fun RelayItem.Location.City.filterOnOwnershipAndProvider(
+private fun RelayItem.Location.City.filter(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>,
+ isDaitaEnabled: Boolean,
): RelayItem.Location.City? {
- val relays = relays.mapNotNull { it.filterOnOwnershipAndProvider(ownership, providers) }
+ val relays = relays.mapNotNull { it.filter(ownership, providers, isDaitaEnabled) }
return if (relays.isNotEmpty()) {
this.copy(relays = relays)
} else {
@@ -93,11 +95,18 @@ private fun RelayItem.Location.City.filterOnOwnershipAndProvider(
}
}
-private fun RelayItem.Location.Relay.filterOnOwnershipAndProvider(
+private fun RelayItem.Location.Relay.hasMatchingDaitaSetting(isDaitaEnabled: Boolean): Boolean {
+ return if (isDaitaEnabled) daita else true
+}
+
+private fun RelayItem.Location.Relay.filter(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>,
+ isDaitaEnabled: Boolean,
): RelayItem.Location.Relay? {
- return if (hasOwnership(ownership) && hasProvider(providers)) {
+ return if (
+ hasMatchingDaitaSetting(isDaitaEnabled) && hasOwnership(ownership) && hasProvider(providers)
+ ) {
this
} else {
null
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
index 19e52b9790..d66d4a5c00 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
@@ -68,4 +68,6 @@ class SettingsRepository(
suspend fun setLocalNetworkSharing(isEnabled: Boolean) =
managementService.setAllowLan(isEnabled)
+
+ suspend fun setDaitaEnabled(enabled: Boolean) = managementService.setDaitaEnabled(enabled)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt
index 9c1994e075..60de94946f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt
@@ -5,25 +5,33 @@ import net.mullvad.mullvadvpn.lib.model.Constraint
import net.mullvad.mullvadvpn.lib.model.Ownership
import net.mullvad.mullvadvpn.lib.model.Providers
import net.mullvad.mullvadvpn.lib.model.RelayItem
-import net.mullvad.mullvadvpn.relaylist.filterOnOwnershipAndProvider
+import net.mullvad.mullvadvpn.relaylist.filter
import net.mullvad.mullvadvpn.repository.RelayListFilterRepository
import net.mullvad.mullvadvpn.repository.RelayListRepository
+import net.mullvad.mullvadvpn.repository.SettingsRepository
class FilteredRelayListUseCase(
private val relayListRepository: RelayListRepository,
private val relayListFilterRepository: RelayListFilterRepository,
+ private val settingsRepository: SettingsRepository,
) {
operator fun invoke() =
combine(
relayListRepository.relayList,
relayListFilterRepository.selectedOwnership,
relayListFilterRepository.selectedProviders,
- ) { relayList, selectedOwnership, selectedProviders ->
- relayList.filterOnOwnershipAndProvider(selectedOwnership, selectedProviders)
+ settingsRepository.settingsUpdates,
+ ) { relayList, selectedOwnership, selectedProviders, settings ->
+ relayList.filter(
+ selectedOwnership,
+ selectedProviders,
+ isDaitaEnabled = settings?.isDaitaEnabled() ?: false,
+ )
}
- private fun List<RelayItem.Location.Country>.filterOnOwnershipAndProvider(
+ private fun List<RelayItem.Location.Country>.filter(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>,
- ) = mapNotNull { it.filterOnOwnershipAndProvider(ownership, providers) }
+ isDaitaEnabled: Boolean,
+ ) = mapNotNull { it.filter(ownership, providers, isDaitaEnabled) }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt
index 49c8ec89f6..17ead75d2a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt
@@ -6,12 +6,14 @@ import net.mullvad.mullvadvpn.lib.model.Constraint
import net.mullvad.mullvadvpn.lib.model.Ownership
import net.mullvad.mullvadvpn.lib.model.Providers
import net.mullvad.mullvadvpn.lib.model.RelayItem
-import net.mullvad.mullvadvpn.relaylist.filterOnOwnershipAndProvider
+import net.mullvad.mullvadvpn.relaylist.filter
import net.mullvad.mullvadvpn.repository.RelayListFilterRepository
+import net.mullvad.mullvadvpn.repository.SettingsRepository
class FilterCustomListsRelayItemUseCase(
private val customListsRelayItemUseCase: CustomListsRelayItemUseCase,
private val relayListFilterRepository: RelayListFilterRepository,
+ private val settingsRepository: SettingsRepository,
) {
operator fun invoke() =
@@ -19,12 +21,18 @@ class FilterCustomListsRelayItemUseCase(
customListsRelayItemUseCase(),
relayListFilterRepository.selectedOwnership,
relayListFilterRepository.selectedProviders,
- ) { customLists, selectedOwnership, selectedProviders ->
- customLists.filterOnOwnershipAndProvider(selectedOwnership, selectedProviders)
+ settingsRepository.settingsUpdates,
+ ) { customLists, selectedOwnership, selectedProviders, settings ->
+ customLists.filterOnOwnershipAndProvider(
+ selectedOwnership,
+ selectedProviders,
+ isDaitaEnabled = settings?.isDaitaEnabled() ?: false,
+ )
}
private fun List<RelayItem.CustomList>.filterOnOwnershipAndProvider(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>,
- ) = mapNotNull { it.filterOnOwnershipAndProvider(ownership, providers) }
+ isDaitaEnabled: Boolean,
+ ) = mapNotNull { it.filter(ownership, providers, isDaitaEnabled = isDaitaEnabled) }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt
index 04476ea560..c34b182aa6 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt
@@ -36,6 +36,7 @@ import net.mullvad.mullvadvpn.relaylist.newFilterOnSearch
import net.mullvad.mullvadvpn.repository.CustomListsRepository
import net.mullvad.mullvadvpn.repository.RelayListFilterRepository
import net.mullvad.mullvadvpn.repository.RelayListRepository
+import net.mullvad.mullvadvpn.repository.SettingsRepository
import net.mullvad.mullvadvpn.usecase.AvailableProvidersUseCase
import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase
import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase
@@ -51,6 +52,7 @@ class SelectLocationViewModel(
private val customListActionUseCase: CustomListActionUseCase,
private val filteredRelayListUseCase: FilteredRelayListUseCase,
private val relayListRepository: RelayListRepository,
+ private val settingsRepository: SettingsRepository,
) : ViewModel() {
private val _searchTerm = MutableStateFlow(EMPTY_SEARCH_TERM)
@@ -110,7 +112,8 @@ class SelectLocationViewModel(
relayListFilterRepository.selectedOwnership,
relayListFilterRepository.selectedProviders,
availableProvidersUseCase(),
- ) { selectedOwnership, selectedConstraintProviders, allProviders ->
+ settingsRepository.settingsUpdates,
+ ) { selectedOwnership, selectedConstraintProviders, allProviders, settings ->
val ownershipFilter = selectedOwnership.getOrNull()
val providerCountFilter =
when (selectedConstraintProviders) {
@@ -122,7 +125,6 @@ class SelectLocationViewModel(
)
.size
}
-
buildList {
if (ownershipFilter != null) {
add(FilterChip.Ownership(ownershipFilter))
@@ -130,6 +132,9 @@ class SelectLocationViewModel(
if (providerCountFilter != null) {
add(FilterChip.Provider(providerCountFilter))
}
+ if (settings?.isDaitaEnabled() == true) {
+ add(FilterChip.Daita)
+ }
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
index abaad265fe..af2ea72e4e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt
@@ -63,6 +63,7 @@ class VpnSettingsViewModel(
mtuValue = settings?.tunnelOptions?.wireguard?.mtu,
isAutoConnectEnabled = settings?.autoConnect ?: false,
isLocalNetworkSharingEnabled = settings?.allowLan ?: false,
+ isDaitaEnabled = settings?.isDaitaEnabled() ?: false,
isCustomDnsEnabled = settings?.isCustomDnsEnabled() ?: false,
customDnsList = settings?.addresses()?.asStringAddressList() ?: listOf(),
contentBlockersOptions =
@@ -123,6 +124,14 @@ class VpnSettingsViewModel(
}
}
+ fun onToggleDaita(enable: Boolean) {
+ viewModelScope.launch(dispatcher) {
+ repository.setDaitaEnabled(enable).onLeft {
+ _uiSideEffect.send(VpnSettingsSideEffect.ShowToast.GenericError)
+ }
+ }
+ }
+
fun onDnsDialogDismissed() {
if (vmState.value.customDnsList.isEmpty()) {
onToggleCustomDns(enable = false)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt
index 534263b44b..676a10cd70 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelState.kt
@@ -13,6 +13,7 @@ data class VpnSettingsViewModelState(
val mtuValue: Mtu?,
val isAutoConnectEnabled: Boolean,
val isLocalNetworkSharingEnabled: Boolean,
+ val isDaitaEnabled: Boolean,
val isCustomDnsEnabled: Boolean,
val customDnsList: List<CustomDnsItem>,
val contentBlockersOptions: DefaultDnsOptions,
@@ -29,6 +30,7 @@ data class VpnSettingsViewModelState(
mtuValue,
isAutoConnectEnabled,
isLocalNetworkSharingEnabled,
+ isDaitaEnabled,
isCustomDnsEnabled,
customDnsList,
contentBlockersOptions,
@@ -47,6 +49,7 @@ data class VpnSettingsViewModelState(
mtuValue = null,
isAutoConnectEnabled = false,
isLocalNetworkSharingEnabled = false,
+ isDaitaEnabled = false,
isCustomDnsEnabled = false,
customDnsList = listOf(),
contentBlockersOptions = DefaultDnsOptions(),
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/CustomListLocationsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/CustomListLocationsViewModelTest.kt
index e4012abd9e..1e0de9c96e 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/CustomListLocationsViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/CustomListLocationsViewModelTest.kt
@@ -322,6 +322,7 @@ class CustomListLocationsViewModelTest {
ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
),
)
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt
index 5a44f6db06..bee888d279 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt
@@ -32,10 +32,12 @@ import net.mullvad.mullvadvpn.lib.model.Provider
import net.mullvad.mullvadvpn.lib.model.Providers
import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.model.RelayItemId
+import net.mullvad.mullvadvpn.lib.model.Settings
import net.mullvad.mullvadvpn.relaylist.descendants
import net.mullvad.mullvadvpn.repository.CustomListsRepository
import net.mullvad.mullvadvpn.repository.RelayListFilterRepository
import net.mullvad.mullvadvpn.repository.RelayListRepository
+import net.mullvad.mullvadvpn.repository.SettingsRepository
import net.mullvad.mullvadvpn.usecase.AvailableProvidersUseCase
import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase
import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase
@@ -58,6 +60,9 @@ class SelectLocationViewModelTest {
private val mockCustomListsRepository: CustomListsRepository = mockk()
private val mockCustomListsRelayItemUseCase: CustomListsRelayItemUseCase = mockk()
+ private val mockSettingsRepository: SettingsRepository = mockk()
+ private val settingsFlow = MutableStateFlow(mockk<Settings>(relaxed = true))
+
private lateinit var viewModel: SelectLocationViewModel
private val allProviders = MutableStateFlow<List<Provider>>(emptyList())
@@ -79,6 +84,7 @@ class SelectLocationViewModelTest {
every { mockFilteredRelayListUseCase() } returns filteredRelayList
every { mockFilteredCustomListRelayItemsUseCase() } returns filteredCustomRelayListItems
every { mockCustomListsRelayItemUseCase() } returns customListsRelayItem
+ every { mockSettingsRepository.settingsUpdates } returns settingsFlow
mockkStatic(RELAY_LIST_EXTENSIONS)
mockkStatic(RELAY_ITEM_EXTENSIONS)
@@ -93,6 +99,7 @@ class SelectLocationViewModelTest {
relayListRepository = mockRelayListRepository,
customListsRepository = mockCustomListsRepository,
customListsRelayItemUseCase = mockCustomListsRelayItemUseCase,
+ settingsRepository = mockSettingsRepository,
)
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt
index c2f9ca34a6..89456c1d02 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt
@@ -113,7 +113,11 @@ class VpnSettingsViewModelTest {
val mockTunnelOptions: TunnelOptions = mockk(relaxed = true)
// Can not use a mock here since mocking a value class val leads to class cast exception
val mockWireguardTunnelOptions =
- WireguardTunnelOptions(mtu = Mtu(0), quantumResistant = expectedResistantState)
+ WireguardTunnelOptions(
+ mtu = Mtu(0),
+ quantumResistant = expectedResistantState,
+ daita = false,
+ )
every { mockSettings.tunnelOptions } returns mockTunnelOptions
every { mockTunnelOptions.wireguard } returns mockWireguardTunnelOptions
@@ -146,6 +150,7 @@ class VpnSettingsViewModelTest {
WireguardTunnelOptions(
mtu = null,
quantumResistant = QuantumResistantState.Off,
+ daita = false,
),
dnsOptions = mockk(relaxed = true),
)
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt
index b51fd7eb2f..f444edce39 100644
--- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt
+++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt
@@ -104,6 +104,7 @@ import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation
import net.mullvad.mullvadvpn.lib.model.SetAllowLanError
import net.mullvad.mullvadvpn.lib.model.SetApiAccessMethodError
import net.mullvad.mullvadvpn.lib.model.SetAutoConnectError
+import net.mullvad.mullvadvpn.lib.model.SetDaitaSettingsError
import net.mullvad.mullvadvpn.lib.model.SetDnsOptionsError
import net.mullvad.mullvadvpn.lib.model.SetObfuscationOptionsError
import net.mullvad.mullvadvpn.lib.model.SetRelayLocationError
@@ -501,6 +502,15 @@ class ManagementService(
.mapLeft(SetAllowLanError::Unknown)
.mapEmpty()
+ suspend fun setDaitaEnabled(enabled: Boolean): Either<SetDaitaSettingsError, Unit> =
+ Either.catch {
+ val daitaSettings =
+ ManagementInterface.DaitaSettings.newBuilder().setEnabled(enabled).build()
+ grpc.setDaitaSettings(daitaSettings)
+ }
+ .mapLeft(SetDaitaSettingsError::Unknown)
+ .mapEmpty()
+
suspend fun setRelayLocation(location: ModelRelayItemId): Either<SetRelayLocationError, Unit> =
Either.catch {
val currentRelaySettings = getSettings().relaySettings
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt
index 5e8df1edc4..1ff297312b 100644
--- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt
+++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt
@@ -68,6 +68,7 @@ import net.mullvad.mullvadvpn.lib.model.TunnelState
import net.mullvad.mullvadvpn.lib.model.Udp2TcpObfuscationSettings
import net.mullvad.mullvadvpn.lib.model.WireguardConstraints
import net.mullvad.mullvadvpn.lib.model.WireguardEndpointData
+import net.mullvad.mullvadvpn.lib.model.WireguardRelayEndpointData
import net.mullvad.mullvadvpn.lib.model.WireguardTunnelOptions
import org.joda.time.Instant
@@ -158,6 +159,7 @@ internal fun ManagementInterface.TunnelEndpoint.toDomain(): TunnelEndpoint =
} else {
null
},
+ daita = daita,
)
internal fun ManagementInterface.ObfuscationEndpoint.toDomain(): ObfuscationEndpoint =
@@ -370,6 +372,7 @@ internal fun ManagementInterface.TunnelOptions.WireguardOptions.toDomain(): Wire
WireguardTunnelOptions(
mtu = if (hasMtu()) Mtu(mtu) else null,
quantumResistant = quantumResistant.toDomain(),
+ daita = daita.enabled,
)
internal fun ManagementInterface.QuantumResistantState.toDomain(): QuantumResistantState =
@@ -442,6 +445,9 @@ internal fun ManagementInterface.RelayList.toDomain(): RelayList =
internal fun ManagementInterface.WireguardEndpointData.toDomain(): WireguardEndpointData =
WireguardEndpointData(portRangesList.map { it.toDomain() })
+internal fun ManagementInterface.WireguardRelayEndpointData.toDomain(): WireguardRelayEndpointData =
+ WireguardRelayEndpointData(daita)
+
internal fun ManagementInterface.PortRange.toDomain(): PortRange = PortRange(first..last)
/**
@@ -493,6 +499,12 @@ internal fun ManagementInterface.Relay.toDomain(
ProviderId(provider),
ownership = if (owned) Ownership.MullvadOwned else Ownership.Rented,
),
+ daita =
+ if (
+ hasEndpointData() && endpointType == ManagementInterface.Relay.RelayType.WIREGUARD
+ ) {
+ ManagementInterface.WireguardRelayEndpointData.parseFrom(endpointData.value).daita
+ } else false,
)
internal fun ManagementInterface.Device.toDomain(): Device =
@@ -596,11 +608,11 @@ internal fun ManagementInterface.FeatureIndicator.toDomain() =
ManagementInterface.FeatureIndicator.SERVER_IP_OVERRIDE ->
FeatureIndicator.SERVER_IP_OVERRIDE
ManagementInterface.FeatureIndicator.CUSTOM_MTU -> FeatureIndicator.CUSTOM_MTU
+ ManagementInterface.FeatureIndicator.DAITA -> FeatureIndicator.DAITA
ManagementInterface.FeatureIndicator.LOCKDOWN_MODE,
ManagementInterface.FeatureIndicator.SHADOWSOCKS,
ManagementInterface.FeatureIndicator.MULTIHOP,
ManagementInterface.FeatureIndicator.BRIDGE_MODE,
ManagementInterface.FeatureIndicator.CUSTOM_MSS_FIX,
- ManagementInterface.FeatureIndicator.DAITA,
ManagementInterface.FeatureIndicator.UNRECOGNIZED -> error("Feature not supported")
}
diff --git a/android/lib/daemon-grpc/src/test/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparatorTest.kt b/android/lib/daemon-grpc/src/test/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparatorTest.kt
index 1494851bcb..e496c6d5aa 100644
--- a/android/lib/daemon-grpc/src/test/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparatorTest.kt
+++ b/android/lib/daemon-grpc/src/test/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/RelayNameComparatorTest.kt
@@ -29,6 +29,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay10 =
RelayItem.Location.Relay(
@@ -39,6 +40,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
relay9 assertOrderBothDirection relay10
@@ -55,6 +57,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay9b =
RelayItem.Location.Relay(
@@ -65,6 +68,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
assertTrue(RelayNameComparator.compare(relay9a, relay9b) == 0)
@@ -82,6 +86,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay1 =
RelayItem.Location.Relay(
@@ -92,6 +97,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay3 =
RelayItem.Location.Relay(
@@ -102,6 +108,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay100 =
RelayItem.Location.Relay(
@@ -112,6 +119,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
relay001 assertOrderBothDirection relay1
@@ -131,6 +139,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay9b =
RelayItem.Location.Relay(
@@ -141,6 +150,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
assertTrue(RelayNameComparator.compare(relay9a, relay9b) == 0)
@@ -158,6 +168,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay005 =
RelayItem.Location.Relay(
@@ -168,6 +179,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
relay001 assertOrderBothDirection relay005
@@ -184,6 +196,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relayAr8 =
RelayItem.Location.Relay(
@@ -194,6 +207,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relaySe5 =
RelayItem.Location.Relay(
@@ -204,6 +218,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relaySe10 =
RelayItem.Location.Relay(
@@ -214,6 +229,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
relayAr2 assertOrderBothDirection relayAr8
@@ -232,6 +248,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay2w =
RelayItem.Location.Relay(
@@ -242,6 +259,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
relay2c assertOrderBothDirection relay2w
@@ -258,6 +276,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
val relay22b =
RelayItem.Location.Relay(
@@ -268,6 +287,7 @@ class RelayNameComparatorTest {
providerId = ProviderId("Provider"),
ownership = Ownership.MullvadOwned,
),
+ daita = false,
)
relay22a assertOrderBothDirection relay22b
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt
index 7ad0b3ab69..d11f405869 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt
@@ -9,12 +9,12 @@ enum class FeatureIndicator {
CUSTOM_DNS,
SERVER_IP_OVERRIDE,
CUSTOM_MTU,
+ DAITA,
// Currently not supported
// LOCKDOWN_MODE,
// SHADOWSOCKS,
// MULTIHOP,
// BRIDGE_MODE,
// CUSTOM_MSS_FIX,
- // DAITA,
// UNRECOGNIZED,
}
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItem.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItem.kt
index edf00d4cb4..af96c4d94d 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItem.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItem.kt
@@ -58,6 +58,7 @@ sealed interface RelayItem {
override val id: GeoLocationId.Hostname,
val provider: Provider,
override val active: Boolean,
+ val daita: Boolean,
) : Location {
override val name: String = id.code
override val hasChildren: Boolean = false
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetDaitaSettingsError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetDaitaSettingsError.kt
new file mode 100644
index 0000000000..f636267c09
--- /dev/null
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetDaitaSettingsError.kt
@@ -0,0 +1,5 @@
+package net.mullvad.mullvadvpn.lib.model
+
+sealed interface SetDaitaSettingsError {
+ data class Unknown(val throwable: Throwable) : SetDaitaSettingsError
+}
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt
index 0c15202bee..f59d85184c 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt
@@ -15,5 +15,7 @@ data class Settings(
val splitTunnelSettings: SplitTunnelSettings,
val apiAccessMethodSettings: List<ApiAccessMethodSetting>,
) {
+ fun isDaitaEnabled() = tunnelOptions.wireguard.daita
+
companion object
}
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelEndpoint.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelEndpoint.kt
index 1465997cc5..3902e5c965 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelEndpoint.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelEndpoint.kt
@@ -4,4 +4,5 @@ data class TunnelEndpoint(
val endpoint: Endpoint,
val quantumResistant: Boolean,
val obfuscation: ObfuscationEndpoint?,
+ val daita: Boolean,
)
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelState.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelState.kt
index 53d468c01e..1849c5abf9 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelState.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TunnelState.kt
@@ -38,4 +38,12 @@ sealed class TunnelState {
is Error -> this.errorState.isBlocking
}
}
+
+ fun isUsingDaita(): Boolean {
+ return when (this) {
+ is Connected -> endpoint.daita
+ is Connecting -> endpoint?.daita ?: false
+ else -> false
+ }
+ }
}
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardRelayEndpointData.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardRelayEndpointData.kt
new file mode 100644
index 0000000000..9e328b92e6
--- /dev/null
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardRelayEndpointData.kt
@@ -0,0 +1,3 @@
+package net.mullvad.mullvadvpn.lib.model
+
+data class WireguardRelayEndpointData(val daita: Boolean)
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardTunnelOptions.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardTunnelOptions.kt
index 573f08213e..70b1599c55 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardTunnelOptions.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardTunnelOptions.kt
@@ -1,3 +1,7 @@
package net.mullvad.mullvadvpn.lib.model
-data class WireguardTunnelOptions(val mtu: Mtu?, val quantumResistant: QuantumResistantState)
+data class WireguardTunnelOptions(
+ val mtu: Mtu?,
+ val quantumResistant: QuantumResistantState,
+ val daita: Boolean,
+)
diff --git a/android/lib/resource/src/main/res/values-da/strings.xml b/android/lib/resource/src/main/res/values-da/strings.xml
index dd8beebc9b..8ac9978676 100644
--- a/android/lib/resource/src/main/res/values-da/strings.xml
+++ b/android/lib/resource/src/main/res/values-da/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Ja, log enhed af</string>
<string name="congrats">Tillykke!</string>
<string name="connect">Gør min forbindelse sikker</string>
+ <string name="connected_using_daita">%1$s via %2$s</string>
<string name="connecting">Tilslutter</string>
<string name="connecting_to_daemon">Opretter forbindelse til Mullvad-systemtjeneste...</string>
<string name="continue_login">Fortsæt med login</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Brugerdefineret WireGuard-port</string>
<string name="custom_port_dialog_valid_ranges">Gyldige områder: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Kunne ikke fortolke værten for den tilpassede tunnel. Prøv at ændre dine indstillinger.</string>
+ <string name="daita_info">%1$s (%2$s) skjuler mønstre i din krypterede VPN-trafik. Hvis nogen overvåger din forbindelse, gør dette det betydeligt sværere for dem at identificere, hvilke websteder du besøger. Mønstrene skjules ved omhyggeligt at tilføje netværksstøj og gøre alle netværkspakker lige store.</string>
+ <string name="daita_warning">Bemærk: Da dette øger din samlede netværkstrafik, skal du være forsigtig, hvis du har et abonnement med begrænset datamængde. Det kan også påvirke din netværkshastighed negativt. Overvej dette, hvis du vil aktivere %1$s.</string>
<string name="delete">Slet</string>
<string name="delete_custom_list_confirmation_description">Vil du slette \"%1$s\"?</string>
<string name="delete_custom_list_message">\"%1$s\" blev slettet</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Rediger metode</string>
<string name="edit_name">Rediger navn</string>
<string name="enable">Aktiver</string>
+ <string name="enable_anyway">Aktivér alligevel</string>
<string name="enable_custom_dns">Brug brugerdefineret DNS-server</string>
<string name="enable_method">Aktiver metode</string>
<string name="enter_value_placeholder">Indtast MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Nulstil alle tilsidesættelser</string>
<string name="set_dns_error">Kan ikke indstille systemets DNS-server. Indsend en problemrapport.</string>
<string name="set_firewall_policy_error">Kan ikke anvende firewallregler. Fejlfind eller send en problemrapport.</string>
+ <string name="setting_chip">Indstilling: %1$s</string>
<string name="settings">Indstillinger</string>
<string name="settings_account">Konto</string>
<string name="settings_api_access">API-adgang</string>
diff --git a/android/lib/resource/src/main/res/values-de/strings.xml b/android/lib/resource/src/main/res/values-de/strings.xml
index 70f3c4a5bb..ca1ae2cd27 100644
--- a/android/lib/resource/src/main/res/values-de/strings.xml
+++ b/android/lib/resource/src/main/res/values-de/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Ja, von Gerät abmelden</string>
<string name="congrats">Glückwunsch!</string>
<string name="connect">Meine Verbindung sichern</string>
+ <string name="connected_using_daita">%1$s verwendet %2$s</string>
<string name="connecting">Verbinden</string>
<string name="connecting_to_daemon">Verbindung zum Mullvad-Systemdienst wird hergestellt...</string>
<string name="continue_login">Weiter mit Anmeldung</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Eigener WireGuard-Port</string>
<string name="custom_port_dialog_valid_ranges">Gültige Bereiche: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Der Host des benutzerdefinierten Tunnels konnte nicht aufgelöst werden. Versuchen Sie, Ihre Einstellungen zu ändern.</string>
+ <string name="daita_info">%1$s (%2$s) verbirgt Muster in Ihrem verschlüsselten VPN-Traffic. Wenn jemand Ihre Verbindung überwacht, ist es für ihn wesentlich schwieriger zu erkennen, welche Websites Sie besuchen. Dazu fügt es vorsichtig Netzwerkrauschen hinzu und sorgt dafür, dass alle Netzwerkpakete die gleiche Größe haben.</string>
+ <string name="daita_warning">Achtung! Da dies Ihren gesamten Netzwerktraffic erhöht, sollten Sie vorsichtig sein, wenn Sie einen begrenzten Datentarif haben. Außerdem kann sich dies negativ auf Ihre Netzwerkgeschwindigkeit auswirken. Bitte beachten Sie dies, wenn Sie %1$s aktivieren möchten.</string>
<string name="delete">Löschen</string>
<string name="delete_custom_list_confirmation_description">„%1$s“ löschen?</string>
<string name="delete_custom_list_message">„%1$s“ wurde gelöscht</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Methode bearbeiten</string>
<string name="edit_name">Name bearbeiten</string>
<string name="enable">Aktivieren</string>
+ <string name="enable_anyway">Trotzdem aktivieren</string>
<string name="enable_custom_dns">Benutzerdefinierten DNS-Server verwenden</string>
<string name="enable_method">Methode aktivieren</string>
<string name="enter_value_placeholder">MTU eingeben</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Alle Überschreibungen zurücksetzen</string>
<string name="set_dns_error">Der DNS-Server des Systems konnte nicht eingestellt werden. Bitte senden Sie einen Problembericht.</string>
<string name="set_firewall_policy_error">Firewall-Regeln können nicht angewendet werden. Bitte beheben Sie das Problem oder senden Sie einen Problembericht.</string>
+ <string name="setting_chip">Einstellung: %1$s</string>
<string name="settings">Einstellungen</string>
<string name="settings_account">Konto</string>
<string name="settings_api_access">API-Zugriff</string>
diff --git a/android/lib/resource/src/main/res/values-es/strings.xml b/android/lib/resource/src/main/res/values-es/strings.xml
index 876d5afcdd..89272f7603 100644
--- a/android/lib/resource/src/main/res/values-es/strings.xml
+++ b/android/lib/resource/src/main/res/values-es/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Sí, cerrar sesión</string>
<string name="congrats">¡Enhorabuena!</string>
<string name="connect">Proteger mi conexión</string>
+ <string name="connected_using_daita">%1$s utilizando %2$s</string>
<string name="connecting">Conectando</string>
<string name="connecting_to_daemon">Conectando al servicio del sistema Mullvad…</string>
<string name="continue_login">Iniciar sesión</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Puerto personalizado de WireGuard</string>
<string name="custom_port_dialog_valid_ranges">Intervalos válidos: %1$s</string>
<string name="custom_tunnel_host_resolution_error">No se puede resolver el host del túnel personalizado. Pruebe a cambiar la configuración.</string>
+ <string name="daita_info">%1$s (%2$s) oculta los patrones en su tráfico VPN cifrado. Si alguien supervisa su conexión, esto les dificulta notablemente identificar qué sitios web está visitando. Lo realiza añadiendo con cuidado ruido de red y haciendo que todos los paquetes de red tengan el mismo tamaño.</string>
+ <string name="daita_warning">Atención: Como esto aumenta su tráfico de red total, tenga cuidado si dispone de un plan de datos limitados. Además, puede afectar negativamente a su velocidad de red. Considere todo esto si quiere habilitar %1$s.</string>
<string name="delete">Eliminar</string>
<string name="delete_custom_list_confirmation_description">¿Eliminar «%1$s»?</string>
<string name="delete_custom_list_message">Se ha eliminado «%1$s»</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Editar método</string>
<string name="edit_name">Editar nombre</string>
<string name="enable">Habilitar</string>
+ <string name="enable_anyway">Habilitar de todos modos</string>
<string name="enable_custom_dns">Usar servidor DNS personalizado</string>
<string name="enable_method">Habilitar método</string>
<string name="enter_value_placeholder">Introducir MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Restablecer todas las anulaciones</string>
<string name="set_dns_error">No se puede configurar el servidor DNS del sistema. Envíe un informe de problemas.</string>
<string name="set_firewall_policy_error">No se pueden aplicar las reglas del firewall. Intente solucionar el problema o envíe un informe de problemas.</string>
+ <string name="setting_chip">Ajuste: %1$s</string>
<string name="settings">Configuración</string>
<string name="settings_account">Cuenta</string>
<string name="settings_api_access">Acceso a API</string>
diff --git a/android/lib/resource/src/main/res/values-fi/strings.xml b/android/lib/resource/src/main/res/values-fi/strings.xml
index f29073df1f..785dd2646a 100644
--- a/android/lib/resource/src/main/res/values-fi/strings.xml
+++ b/android/lib/resource/src/main/res/values-fi/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Kyllä, kirjaa laite ulos</string>
<string name="congrats">Onnittelut!</string>
<string name="connect">Suojaa yhteyteni</string>
+ <string name="connected_using_daita">%1$s – %2$s käytössä</string>
<string name="connecting">Yhdistetään</string>
<string name="connecting_to_daemon">Yhdistetään Mullvad-järjestelmäpalveluun...</string>
<string name="continue_login">Jatka kirjautumista</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Mukautettu WireGuard-portti</string>
<string name="custom_port_dialog_valid_ranges">Kelvolliset portit: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Muokatun tunnelin isännän selvittäminen ei onnistu. Kokeile muuttaa asetuksiasi.</string>
+ <string name="daita_info">%1$s (%2$s) piilottaa salatussa VPN-liikenteessäsi toistuvat maneerit luomalla tarkoin räätälöityjä häiriöitä verkkoliikenteeseen ja tekemällä kaikista verkkopaketeista samankokoisia. Jos joku siis yrittää tarkkailla yhteyttäsi, hänen on huomattavasti vaikeampi tunnistaa, millä verkkosivustoilla oikein vierailet.</string>
+ <string name="daita_warning">Huomioithan, että %1$s:n käyttöönotto kasvattaa verkkoliikennettäsi kokonaisuudessaan ja voi myös vaikuttaa negatiivisesti verkon nopeuteen. DAITA:n käyttämistä kannattaa harkita tarkkaan, mikäli datapakettisi tiedonsiirtomäärä on rajoitettu.</string>
<string name="delete">Poista</string>
<string name="delete_custom_list_confirmation_description">Poistetaanko \"%1$s\"?</string>
<string name="delete_custom_list_message">\"%1$s\" poistettiin</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Muokkaa menetelmää</string>
<string name="edit_name">Muokkaa nimeä</string>
<string name="enable">Ota käyttöön</string>
+ <string name="enable_anyway">Ota silti käyttöön</string>
<string name="enable_custom_dns">Käytä mukautettua DNS-palvelinta</string>
<string name="enable_method">Ota menetelmä käyttöön</string>
<string name="enter_value_placeholder">Syötä MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Nollaa kaikki ohitukset</string>
<string name="set_dns_error">Järjestelmän DNS-palvelimen asettaminen ei onnistu. Lähetä ongelmaraportti.</string>
<string name="set_firewall_policy_error">Palomuurisääntöjä ei voida käyttää. Suorita vianetsintä tai lähetä ongelmaraportti.</string>
+ <string name="setting_chip">Asetus: %1$s</string>
<string name="settings">Asetukset</string>
<string name="settings_account">Tili</string>
<string name="settings_api_access">Ohjelmointirajapinnan käyttö</string>
diff --git a/android/lib/resource/src/main/res/values-fr/strings.xml b/android/lib/resource/src/main/res/values-fr/strings.xml
index 6acc7c2660..9f214429f9 100644
--- a/android/lib/resource/src/main/res/values-fr/strings.xml
+++ b/android/lib/resource/src/main/res/values-fr/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Oui, déconnecter l\'appareil</string>
<string name="congrats">Félicitations !</string>
<string name="connect">Sécuriser ma connexion</string>
+ <string name="connected_using_daita">%1$s utilisant %2$s</string>
<string name="connecting">Connexion</string>
<string name="connecting_to_daemon">Connexion au service système Mullvad...</string>
<string name="continue_login">Continuer avec la connexion</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Port WireGuard personnalisé</string>
<string name="custom_port_dialog_valid_ranges">Plages valides : %1$s</string>
<string name="custom_tunnel_host_resolution_error">Échec de la résolution de l\'hôte du tunnel personnalisé. Essayez de modifier vos paramètres.</string>
+ <string name="daita_info">%1$s (%2$s) dissimule des motifs dans votre trafic VPN chiffré. Si quelqu\'un surveille votre connexion, il lui sera beaucoup plus difficile d\'identifier les sites Web que vous visitez. Pour ce faire, il ajoute soigneusement du bruit réseau et fait en sorte que tous les paquets de réseau aient la même taille.</string>
+ <string name="daita_warning">Attention : étant donné que cette opération augmente le trafic total de votre réseau, faites attention si vous disposez d\'un forfait à données limitées. Cela peut également avoir un impact négatif sur la vitesse de votre réseau. Veuillez en tenir compte si vous souhaitez activer %1$s.</string>
<string name="delete">Supprimer</string>
<string name="delete_custom_list_confirmation_description">Supprimer « %1$s » ?</string>
<string name="delete_custom_list_message">« %1$s » a été supprimé</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Modifier le mode</string>
<string name="edit_name">Modifier le nom</string>
<string name="enable">Activer</string>
+ <string name="enable_anyway">Activer quand même</string>
<string name="enable_custom_dns">Utiliser un serveur DNS personnalisé</string>
<string name="enable_method">Activer la méthode</string>
<string name="enter_value_placeholder">Saisir le MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Réinitialiser toutes les substitutions</string>
<string name="set_dns_error">Impossible de définir le serveur DNS système. Veuillez envoyer un rapport de problème.</string>
<string name="set_firewall_policy_error">Impossible d\'appliquer les règles du pare-feu. Merci de résoudre le problème ou d\'envoyer un rapport de problème.</string>
+ <string name="setting_chip">Paramètre : %1$s</string>
<string name="settings">Paramètres</string>
<string name="settings_account">Compte</string>
<string name="settings_api_access">Accès à l\'API</string>
diff --git a/android/lib/resource/src/main/res/values-it/strings.xml b/android/lib/resource/src/main/res/values-it/strings.xml
index 1853a4e171..20a8533616 100644
--- a/android/lib/resource/src/main/res/values-it/strings.xml
+++ b/android/lib/resource/src/main/res/values-it/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Sì, disconnetti dal dispositivo</string>
<string name="congrats">Complimenti!</string>
<string name="connect">Proteggi mia connessione</string>
+ <string name="connected_using_daita">%1$s usa %2$s</string>
<string name="connecting">Connessione</string>
<string name="connecting_to_daemon">Connessione al servizio del sistema Mullvad...</string>
<string name="continue_login">Continua con il login</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Porta personalizzata WireGuard</string>
<string name="custom_port_dialog_valid_ranges">Intervalli validi: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Impossibile risolvere l\'host del tunnel personalizzato. Prova a modificare le impostazioni.</string>
+ <string name="daita_info">%1$s (%2$s) nasconde i percorsi in un traffico VPN crittografato. Se qualcuno sta monitorando la tua connessione, sarà molto più difficile per lui identificare quali siti web stai visitando. Ciò avviene aggiungendo con attenzione rumore di rete e rendendo tutti i pacchetti di rete della stessa dimensione.</string>
+ <string name="daita_warning">Attenzione: poiché questa operazione aumenta il traffico di rete totale, usala con cautela se disponi di un piano dati limitato. Può anche avere un impatto negativo sulla velocità della rete. Tienilo presente se vuoi abilitare %1$s.</string>
<string name="delete">Elimina</string>
<string name="delete_custom_list_confirmation_description">Eliminare \"%1$s\"?</string>
<string name="delete_custom_list_message">\"%1$s\" eliminato</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Modifica metodo</string>
<string name="edit_name">Modifica nome</string>
<string name="enable">Abilita</string>
+ <string name="enable_anyway">Abilita comunque</string>
<string name="enable_custom_dns">Usa un server DNS personalizzato</string>
<string name="enable_method">Abilita metodo</string>
<string name="enter_value_placeholder">Inserisci MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Reimposta tutte le sovrascritture</string>
<string name="set_dns_error">Impossibile impostare il server DNS di sistema. Invia una segnalazione del problema.</string>
<string name="set_firewall_policy_error">Impossibile applicare le regole del firewall. Consulta la risoluzione dei problemi o invia una segnalazione del problema.</string>
+ <string name="setting_chip">Impostazione: %1$s</string>
<string name="settings">Impostazioni</string>
<string name="settings_account">Account</string>
<string name="settings_api_access">Accesso API</string>
diff --git a/android/lib/resource/src/main/res/values-ja/strings.xml b/android/lib/resource/src/main/res/values-ja/strings.xml
index 794ad8cc28..6916c8de00 100644
--- a/android/lib/resource/src/main/res/values-ja/strings.xml
+++ b/android/lib/resource/src/main/res/values-ja/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">はい。デバイスをログアウトさせます</string>
<string name="congrats">おめでとうございます!</string>
<string name="connect">接続を保護する</string>
+ <string name="connected_using_daita">%1$s を使用した %2$s</string>
<string name="connecting">接続中</string>
<string name="connecting_to_daemon">Mullvad システムサービスに接続中...</string>
<string name="continue_login">ログインを続ける</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">WireGuardカスタムポート</string>
<string name="custom_port_dialog_valid_ranges">有効な範囲: %1$s</string>
<string name="custom_tunnel_host_resolution_error">カスタムトンネルのホストを解決できません。設定を変更してみてください。</string>
+ <string name="daita_info">%1$s (%2$s) を使用すると、暗号化された VPN トラフィックのパターンを隠すことができるようになります。何者かがあなたの接続を監視している場合に、アクセスしているウェブサイトの特定が大幅に難しくなります。ネットワークノイズを慎重に追加し、ネットワークパケットのサイズをすべて同一に揃えることによって実現しています。</string>
+ <string name="daita_warning">注意: これにより、ネットワークトラフィックの総数が増加します。上限のあるデータプランをご利用の場合にはご注意ください。また、ネットワーク の速度にも悪影響を及ぼす可能性があります。%1$s を有効にする場合は、この点を考慮に入れてください。</string>
<string name="delete">削除</string>
<string name="delete_custom_list_confirmation_description">\"%1$s\" を削除しますか?</string>
<string name="delete_custom_list_message">\"%1$s\" は削除されました</string>
@@ -133,6 +136,7 @@
<string name="edit_method">方法の編集</string>
<string name="edit_name">名前を編集</string>
<string name="enable">有効にする</string>
+ <string name="enable_anyway">それでも有効化する</string>
<string name="enable_custom_dns">カスタムDNSサーバーを使う</string>
<string name="enable_method">方法を有効化する</string>
<string name="enter_value_placeholder">MTU を入力</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">すべてのオーバーライドをリセット</string>
<string name="set_dns_error">システムのDNSサーバーを設定できません。問題の報告を送信してください。</string>
<string name="set_firewall_policy_error">ファイアウォールのルールを適用できません。問題に対処するか、問題の報告を送信してください。</string>
+ <string name="setting_chip">設定: %1$s</string>
<string name="settings">設定</string>
<string name="settings_account">アカウント</string>
<string name="settings_api_access">APIアクセス</string>
diff --git a/android/lib/resource/src/main/res/values-ko/strings.xml b/android/lib/resource/src/main/res/values-ko/strings.xml
index f80d458943..e74820e81b 100644
--- a/android/lib/resource/src/main/res/values-ko/strings.xml
+++ b/android/lib/resource/src/main/res/values-ko/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">예, 장치에서 로그아웃</string>
<string name="congrats">축하합니다!</string>
<string name="connect">내 연결 보안 유지</string>
+ <string name="connected_using_daita">%1$s 사용 %2$s</string>
<string name="connecting">연결 중</string>
<string name="connecting_to_daemon">Mullvad 시스템 서비스에 연결하는 중...</string>
<string name="continue_login">로그인 계속하기</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">WireGuard 사용자 지정 포트</string>
<string name="custom_port_dialog_valid_ranges">유효한 범위: %1$s</string>
<string name="custom_tunnel_host_resolution_error">사용자 지정 터널의 호스트를 확인할 수 없습니다. 설정을 변경해 보세요.</string>
+ <string name="daita_info">%1$s (%2$s)은(는) 암호화 VPN 트래픽에서 패턴을 숨깁니다. 누군가가 사용자의 연결을 모니터링하고 있다면, 사용자가 방문하고 있는 웹사이트 식별을 훨씬 더 어렵게 만듭니다. 네트워크 노이즈를 세심하게 추가하고, 모든 네트워크 패킷을 같은 크기로 만듭니다.</string>
+ <string name="daita_warning">주의: 이러한 방식은 총 네트워크 트래픽을 증가시키므로, 제한된 데이터 플랜 사용 시에는 유의하시기 바랍니다. 네트워크 속도에도 부정적 영향을 미칠 수 있습니다. %1$s 활성화 시에는 이러한 부분을 고려해 주시기 바랍니다.</string>
<string name="delete">삭제</string>
<string name="delete_custom_list_confirmation_description">\"%1$s\"을(를) 삭제하시겠습니까?</string>
<string name="delete_custom_list_message">\"%1$s\"이(가) 삭제되었습니다</string>
@@ -133,6 +136,7 @@
<string name="edit_method">방법 편집</string>
<string name="edit_name">이름 편집</string>
<string name="enable">사용</string>
+ <string name="enable_anyway">그래도 사용</string>
<string name="enable_custom_dns">사용자 지정 DNS 서버 사용</string>
<string name="enable_method">방법 활성화</string>
<string name="enter_value_placeholder">MTU 입력</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">모든 재정의 초기화</string>
<string name="set_dns_error">시스템 DNS 서버를 설정할 수 없습니다. 문제 보고서를 보내주세요.</string>
<string name="set_firewall_policy_error">방화벽 규칙을 적용할 수 없습니다. 문제를 해결하거나 문제 보고서를 보내주세요.</string>
+ <string name="setting_chip">설정: %1$s</string>
<string name="settings">설정</string>
<string name="settings_account">계정</string>
<string name="settings_api_access">API 액세스</string>
diff --git a/android/lib/resource/src/main/res/values-my/strings.xml b/android/lib/resource/src/main/res/values-my/strings.xml
index d7a185edf4..1b7561310c 100644
--- a/android/lib/resource/src/main/res/values-my/strings.xml
+++ b/android/lib/resource/src/main/res/values-my/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">စက်မှ ထွက်မည်</string>
<string name="congrats">ဝမ်းသာပါတယ်။</string>
<string name="connect">ကျွန်ုပ်၏ ချိတ်ဆက်မှုကို ကာကွယ်ရန်</string>
+ <string name="connected_using_daita">%1$s သည် %2$s ကို သုံးနေပါသည်</string>
<string name="connecting">ချိတ်ဆက်နေဆဲ</string>
<string name="connecting_to_daemon">Mullvad စနစ် ဝန်ဆောင်မှုနှင့် ချိတ်ဆက်နေဆဲ...</string>
<string name="continue_login">ဆက်လက် ဝင်ရောက်ရန်</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">စိတ်ကြိုက် WireGuard ပေါ့တ်</string>
<string name="custom_port_dialog_valid_ranges">အကျုံးဝင်သည့် အပိုင်းအခြား- %1$s</string>
<string name="custom_tunnel_host_resolution_error">စိတ်ကြိုက်ပြုလုပ်ထားသည့် Tunnel ၏ Host ကို ဖြေရှင်း၍ မရနိုင်ပါ။ သင့်ဆက်တင်ကို ပြောင်းကြည့်ပါ။</string>
+ <string name="daita_info">%1$s (%2$s) သည် သင်၏ ကုဒ်ပြောင်းဝှက်ထားသော VPN ကူးလူးမှုတွင် ပက်တန်များကို ဝှက်ထားပါသည်။ သင့်ချိတ်ဆက်မှုကို တစ်စုံတစ်ယောက်က စောင့်ကြည့်နေပါက မည်သည့်ဝက်ဘ်ဆိုက်များ သင်ဝင်ရောက်နေသည်ကို ၎င်းတို့က ခွဲခြားဖော်ထုတ်ဖို့ရာ ပို၍ သိသိသာသာ ခက်ခဲသွားအောင် ၎င်းက ပြုလုပ်ပေးပါသည်။ ကွန်ရက် အနှောင့်အယှက်လျှပ်လိုင်းကို ဂရုတစိုက် ထည့်ပြီး ကွန်ရက် ပက်ကက်အားလုံးကို အရွယ်အစားတူညီအောင် ပြုလုပ်ခြင်းဖြင့် ပို၍ခက်ခဲသွားအောင် ဆောင်ရွက်ပါသည်။</string>
+ <string name="daita_warning">သတိပြုရန်- ဤသည်က သင့်ကွန်ရန်ကူးလူးမှု စုစုပေါင်းပမာဏကို တိုးစေသောကြောင့် ဒေတာပလန်သည် အကန့်အသတ်ရှိပါက သတိထားဆောင်ရွက်ပါ။ သင့်ကွန်ရက်အမြန်နှုန်းကိုလည်း အပျက်သဘောထိခိုက်စေနိုင်ပါသည်။ %1$s ကို ဖွင့်လိုပါက ဤသည်ကို ထည့်သွင်းစဉ်းစားပေးပါ။</string>
<string name="delete">ဖျက်ရန်</string>
<string name="delete_custom_list_confirmation_description">\"%1$s\" ကို ဖျက်မည်လား။</string>
<string name="delete_custom_list_message">\"%1$s\" ကို ဖျက်ပြီးပါပြီ</string>
@@ -133,6 +136,7 @@
<string name="edit_method">နည်းလမ်းကို တည်းဖြတ်ပါ</string>
<string name="edit_name">အမည် တည်းဖြတ်ရန်</string>
<string name="enable">ဖွင့်ရန်</string>
+ <string name="enable_anyway">မည်သို့ပင်ဖြစ်စေ ဖွင့်ရန်</string>
<string name="enable_custom_dns">စိတ်ကြိုက် DNS ဆာဗာကို သုံးရန်</string>
<string name="enable_method">နည်းလမ်းကို ဖွင့်ရန်</string>
<string name="enter_value_placeholder">MTU ကို ရိုက်ထည့်ရန်</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">ကျော်လွန် ပယ်ဖျက်မှု အားလုံးကို ပြန်လည်သတ်မှတ်ရန်</string>
<string name="set_dns_error">စနစ် DNS ဆာဗာကို သတ်မှတ်၍ မရနိုင်ပါ။ ပြဿနာ ရီပို့တ်တစ်ခု ပေးပို့ပေးပါ။</string>
<string name="set_firewall_policy_error">Firewall စည်းမျဉ်းများကို အသုံးချ၍ မရနိုင်ပါ။ ပြစ်ချက် ရှာဖွေဖယ်ရှာပေးပါ သို့မဟုတ် ပြဿနာ ရီပို့တ် ပေးပို့ပေးပါ။</string>
+ <string name="setting_chip">ဆက်တင်- %1$s</string>
<string name="settings">ဆက်တင်</string>
<string name="settings_account">အကောင့်</string>
<string name="settings_api_access">API ရယူသုံးစွဲခွင့်</string>
diff --git a/android/lib/resource/src/main/res/values-nb/strings.xml b/android/lib/resource/src/main/res/values-nb/strings.xml
index 4be52ec773..ac085f9269 100644
--- a/android/lib/resource/src/main/res/values-nb/strings.xml
+++ b/android/lib/resource/src/main/res/values-nb/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Ja, logg av enhet</string>
<string name="congrats">Gratulerer!</string>
<string name="connect">Gjør tilkoblingen sikker</string>
+ <string name="connected_using_daita">%1$s bruker %2$s</string>
<string name="connecting">Kobler til</string>
<string name="connecting_to_daemon">Kobler til Mullvads systemtjeneste ...</string>
<string name="continue_login">Fortsett med pålogging</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Tilpasset WireGuard-port</string>
<string name="custom_port_dialog_valid_ranges">Gyldige verdiområder: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Kunne ikke løse vert for egendefinert tunnel. Forsøk å endre innstillingene dine.</string>
+ <string name="daita_info">%1$s (%2$s) skjuler mønstre i den krypterte VPN-trafikken. Hvis noen overvåker tilkoblingen din, gjør dette det betydelig vanskeligere for dem å identifisere hvilke nettsteder du besøker. Dette gjøres ved varsomt å legge til nettverksstøy og gjøre alle nettverkspakker like store.</string>
+ <string name="daita_warning">Obs: Siden dette øker den totale nettverkstrafikken, bør du være forsiktig hvis du har et abonnement med begrenset data. Det kan også påvirke nettverkshastigheten i negativ retning. Vær oppmerksom på dette hvis du ønsker å aktivere %1$s.</string>
<string name="delete">Slett</string>
<string name="delete_custom_list_confirmation_description">Slette «%1$s»?</string>
<string name="delete_custom_list_message">«%1$s» ble slettet</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Endre metode</string>
<string name="edit_name">Endre navn</string>
<string name="enable">Aktiver</string>
+ <string name="enable_anyway">Aktiver uansett</string>
<string name="enable_custom_dns">Bruk egendefinert DNS-server</string>
<string name="enable_method">Aktiver metoden</string>
<string name="enter_value_placeholder">Angi MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Tilbakestill alle overstyringer</string>
<string name="set_dns_error">Kunne ikke angi DNS-server for systemet. Send inn en problemrapport.</string>
<string name="set_firewall_policy_error">Kunne ikke bruke brannmur-regler. Feilsøk eller send inn en problemrapport.</string>
+ <string name="setting_chip">Innstilling: %1$s</string>
<string name="settings">Innstillinger</string>
<string name="settings_account">Konto</string>
<string name="settings_api_access">API-tilgang</string>
diff --git a/android/lib/resource/src/main/res/values-nl/strings.xml b/android/lib/resource/src/main/res/values-nl/strings.xml
index df7414265b..a5462c93b7 100644
--- a/android/lib/resource/src/main/res/values-nl/strings.xml
+++ b/android/lib/resource/src/main/res/values-nl/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Ja, apparaat afmelden</string>
<string name="congrats">Gefeliciteerd!</string>
<string name="connect">Mijn verbinding beveiligen</string>
+ <string name="connected_using_daita">%1$s via %2$s</string>
<string name="connecting">Bezig met verbinden</string>
<string name="connecting_to_daemon">Verbinden met Mullvad-systeemdienst...</string>
<string name="continue_login">Doorgaan met aanmelden</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Aangepaste WireGuard-poort</string>
<string name="custom_port_dialog_valid_ranges">Geldige bereiken: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Kan host van aangepaste tunnel niet omzetten. Probeer uw instellingen te wijzigen.</string>
+ <string name="daita_info">%1$s (%2$s) verbergt patronen in het versleutelde VPN-verkeer. Als iemand de verbinding in de gaten houdt, maakt dit het aanzienlijk moeilijker voor diegene om te zien welke websites u bezoekt. Dit wordt gedaan door zorgvuldig netwerkruis toe te voegen en alle netwerkpakketten even groot te maken.</string>
+ <string name="daita_warning">Let op: omdat dit het totale netwerkverkeer verhoogt, moet u voorzichtig zijn als u een beperkt data-abonnement hebt. Ook kan het uw netwerksnelheid negatief beïnvloeden. Houd hier rekening mee als u %1$s wilt inschakelen.</string>
<string name="delete">Verwijderen</string>
<string name="delete_custom_list_confirmation_description">\"%1$s\" verwijderen?</string>
<string name="delete_custom_list_message">\"%1$s\" is verwijderd</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Methode bewerken</string>
<string name="edit_name">Naam bewerken</string>
<string name="enable">Inschakelen</string>
+ <string name="enable_anyway">Toch inschakelen</string>
<string name="enable_custom_dns">Aangepaste DNS-server gebruiken</string>
<string name="enable_method">Methode inschakelen</string>
<string name="enter_value_placeholder">Voer MTU in</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Alle overschrijvingen resetten</string>
<string name="set_dns_error">Kan DNS-server van systeem niet instellen. Stuur een probleemrapport.</string>
<string name="set_firewall_policy_error">Kan firewallregels niet toepassen. Los problemen op of stuur een probleemmelding.</string>
+ <string name="setting_chip">Instelling: %1$s</string>
<string name="settings">Instellingen</string>
<string name="settings_account">Account</string>
<string name="settings_api_access">API-toegang</string>
diff --git a/android/lib/resource/src/main/res/values-pl/strings.xml b/android/lib/resource/src/main/res/values-pl/strings.xml
index 9c3fb6b485..b97c1e62fe 100644
--- a/android/lib/resource/src/main/res/values-pl/strings.xml
+++ b/android/lib/resource/src/main/res/values-pl/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Tak, wyloguj urządzenie</string>
<string name="congrats">Gratulacje!</string>
<string name="connect">Zabezpiecz moje połączenie</string>
+ <string name="connected_using_daita">%1$s przy użyciu %2$s</string>
<string name="connecting">Łączenie</string>
<string name="connecting_to_daemon">Łączenie z usługą systemową Mullvad...</string>
<string name="continue_login">Kontynuuj logowanie</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Niestandardowy port WireGuard</string>
<string name="custom_port_dialog_valid_ranges">Prawidłowe zakresy: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Nie można rozpoznać hosta tunelu niestandardowego. Spróbuj zmienić ustawienia.</string>
+ <string name="daita_info">%1$s (%2$s) ukrywa wzorce w zaszyfrowanym ruchu VPN. Jeśli ktoś monitoruje Twoje połączenie, znacznie utrudni to identyfikację odwiedzanych witryn. Odbywa się to poprzez ostrożne dodawanie szumów sieciowych i ustawianie tego samego rozmiaru wszystkich pakietów sieciowych.</string>
+ <string name="daita_warning">Uwaga: zwiększa to łączny ruch sieciowy, zachowaj więc ostrożność, jeśli masz ograniczony pakiet danych. Może to również negatywnie wpłynąć na szybkość sieci. Weź to pod uwagę, jeśli chcesz włączyć %1$s.</string>
<string name="delete">Usuń</string>
<string name="delete_custom_list_confirmation_description">Usunąć „%1$s”?</string>
<string name="delete_custom_list_message">Usunięto „%1$s”</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Edytuj metodę</string>
<string name="edit_name">Edytuj nazwę</string>
<string name="enable">Włącz</string>
+ <string name="enable_anyway">Mimo to włącz</string>
<string name="enable_custom_dns">Użyj niestandardowego serwera DNS</string>
<string name="enable_method">Włącz metodę</string>
<string name="enter_value_placeholder">Wprowadź MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Resetuj wszystkie zastąpienia</string>
<string name="set_dns_error">Nie można ustawić systemowego serwera DNS. Wyślij zgłoszenie problemu.</string>
<string name="set_firewall_policy_error">Nie można zastosować reguł zapory. Rozwiąż problem lub wyślij zgłoszenie problemu.</string>
+ <string name="setting_chip">Ustawienie: %1$s</string>
<string name="settings">Ustawienia</string>
<string name="settings_account">Konto</string>
<string name="settings_api_access">Dostęp do API</string>
diff --git a/android/lib/resource/src/main/res/values-pt/strings.xml b/android/lib/resource/src/main/res/values-pt/strings.xml
index 5482bd0cac..559e92a6b5 100644
--- a/android/lib/resource/src/main/res/values-pt/strings.xml
+++ b/android/lib/resource/src/main/res/values-pt/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Sim, desligar o dispositivo</string>
<string name="congrats">Parabéns!</string>
<string name="connect">Tornar a minha ligação segura</string>
+ <string name="connected_using_daita">%1$s a usar %2$s</string>
<string name="connecting">A ligar</string>
<string name="connecting_to_daemon">A ligar-se ao serviço de sistema Mulvad...</string>
<string name="continue_login">Continuar com a ligação</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Porta personalizada WireGuard</string>
<string name="custom_port_dialog_valid_ranges">Intervalos válidos: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Não foi possível resolver o anfitrião do túnel personalizado. Experimente alterar as suas definições.</string>
+ <string name="daita_info">%1$s (%2$s) oculta padrões no seu tráfego VPN encriptado. Se alguém estiver a monitorizar a sua ligação, isto dificulta significativamente a identificação dos sites que visita. Para tal, adiciona cuidadosamente ruído de rede e torna todos os pacotes de rede do mesmo tamanho.</string>
+ <string name="daita_warning">Atenção: visto que isto aumenta o tráfego total da sua rede, tenha cuidado se tiver um plano de dados limitado. Também pode afetar negativamente a velocidade da sua rede. Tenha isto em consideração se pretender ativar %1$s.</string>
<string name="delete">Eliminar</string>
<string name="delete_custom_list_confirmation_description">Eliminar \"%1$s\"?</string>
<string name="delete_custom_list_message">\"%1$s\" foi eliminada</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Editar método</string>
<string name="edit_name">Editar nome</string>
<string name="enable">Ativar</string>
+ <string name="enable_anyway">Ativar mesmo assim</string>
<string name="enable_custom_dns">Usar servidor DNS personalizado</string>
<string name="enable_method">Ativar método</string>
<string name="enter_value_placeholder">Introduzir MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Repor todas as substituições</string>
<string name="set_dns_error">Não foi possível definir o servidor DNS do sistema. Envie um relatório do problema.</string>
<string name="set_firewall_policy_error">Não foi possível aplicar as regras de firewall. Experimente a resolução de problemas ou envie um relatório do problema.</string>
+ <string name="setting_chip">Definição: %1$s</string>
<string name="settings">Definições</string>
<string name="settings_account">Conta</string>
<string name="settings_api_access">Acesso à API</string>
diff --git a/android/lib/resource/src/main/res/values-ru/strings.xml b/android/lib/resource/src/main/res/values-ru/strings.xml
index 97269c75ed..b930f03c14 100644
--- a/android/lib/resource/src/main/res/values-ru/strings.xml
+++ b/android/lib/resource/src/main/res/values-ru/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Выйти из профиля на устройстве</string>
<string name="congrats">Поздравляем!</string>
<string name="connect">Защитить мое подключение</string>
+ <string name="connected_using_daita">%1$s через %2$s</string>
<string name="connecting">Идет подключение</string>
<string name="connecting_to_daemon">Подключение к системному сервису Mullvad...</string>
<string name="continue_login">Войти</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Пользовательский порт WireGuard</string>
<string name="custom_port_dialog_valid_ranges">Допустимые диапазоны: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Не удалось преобразовать имя узла пользовательского туннеля. Попробуйте изменить настройки.</string>
+ <string name="daita_info">%1$s (%2$s) маскирует особенности зашифрованного VPN-трафика. Если кто-то следит за вашим подключением, ему будет значительно сложнее определить, какие сайты вы посещаете. Для этого добавляется сетевой шум, а все сетевые пакеты делаются одинаковыми по размеру.</string>
+ <string name="daita_warning">Внимание: использование этой функции увеличит общий сетевой трафик — учтите это при ограниченном тарифном плане. Это также может негативно повлиять на скорость работы сети. Помните об этих факторах при включении %1$s.</string>
<string name="delete">Удалить</string>
<string name="delete_custom_list_confirmation_description">Удалить список «%1$s»?</string>
<string name="delete_custom_list_message">Список «%1$s» удален</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Изменение метода</string>
<string name="edit_name">Изменить имя</string>
<string name="enable">Включить</string>
+ <string name="enable_anyway">Всё равно включить</string>
<string name="enable_custom_dns">Пользовательский DNS-сервер</string>
<string name="enable_method">Включить метод</string>
<string name="enter_value_placeholder">Введите MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Сброс всех переопределений</string>
<string name="set_dns_error">Не удалось установить системный DNS-сервер. Отправьте сообщение о проблеме.</string>
<string name="set_firewall_policy_error">Невозможно применить правила брандмауэра. Устраните неполадки или отправьте сообщение о проблеме.</string>
+ <string name="setting_chip">Параметр: %1$s</string>
<string name="settings">Настройки</string>
<string name="settings_account">Учетная запись</string>
<string name="settings_api_access">Доступ к API</string>
diff --git a/android/lib/resource/src/main/res/values-sv/strings.xml b/android/lib/resource/src/main/res/values-sv/strings.xml
index 3395eeb6e6..6c34428c07 100644
--- a/android/lib/resource/src/main/res/values-sv/strings.xml
+++ b/android/lib/resource/src/main/res/values-sv/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Ja, logga ut enheten</string>
<string name="congrats">Grattis!</string>
<string name="connect">Skydda min anslutning</string>
+ <string name="connected_using_daita">%1$s använder %2$s</string>
<string name="connecting">Ansluter</string>
<string name="connecting_to_daemon">Ansluter till Mullvads systemtjänst...</string>
<string name="continue_login">Fortsätt med inloggning</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">Anpassad WireGuard-port</string>
<string name="custom_port_dialog_valid_ranges">Giltiga intervall: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Det går inte att lösa värd för anpassad tunnel. Försök att ändra inställningarna.</string>
+ <string name="daita_info">%1$s (%2$s) döljer mönster i din krypterade VPN-trafik. Om någon övervakar din anslutning blir det mycket svårare för hen att identifiera vilka webbplatser du besöker. Den gör det genom att noggrant lägga till nätverksbrus och se till så att alla nätverkspaket har samma storlek.</string>
+ <string name="daita_warning">Obs! Detta ger dig högre total nätverkstrafik så var försiktig på om du har ett abonnemang med begränsad mängd data. Det kan även ha en negativ påverkan på din nätverkshastighet. Tänk på det när du aktiverar %1$s.</string>
<string name="delete">Ta bort</string>
<string name="delete_custom_list_confirmation_description">Ta bort \"%1$s\"?</string>
<string name="delete_custom_list_message">\"%1$s\" har tagits bort</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Redigera metod</string>
<string name="edit_name">Redigera namn</string>
<string name="enable">Aktivera</string>
+ <string name="enable_anyway">Aktivera ändå</string>
<string name="enable_custom_dns">Använd anpassad DNS-server</string>
<string name="enable_method">Aktivera metod</string>
<string name="enter_value_placeholder">Ange MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Återställ alla åsidosättningar</string>
<string name="set_dns_error">Det går inte att konfigurera DNS-server. Skicka en problemrapport.</string>
<string name="set_firewall_policy_error">Det går inte att tillämpa brandväggsregler. Felsök eller skicka en problemrapport.</string>
+ <string name="setting_chip">Inställning: %1$s</string>
<string name="settings">Inställningar</string>
<string name="settings_account">Konto</string>
<string name="settings_api_access">API-åtkomst</string>
diff --git a/android/lib/resource/src/main/res/values-th/strings.xml b/android/lib/resource/src/main/res/values-th/strings.xml
index 6873f09ab0..cd9053dc00 100644
--- a/android/lib/resource/src/main/res/values-th/strings.xml
+++ b/android/lib/resource/src/main/res/values-th/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">ใช่ นำอุปกรณ์ออกจากระบบ</string>
<string name="congrats">ยินดีด้วย!</string>
<string name="connect">รักษาความปลอดภัยในการเชื่อมต่อ</string>
+ <string name="connected_using_daita">%1$s กำลังใช้ %2$s</string>
<string name="connecting">กำลังเชื่อมต่อ</string>
<string name="connecting_to_daemon">กำลังเชื่อมต่อบริการของระบบ Mullvad...</string>
<string name="continue_login">เข้าสู่ระบบต่อ</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">พอร์ต WireGuard แบบกำหนดเอง</string>
<string name="custom_port_dialog_valid_ranges">ช่วงที่ใช้ได้: %1$s</string>
<string name="custom_tunnel_host_resolution_error">ไม่พบโฮสต์ของช่องทางแบบกำหนดเอง กรุณาลองเปลี่ยนการตั้งค่าของคุณ</string>
+ <string name="daita_info">%1$s (%2$s) ซ่อนรูปแบบในการรับส่งข้อมูล VPN ที่เข้ารหัสของคุณ หากมีใครกำลังเฝ้าดูการเชื่อมต่อของคุณอยู่ สิ่งนี้จะทำให้การระบุเว็บไซต์ที่คุณกำลังเยี่ยมชมยากขึ้นอย่างมาก ซึ่งทำได้โดยการเพิ่มสัญญาณรบกวนเครือข่ายอย่างระมัดระวัง และทำให้แพ็กเก็ตเครือข่ายทั้งหมดมีขนาดเท่ากันหมด</string>
+ <string name="daita_warning">โปรดทราบ: เนื่องจากการดำเนินการนี้จะเพิ่มการรับส่งข้อมูลโดยรวมของคุณขึ้น โปรดใช้ความระมัดระวัง หากคุณมีแผนข้อมูลที่มีปริมาณจำกัด การดำเนินการนี้อาจส่งผลเชิงลบต่อความเร็วเครือข่ายของคุณได้ โปรดพิจารณาข้อมูลเหล่านี้ หากคุณต้องการเปิดใช้งาน %1$s</string>
<string name="delete">ลบ</string>
<string name="delete_custom_list_confirmation_description">ลบ \"%1$s\" หรือไม่</string>
<string name="delete_custom_list_message">\"%1$s\" ถูกลบแล้ว</string>
@@ -133,6 +136,7 @@
<string name="edit_method">แก้ไขวิธี</string>
<string name="edit_name">แก้ไขชื่อ</string>
<string name="enable">เปิดใช้งาน</string>
+ <string name="enable_anyway">เปิดใช้งานต่อไป</string>
<string name="enable_custom_dns">ใช้เซิร์ฟเวอร์ DNS แบบกำหนดเอง</string>
<string name="enable_method">เปิดใช้งานวิธีการ</string>
<string name="enter_value_placeholder">ป้อน MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">รีเซ็ตโอเวอร์ไรด์ทั้งหมด</string>
<string name="set_dns_error">ไม่สามารถตั้งค่าเซิร์ฟเวอร์ DNS ของระบบได้ โปรดส่งรายงานปัญหา</string>
<string name="set_firewall_policy_error">ไม่สามารถใช้กฎไฟร์วอลล์ได้ โปรดแก้ไขปัญหา หรือส่งรายงานปัญหา</string>
+ <string name="setting_chip">การตั้งค่า: %1$s</string>
<string name="settings">การตั้งค่า</string>
<string name="settings_account">บัญชี</string>
<string name="settings_api_access">การเข้าถึง API</string>
diff --git a/android/lib/resource/src/main/res/values-tr/strings.xml b/android/lib/resource/src/main/res/values-tr/strings.xml
index b0d7207d21..d1f31fc53a 100644
--- a/android/lib/resource/src/main/res/values-tr/strings.xml
+++ b/android/lib/resource/src/main/res/values-tr/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">Evet, cihazdan çıkış yap</string>
<string name="congrats">Tebrikler!</string>
<string name="connect">Bağlantımı güvenceye al</string>
+ <string name="connected_using_daita">%1$s, %2$s kullanıyor</string>
<string name="connecting">Bağlanılıyor</string>
<string name="connecting_to_daemon">Mullvad sistem hizmetlerine bağlanılıyor...</string>
<string name="continue_login">Giriş yapmak için devam et</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">WireGuard özel portu</string>
<string name="custom_port_dialog_valid_ranges">Geçerli aralıklar: %1$s</string>
<string name="custom_tunnel_host_resolution_error">Özel tünel ana bilgisayarı çözülemedi. Ayarlarınızı değiştirmeyi deneyin.</string>
+ <string name="daita_info">%1$s (%2$s), şifrelenmiş VPN trafiğinizdeki kalıpları gizler. Bu sayede, başka biri bağlantınızı izliyorsa ziyaret ettiğiniz web sitelerini tespit etmesi çok daha zor olacaktır. Özellik, dikkatli bir şekilde ağ paraziti ekleyerek ve tüm ağ paketlerini aynı boyuta getirerek sizi izlenmekten korur.</string>
+ <string name="daita_warning">Dikkat: Bu özellik, toplam ağ trafiğinizi artıracağından dolayı sınırlı bir veri planınız varsa dikkatli olun. Bu, ağ hızınızı da olumsuz etkileyebilir. %1$s özelliğini etkinleştirmek istiyorsanız lütfen bu durumu göz önünde bulundurun.</string>
<string name="delete">Sil</string>
<string name="delete_custom_list_confirmation_description">\"%1$s\" silinsin mi\"?</string>
<string name="delete_custom_list_message">\"%1$s\" silindi</string>
@@ -133,6 +136,7 @@
<string name="edit_method">Yöntemi düzenle</string>
<string name="edit_name">Adı düzenle</string>
<string name="enable">Etkinleştir</string>
+ <string name="enable_anyway">Yine de etkinleştir</string>
<string name="enable_custom_dns">Özel DNS sunucusu kullanın</string>
<string name="enable_method">Yöntemi etkinleştir</string>
<string name="enter_value_placeholder">MTU\'yu girin</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">Tüm geçersiz kılmaları sıfırla</string>
<string name="set_dns_error">Sistem DNS sunucusu ayarlanamıyor. Lütfen bir hata raporu gönderin.</string>
<string name="set_firewall_policy_error">Güvenlik duvarı kuralları uygulanamıyor. Lütfen sorunu çözmeye çalışın veya bir hata raporu gönderin.</string>
+ <string name="setting_chip">Ayar: %1$s</string>
<string name="settings">Ayarlar</string>
<string name="settings_account">Hesap</string>
<string name="settings_api_access">API erişimi</string>
diff --git a/android/lib/resource/src/main/res/values-zh-rCN/strings.xml b/android/lib/resource/src/main/res/values-zh-rCN/strings.xml
index ff6879f9b8..222b9c007d 100644
--- a/android/lib/resource/src/main/res/values-zh-rCN/strings.xml
+++ b/android/lib/resource/src/main/res/values-zh-rCN/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">是,退出设备</string>
<string name="congrats">恭喜!</string>
<string name="connect">保护我的连接</string>
+ <string name="connected_using_daita">%1$s,使用 %2$s</string>
<string name="connecting">正在连接</string>
<string name="connecting_to_daemon">正在连接到 Mullvad 系统服务…</string>
<string name="continue_login">继续登录</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">WireGuard 自定义端口</string>
<string name="custom_port_dialog_valid_ranges">有效范围:%1$s</string>
<string name="custom_tunnel_host_resolution_error">无法解析自定义隧道的主机。请尝试更改您的设置。</string>
+ <string name="daita_info">%1$s(%2$s)会在您的加密 VPN 流量中隐藏模式。如果有人在监视您的连接,这可以让他们很难识别您正在访问的网站。它的实现方法是小心地添加网络噪声并使所有网络数据包的大小都相同。</string>
+ <string name="daita_warning">注意:这会增加您的总网络流量,因此如果您的流量套餐有限,请谨慎使用。它还会对您的网速产生负面影响。如果要启用 %1$s,请考虑到这一点。</string>
<string name="delete">删除</string>
<string name="delete_custom_list_confirmation_description">删除“%1$s”?</string>
<string name="delete_custom_list_message">“%1$s”已被删除</string>
@@ -133,6 +136,7 @@
<string name="edit_method">编辑方法</string>
<string name="edit_name">编辑名称</string>
<string name="enable">启用</string>
+ <string name="enable_anyway">仍然启用</string>
<string name="enable_custom_dns">使用自定义 DNS 服务器</string>
<string name="enable_method">启用方法</string>
<string name="enter_value_placeholder">输入 MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">重置所有覆盖设置</string>
<string name="set_dns_error">无法设置系统 DNS 服务器。请发送问题报告。</string>
<string name="set_firewall_policy_error">无法应用防火墙规则。请排查问题或发送问题报告。</string>
+ <string name="setting_chip">设置:%1$s</string>
<string name="settings">设置</string>
<string name="settings_account">帐户</string>
<string name="settings_api_access">API 访问</string>
diff --git a/android/lib/resource/src/main/res/values-zh-rTW/strings.xml b/android/lib/resource/src/main/res/values-zh-rTW/strings.xml
index fe531572b8..ed70785bb1 100644
--- a/android/lib/resource/src/main/res/values-zh-rTW/strings.xml
+++ b/android/lib/resource/src/main/res/values-zh-rTW/strings.xml
@@ -74,6 +74,7 @@
<string name="confirm_removal">是,將裝置登出</string>
<string name="congrats">恭喜!</string>
<string name="connect">保護我的連線</string>
+ <string name="connected_using_daita">%1$s,使用 %2$s</string>
<string name="connecting">正在連線</string>
<string name="connecting_to_daemon">連線 Mullvad 系統服務中...</string>
<string name="continue_login">繼續登入</string>
@@ -100,6 +101,8 @@
<string name="custom_port_dialog_title">WireGuard 自訂連接埠</string>
<string name="custom_port_dialog_valid_ranges">有效範圍:%1$s</string>
<string name="custom_tunnel_host_resolution_error">無法解析自訂通道的主機。請嘗試變更您的設定。</string>
+ <string name="daita_info">%1$s (%2$s) 會在您的加密 VPN 流量中隱藏模式。如果有人正在監視您的連線,這能讓他們難以識別出您正在存取的網站。此實現方式係謹慎加入網路噪音,並使所有網路資料包大小皆相同。</string>
+ <string name="daita_warning">注意:這會增加您的網路總流量。如果您方案中的流量有限,請謹慎使用。這還會對您的網路速度產生負面影響。如果要啟用 %1$s,請考慮到這一點。</string>
<string name="delete">刪除</string>
<string name="delete_custom_list_confirmation_description">要刪除「%1$s」嗎?</string>
<string name="delete_custom_list_message">「%1$s」已刪除</string>
@@ -133,6 +136,7 @@
<string name="edit_method">編輯方式</string>
<string name="edit_name">編輯名稱</string>
<string name="enable">啟用</string>
+ <string name="enable_anyway">仍然啟用</string>
<string name="enable_custom_dns">使用自訂 DNS 伺服器</string>
<string name="enable_method">啟用方式</string>
<string name="enter_value_placeholder">輸入 MTU</string>
@@ -288,6 +292,7 @@
<string name="server_ip_overrides_reset_title">重設所有覆寫設定</string>
<string name="set_dns_error">無法設定系統 DNS 伺服器。請傳送問題回報。</string>
<string name="set_firewall_policy_error">無法套用防火牆規則。請排除故障或傳送問題回報。</string>
+ <string name="setting_chip">設定:%1$s</string>
<string name="settings">設定</string>
<string name="settings_account">帳戶</string>
<string name="settings_api_access">API 存取</string>
diff --git a/android/lib/resource/src/main/res/values/strings.xml b/android/lib/resource/src/main/res/values/strings.xml
index 071f45ae23..b72902897f 100644
--- a/android/lib/resource/src/main/res/values/strings.xml
+++ b/android/lib/resource/src/main/res/values/strings.xml
@@ -385,4 +385,10 @@
<string name="failed_to_set_current_unknown_error">Failed to set to current - Unknown reason</string>
<string name="location_was_removed_from_list">%s was removed from \"%s\"</string>
<string name="create_custom_list_message">\"%s\" was created</string>
+ <string name="daita_info">%s (%s) hides patterns in your encrypted VPN traffic. If anyone is monitoring your connection, this makes it significantly harder for them to identify what websites you are visiting. It does this by carefully adding network noise and making all network packets the same size.</string>
+ <string name="daita_warning">Attention: Since this increases your total network traffic, be cautious if you have a limited data plan. It can also negatively impact your network speed. Please consider this if you want to enable %s.</string>
+ <string name="connected_using_daita">%s using %s</string>
+ <string name="setting_chip">Setting: %s</string>
+ <string name="enable_anyway">Enable anyway</string>
+ <string name="daita_relay_subset_warning">This feature isn’t available on all servers. You might need to change location after enabling.</string>
</resources>
diff --git a/android/lib/resource/src/main/res/values/strings_non_translatable.xml b/android/lib/resource/src/main/res/values/strings_non_translatable.xml
index 110e112e99..9cf571171a 100644
--- a/android/lib/resource/src/main/res/values/strings_non_translatable.xml
+++ b/android/lib/resource/src/main/res/values/strings_non_translatable.xml
@@ -14,4 +14,6 @@
<string name="local_network_sharing_ip_ranges">
<![CDATA[<ul><li>10.0.0.0/8</li><li>172.16.0.0/12</li><li>192.168.0.0/16</li><li>169.254.0.0/16</li><li>fe80::/10</li><li>fc00::/7</li></ul>]]>
</string>
+ <string name="daita">DAITA</string>
+ <string name="daita_full">Defence against AI-guided Traffic Analysis</string>
</resources>
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/FileResourceExtractor.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/FileResourceExtractor.kt
deleted file mode 100644
index 71a05e6743..0000000000
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/FileResourceExtractor.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package net.mullvad.mullvadvpn.service
-
-import android.content.Context
-import java.io.File
-import java.io.FileOutputStream
-
-class FileResourceExtractor(val context: Context) {
- fun extract(asset: String, force: Boolean = false) {
- val destination = File(context.filesDir, asset)
-
- if (!destination.exists() || force) {
- extractFile(asset, destination)
- }
- }
-
- private fun extractFile(asset: String, destination: File) {
- val destinationStream = FileOutputStream(destination)
-
- context.assets.open(asset).copyTo(destinationStream)
-
- destinationStream.close()
- }
-}
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
index 2db5a00fdb..ebdcbec780 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
@@ -10,7 +10,6 @@ import androidx.core.content.getSystemService
import androidx.lifecycle.lifecycleScope
import arrow.atomic.AtomicInt
import co.touchlab.kermit.Logger
-import java.io.File
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.launch
@@ -27,11 +26,13 @@ import net.mullvad.mullvadvpn.service.migration.MigrateSplitTunneling
import net.mullvad.mullvadvpn.service.notifications.ForegroundNotificationManager
import net.mullvad.mullvadvpn.service.notifications.NotificationChannelFactory
import net.mullvad.mullvadvpn.service.notifications.NotificationManager
+import net.mullvad.mullvadvpn.service.util.extractAndOverwriteIfAssetMoreRecent
import net.mullvad.talpid.TalpidVpnService
import org.koin.android.ext.android.getKoin
import org.koin.core.context.loadKoinModules
-private const val RELAYS_FILE = "relays.json"
+private const val RELAY_LIST_ASSET_NAME = "relays.json"
+private const val MAYBENOT_MACHINES_ASSET_NAME = "maybenot_machines"
class MullvadVpnService : TalpidVpnService() {
@@ -72,7 +73,7 @@ class MullvadVpnService : TalpidVpnService() {
keyguardManager = getSystemService<KeyguardManager>()!!
- prepareFiles(this@MullvadVpnService)
+ prepareFiles()
migrateSplitTunneling.migrate()
// If it is a debug build and we have an api override in the intent, use it
@@ -221,16 +222,11 @@ class MullvadVpnService : TalpidVpnService() {
return this?.action == SERVICE_INTERFACE
}
- private fun prepareFiles(context: Context) {
- val shouldOverwriteRelayList =
- lastUpdatedTime(context) > File(context.filesDir, RELAYS_FILE).lastModified()
-
- FileResourceExtractor(context).apply { extract(RELAYS_FILE, shouldOverwriteRelayList) }
+ private fun Context.prepareFiles() {
+ extractAndOverwriteIfAssetMoreRecent(RELAY_LIST_ASSET_NAME)
+ extractAndOverwriteIfAssetMoreRecent(MAYBENOT_MACHINES_ASSET_NAME)
}
- private fun lastUpdatedTime(context: Context): Long =
- context.packageManager.getPackageInfo(context.packageName, 0).lastUpdateTime
-
companion object {
init {
System.loadLibrary("mullvad_jni")
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ContextExtensions.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ContextExtensions.kt
new file mode 100644
index 0000000000..51240fa16d
--- /dev/null
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/util/ContextExtensions.kt
@@ -0,0 +1,23 @@
+package net.mullvad.mullvadvpn.service.util
+
+import android.content.Context
+import java.io.File
+import java.io.FileOutputStream
+
+fun Context.extractAndOverwriteIfAssetMoreRecent(assetName: String) {
+ val forceOverwriteIfMoreRecent = lastUpdatedTime() > File(filesDir, assetName).lastModified()
+ val destination = File(filesDir, assetName)
+
+ if (!destination.exists() || forceOverwriteIfMoreRecent) {
+ extractFile(assetName, destination)
+ }
+}
+
+private fun Context.lastUpdatedTime(): Long =
+ packageManager.getPackageInfo(packageName, 0).lastUpdateTime
+
+private fun Context.extractFile(asset: String, destination: File) {
+ val destinationStream = FileOutputStream(destination)
+ assets.open(asset).copyTo(destinationStream)
+ destinationStream.close()
+}