summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2024-08-26 15:48:37 +0200
committerAlbin <albin@mullvad.net>2024-09-06 14:59:55 +0200
commit3847c1eb82a324a4b5fff2a5e076750ebf4449c4 (patch)
tree55c45a4a75e56503e675fdad5418cbeafb850854 /android/app/src
parentd464325f98bc488f091ef18b4ba04e0d7dbe2605 (diff)
downloadmullvadvpn-3847c1eb82a324a4b5fff2a5e076750ebf4449c4.tar.xz
mullvadvpn-3847c1eb82a324a4b5fff2a5e076750ebf4449c4.zip
Add daita grpc and ui
Diffstat (limited to 'android/app/src')
-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
23 files changed, 350 insertions, 47 deletions
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),
)