summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt45
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreen.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/VpnSettingsUiState.kt1
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt5
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt13
-rw-r--r--android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt17
8 files changed, 91 insertions, 17 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
index 15b0d935b2..650c51d641 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
@@ -8,6 +8,7 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollToNode
import io.mockk.MockKAnnotations
+import io.mockk.coVerify
import io.mockk.mockk
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
@@ -27,6 +28,7 @@ import net.mullvad.mullvadvpn.lib.model.Mtu
import net.mullvad.mullvadvpn.lib.model.Port
import net.mullvad.mullvadvpn.lib.model.PortRange
import net.mullvad.mullvadvpn.lib.model.QuantumResistantState
+import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation
import net.mullvad.mullvadvpn.onNodeWithTagAndText
import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem
import org.junit.jupiter.api.BeforeEach
@@ -209,15 +211,18 @@ class VpnSettingsScreenTest {
}
@Test
- fun testShowTcpOverUdpPortOptions() =
+ fun testSelectTcpOverUdpPortOption() =
composeExtension.use {
// Arrange
+ val onObfuscationPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true)
setContentWithTheme {
VpnSettingsScreen(
state =
VpnSettingsUiState.createDefault(
+ selectedObfuscation = SelectedObfuscation.Udp2Tcp,
selectedObfuscationPort = Constraint.Only(Port(5001))
),
+ onObfuscationPortSelected = onObfuscationPortSelected
)
}
@@ -236,6 +241,44 @@ class VpnSettingsScreenTest {
text = "5001"
)
.assertExists()
+ .performClick()
+
+ coVerify(exactly = 1) { onObfuscationPortSelected.invoke(Constraint.Only(Port(5001))) }
+ }
+
+ @Test
+ fun testAttemptSelectTcpOverUdpPortOption() =
+ composeExtension.use {
+ // Arrange
+ val onObfuscationPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ state =
+ VpnSettingsUiState.createDefault(
+ selectedObfuscation = SelectedObfuscation.Off,
+ ),
+ onObfuscationPortSelected = onObfuscationPortSelected
+ )
+ }
+
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG))
+ onNodeWithText("UDP-over-TCP port").performClick()
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(
+ hasTestTag(String.format(LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG, 5001))
+ )
+
+ // Assert
+ onNodeWithTagAndText(
+ testTag = String.format(LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_X_TEST_TAG, 5001),
+ text = "5001"
+ )
+ .assertExists()
+ .performClick()
+
+ verify(exactly = 0) { onObfuscationPortSelected.invoke(any()) }
}
@Test
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt
index d69194490e..a4cd9b9548 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SelectableCell.kt
@@ -17,6 +17,7 @@ import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.component.SpacedColumn
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
+import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled
import net.mullvad.mullvadvpn.lib.theme.color.AlphaInvisible
import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible
import net.mullvad.mullvadvpn.lib.theme.color.selected
@@ -36,6 +37,7 @@ private fun PreviewSelectableCell() {
fun SelectableCell(
title: String,
isSelected: Boolean,
+ isEnabled: Boolean = true,
iconContentDescription: String? = null,
selectedIcon: @Composable RowScope.() -> Unit = {
Icon(
@@ -44,7 +46,10 @@ fun SelectableCell(
tint = MaterialTheme.colorScheme.onPrimary,
modifier =
Modifier.padding(end = Dimens.selectableCellTextMargin)
- .alpha(if (isSelected) AlphaVisible else AlphaInvisible)
+ .alpha(
+ if (isSelected && !isEnabled) AlphaDisabled
+ else if (isSelected) AlphaVisible else AlphaInvisible
+ )
)
},
titleStyle: TextStyle = MaterialTheme.typography.labelLarge,
@@ -56,7 +61,16 @@ fun SelectableCell(
) {
BaseCell(
onCellClicked = onCellClicked,
- headlineContent = { BaseCellTitle(title = title, style = titleStyle) },
+ isRowEnabled = isEnabled,
+ headlineContent = {
+ BaseCellTitle(
+ title = title,
+ style = titleStyle,
+ color =
+ if (isEnabled) MaterialTheme.colorScheme.onPrimary
+ else MaterialTheme.colorScheme.onPrimary.copy(AlphaDisabled)
+ )
+ },
background =
if (isSelected) {
selectedColor
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt
index f74349113c..11045fa617 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt
@@ -28,6 +28,7 @@ import net.mullvad.mullvadvpn.compose.component.textResource
import net.mullvad.mullvadvpn.compose.extensions.toAnnotatedString
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
+import net.mullvad.mullvadvpn.lib.theme.color.AlphaDisabled
@Preview
@Composable
@@ -67,7 +68,10 @@ fun NormalSwitchComposeCell(
BaseCellTitle(
title = title,
style = MaterialTheme.typography.labelLarge,
- modifier = Modifier.weight(1f, true)
+ modifier = Modifier.weight(1f, true),
+ color =
+ if (isEnabled) MaterialTheme.colorScheme.onPrimary
+ else MaterialTheme.colorScheme.onPrimary.copy(AlphaDisabled)
)
},
isToggled = isToggled,
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 3332aa264e..41b4ea8a2e 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
@@ -594,6 +594,7 @@ fun VpnSettingsScreen(
ExpandableComposeCell(
title = stringResource(R.string.udp_over_tcp_port_title),
isExpanded = expandUdp2TcpPortSettings,
+ isEnabled = state.selectedObfuscation != SelectedObfuscation.Off,
onInfoClicked = navigateUdp2TcpInfo,
onCellClicked = { expandUdp2TcpPortSettings = !expandUdp2TcpPortSettings },
testTag = LAZY_LIST_UDP_OVER_TCP_PORT_TEST_TAG
@@ -605,6 +606,7 @@ fun VpnSettingsScreen(
SelectableCell(
title = stringResource(id = R.string.automatic),
isSelected = state.selectedObfuscationPort is Constraint.Any,
+ isEnabled = state.selectObfuscationPortEnabled,
onCellClicked = { onObfuscationPortSelected(Constraint.Any) },
testTag = LAZY_LIST_UDP_OVER_TCP_PORT_ITEM_AUTOMATIC_TEST_TAG,
)
@@ -615,6 +617,7 @@ fun VpnSettingsScreen(
SelectableCell(
title = port.toString(),
isSelected = state.selectedObfuscationPort.hasValue(port),
+ isEnabled = state.selectObfuscationPortEnabled,
onCellClicked = {
onObfuscationPortSelected(Constraint.Only(Port(port)))
},
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 cefc5edb7a..17eb69d380 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
@@ -24,6 +24,7 @@ data class VpnSettingsUiState(
val availablePortRanges: List<PortRange>,
val systemVpnSettingsAvailable: Boolean,
) {
+ val selectObfuscationPortEnabled = selectedObfuscation != SelectedObfuscation.Off
companion object {
fun createDefault(
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 a1a1ed007a..7a9be0303a 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
@@ -14,9 +14,9 @@ import net.mullvad.mullvadvpn.lib.model.DefaultDnsOptions
import net.mullvad.mullvadvpn.lib.model.DnsOptions
import net.mullvad.mullvadvpn.lib.model.DnsState
import net.mullvad.mullvadvpn.lib.model.Mtu
-import net.mullvad.mullvadvpn.lib.model.ObfuscationSettings
import net.mullvad.mullvadvpn.lib.model.Port
import net.mullvad.mullvadvpn.lib.model.QuantumResistantState
+import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation
import net.mullvad.mullvadvpn.lib.model.Settings
class SettingsRepository(
@@ -64,8 +64,7 @@ class SettingsRepository(
suspend fun setWireguardQuantumResistant(value: QuantumResistantState) =
managementService.setWireguardQuantumResistant(value)
- suspend fun setObfuscationOptions(value: ObfuscationSettings) =
- managementService.setObfuscationOptions(value)
+ suspend fun setObfuscation(value: SelectedObfuscation) = managementService.setObfuscation(value)
suspend fun setAutoConnect(isEnabled: Boolean) = managementService.setAutoConnect(isEnabled)
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 0ad91af8cc..a0a38ef6f8 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
@@ -22,12 +22,10 @@ import net.mullvad.mullvadvpn.compose.state.VpnSettingsUiState
import net.mullvad.mullvadvpn.lib.model.Constraint
import net.mullvad.mullvadvpn.lib.model.DefaultDnsOptions
import net.mullvad.mullvadvpn.lib.model.DnsState
-import net.mullvad.mullvadvpn.lib.model.ObfuscationSettings
import net.mullvad.mullvadvpn.lib.model.Port
import net.mullvad.mullvadvpn.lib.model.QuantumResistantState
import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation
import net.mullvad.mullvadvpn.lib.model.Settings
-import net.mullvad.mullvadvpn.lib.model.Udp2TcpObfuscationSettings
import net.mullvad.mullvadvpn.lib.model.WireguardConstraints
import net.mullvad.mullvadvpn.repository.RelayListRepository
import net.mullvad.mullvadvpn.repository.SettingsRepository
@@ -206,14 +204,9 @@ class VpnSettingsViewModel(
fun onSelectObfuscationSetting(selectedObfuscation: SelectedObfuscation) {
viewModelScope.launch(dispatcher) {
- repository
- .setObfuscationOptions(
- ObfuscationSettings(
- selectedObfuscation = selectedObfuscation,
- udp2tcp = Udp2TcpObfuscationSettings(Constraint.Any)
- )
- )
- .onLeft { _uiSideEffect.send(VpnSettingsSideEffect.ShowToast.GenericError) }
+ repository.setObfuscation(selectedObfuscation).onLeft {
+ _uiSideEffect.send(VpnSettingsSideEffect.ShowToast.GenericError)
+ }
}
}
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 268f664840..4c4bdc623a 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
@@ -87,6 +87,7 @@ import net.mullvad.mullvadvpn.lib.model.RelayList as ModelRelayList
import net.mullvad.mullvadvpn.lib.model.RelayList
import net.mullvad.mullvadvpn.lib.model.RelaySettings
import net.mullvad.mullvadvpn.lib.model.RemoveSplitTunnelingAppError
+import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation
import net.mullvad.mullvadvpn.lib.model.SetAllowLanError
import net.mullvad.mullvadvpn.lib.model.SetAutoConnectError
import net.mullvad.mullvadvpn.lib.model.SetDnsOptionsError
@@ -109,6 +110,7 @@ import net.mullvad.mullvadvpn.lib.model.location
import net.mullvad.mullvadvpn.lib.model.ownership
import net.mullvad.mullvadvpn.lib.model.providers
import net.mullvad.mullvadvpn.lib.model.relayConstraints
+import net.mullvad.mullvadvpn.lib.model.selectedObfuscation
import net.mullvad.mullvadvpn.lib.model.state
import net.mullvad.mullvadvpn.lib.model.udp2tcp
import net.mullvad.mullvadvpn.lib.model.wireguardConstraints
@@ -390,6 +392,21 @@ class ManagementService(
.mapLeft(SetObfuscationOptionsError::Unknown)
.mapEmpty()
+ suspend fun setObfuscation(
+ value: SelectedObfuscation
+ ): Either<SetObfuscationOptionsError, Unit> =
+ Either.catch {
+ val updatedObfuscationSettings =
+ ObfuscationSettings.selectedObfuscation.modify(
+ getSettings().obfuscationSettings
+ ) {
+ value
+ }
+ grpc.setObfuscationSettings(updatedObfuscationSettings.fromDomain())
+ }
+ .mapLeft(SetObfuscationOptionsError::Unknown)
+ .mapEmpty()
+
suspend fun setObfuscationPort(
portConstraint: Constraint<Port>
): Either<SetObfuscationOptionsError, Unit> = either {