summaryrefslogtreecommitdiffhomepage
path: root/android/app/src
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2023-05-15 17:00:50 +0200
committerAlbin <albin@mullvad.net>2023-05-15 17:00:50 +0200
commitb3821d62c16eda5141f7b4e5eba582d90966f4e2 (patch)
tree9d128bd932df0a405081da8064bd74afbd47e96f /android/app/src
parent6e36ff8295cbd91e1fbac9d6fa92d97c05f09017 (diff)
parent26b857acd0701c741687e76f4f0b2a352e607c08 (diff)
downloadmullvadvpn-b3821d62c16eda5141f7b4e5eba582d90966f4e2.tar.xz
mullvadvpn-b3821d62c16eda5141f7b4e5eba582d90966f4e2.zip
Merge remote-tracking branch 'origin/migrate-preferences-view-to-compose-droid-57'
Diffstat (limited to 'android/app/src')
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt60
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/LocalNetworkSharingInfoDialog.kt19
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt41
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt41
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt4
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/PreferencesFragment.kt130
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SettingsFragment.kt7
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt28
-rw-r--r--android/app/src/main/res/layout/preferences.xml60
-rw-r--r--android/app/src/main/res/layout/settings.xml5
-rw-r--r--android/app/src/main/res/values/strings.xml2
-rw-r--r--android/app/src/main/res/values/strings_non_translatable.xml3
16 files changed, 200 insertions, 243 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt
index 340b903886..970e877b80 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingsScreenTest.kt
@@ -3,10 +3,13 @@ package net.mullvad.mullvadvpn.compose.screen
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.hasTestTag
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performScrollToNode
import androidx.compose.ui.test.performTextInput
import io.mockk.MockKAnnotations
import io.mockk.mockk
@@ -15,6 +18,8 @@ import io.mockk.verifyAll
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import net.mullvad.mullvadvpn.compose.state.AdvancedSettingsUiState
+import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_LAST_ITEM_TEST_TAG
+import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_TEST_TAG
import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem
import net.mullvad.mullvadvpn.viewmodel.StagedDns
import org.junit.Before
@@ -249,13 +254,15 @@ class AdvancedSettingsScreenTest {
listOf(
CustomDnsItem(address = DUMMY_DNS_ADDRESS, false),
CustomDnsItem(address = DUMMY_DNS_ADDRESS_2, false),
- CustomDnsItem(address = DUMMY_DNS_ADDRESS_3, false),
- ),
+ CustomDnsItem(address = DUMMY_DNS_ADDRESS_3, false)
+ )
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
}
-
+ composeTestRule
+ .onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
// Assert
composeTestRule.apply {
onNodeWithText(DUMMY_DNS_ADDRESS).assertExists()
@@ -274,12 +281,14 @@ class AdvancedSettingsScreenTest {
uiState =
AdvancedSettingsUiState.DefaultUiState(
isCustomDnsEnabled = false,
- customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false)),
+ customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false))
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
}
-
+ composeTestRule
+ .onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
// Assert
composeTestRule.onNodeWithText(DUMMY_DNS_ADDRESS).assertDoesNotExist()
composeTestRule.onNodeWithText("Add a server").assertDoesNotExist()
@@ -296,7 +305,7 @@ class AdvancedSettingsScreenTest {
isCustomDnsEnabled = true,
isAllowLanEnabled = true,
customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true)),
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true))
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -317,7 +326,7 @@ class AdvancedSettingsScreenTest {
isCustomDnsEnabled = true,
isAllowLanEnabled = false,
customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false)),
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false))
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -338,7 +347,7 @@ class AdvancedSettingsScreenTest {
isCustomDnsEnabled = true,
isAllowLanEnabled = true,
customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false)),
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false))
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -359,7 +368,7 @@ class AdvancedSettingsScreenTest {
isCustomDnsEnabled = true,
isAllowLanEnabled = false,
customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true)),
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true))
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -383,6 +392,9 @@ class AdvancedSettingsScreenTest {
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
}
+ composeTestRule
+ .onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
// Act
composeTestRule.onNodeWithText("Add a server").performClick()
@@ -401,7 +413,7 @@ class AdvancedSettingsScreenTest {
AdvancedSettingsUiState.DnsDialogUiState(
stagedDns =
StagedDns.NewDns(
- item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false),
+ item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false)
),
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
@@ -423,8 +435,8 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.EditDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false),
- index = 0,
- ),
+ index = 0
+ )
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -445,9 +457,9 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.NewDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = true),
- validationResult = StagedDns.ValidationResult.Success,
+ validationResult = StagedDns.ValidationResult.Success
),
- isAllowLanEnabled = false,
+ isAllowLanEnabled = false
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -468,9 +480,9 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.NewDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = true),
- validationResult = StagedDns.ValidationResult.Success,
+ validationResult = StagedDns.ValidationResult.Success
),
- isAllowLanEnabled = true,
+ isAllowLanEnabled = true
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -491,9 +503,9 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.NewDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false),
- validationResult = StagedDns.ValidationResult.Success,
+ validationResult = StagedDns.ValidationResult.Success
),
- isAllowLanEnabled = true,
+ isAllowLanEnabled = true
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -514,9 +526,9 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.NewDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false),
- validationResult = StagedDns.ValidationResult.Success,
+ validationResult = StagedDns.ValidationResult.Success
),
- isAllowLanEnabled = false,
+ isAllowLanEnabled = false
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -537,8 +549,8 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.NewDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false),
- validationResult = StagedDns.ValidationResult.InvalidAddress,
- ),
+ validationResult = StagedDns.ValidationResult.InvalidAddress
+ )
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
@@ -559,8 +571,8 @@ class AdvancedSettingsScreenTest {
stagedDns =
StagedDns.NewDns(
item = CustomDnsItem(DUMMY_DNS_ADDRESS, isLocal = false),
- validationResult = StagedDns.ValidationResult.DuplicateAddress,
- ),
+ validationResult = StagedDns.ValidationResult.DuplicateAddress
+ )
),
toastMessagesSharedFlow = MutableSharedFlow<String>().asSharedFlow()
)
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 980af59693..0b5508d524 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
@@ -46,13 +46,14 @@ private fun PreviewSwitchComposeCell() {
fun SwitchComposeCell(
title: String,
isToggled: Boolean,
+ subtitle: String? = null,
isEnabled: Boolean = true,
background: Color = MullvadBlue,
onCellClicked: (Boolean) -> Unit = {},
onInfoClicked: (() -> Unit)? = null
) {
- val subtitleModifier = Modifier
+ val textSize = dimensionResource(id = R.dimen.text_small).value.sp
BaseCell(
title = {
SwitchCellTitle(
@@ -60,6 +61,10 @@ fun SwitchComposeCell(
modifier = Modifier.alpha(if (isEnabled) AlphaActive else AlphaInactive)
)
},
+ subtitle =
+ subtitle?.let {
+ @Composable { Text(text = it, fontSize = textSize, color = MullvadWhite60) }
+ },
isRowEnabled = isEnabled,
bodyView = {
SwitchCellView(
@@ -70,8 +75,7 @@ fun SwitchComposeCell(
)
},
background = background,
- onCellClicked = { onCellClicked(!isToggled) },
- subtitleModifier = subtitleModifier
+ onCellClicked = { onCellClicked(!isToggled) }
)
}
@@ -100,7 +104,7 @@ fun SwitchCellView(
val verticalPadding = 13.dp
Row(
modifier = modifier.wrapContentWidth().wrapContentHeight(),
- verticalAlignment = Alignment.CenterVertically,
+ verticalAlignment = Alignment.CenterVertically
) {
if (onInfoClicked != null) {
Icon(
@@ -110,7 +114,7 @@ fun SwitchCellView(
start = horizontalPadding,
end = horizontalPadding,
top = verticalPadding,
- bottom = verticalPadding,
+ bottom = verticalPadding
)
.align(Alignment.CenterVertically),
painter = painterResource(id = R.drawable.icon_info),
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/LocalNetworkSharingInfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/LocalNetworkSharingInfoDialog.kt
new file mode 100644
index 0000000000..89ef3cb3a6
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/LocalNetworkSharingInfoDialog.kt
@@ -0,0 +1,19 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.component.textResource
+
+@Composable
+fun LocalNetworkSharingInfoDialog(onDismiss: () -> Unit) {
+ InfoDialog(
+ message = stringResource(id = R.string.local_network_sharing_info),
+ additionalInfo =
+ buildString {
+ appendLine(stringResource(id = R.string.local_network_sharing_additional_info))
+ appendLine(textResource(id = R.string.local_network_sharing_ip_ranges))
+ },
+ onDismiss = onDismiss
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt
index c07d188e42..56aedb69ca 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt
@@ -28,6 +28,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@@ -58,11 +59,14 @@ import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.compose.dialog.ContentBlockersInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.CustomDnsInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.DnsDialog
+import net.mullvad.mullvadvpn.compose.dialog.LocalNetworkSharingInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.MalwareInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.MtuDialog
import net.mullvad.mullvadvpn.compose.dialog.ObfuscationInfoDialog
import net.mullvad.mullvadvpn.compose.extensions.itemWithDivider
import net.mullvad.mullvadvpn.compose.state.AdvancedSettingsUiState
+import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_LAST_ITEM_TEST_TAG
+import net.mullvad.mullvadvpn.compose.test.LAZY_LIST_TEST_TAG
import net.mullvad.mullvadvpn.compose.theme.MullvadBlue20
import net.mullvad.mullvadvpn.compose.theme.MullvadDarkBlue
import net.mullvad.mullvadvpn.compose.theme.MullvadGreen
@@ -76,6 +80,7 @@ private fun PreviewAdvancedSettings() {
AdvancedSettingScreen(
uiState =
AdvancedSettingsUiState.DefaultUiState(
+ isAutoConnectEnabled = true,
mtu = "1337",
isCustomDnsEnabled = true,
customDnsItems = listOf(CustomDnsItem("0.0.0.0", false)),
@@ -86,6 +91,8 @@ private fun PreviewAdvancedSettings() {
onRestoreMtuClick = {},
onCancelMtuDialogClicked = {},
onSplitTunnelingNavigationClick = {},
+ onToggleAutoConnect = {},
+ onToggleLocalNetworkSharing = {},
onToggleDnsClick = {},
onToggleBlockAds = {},
onToggleBlockTrackers = {},
@@ -97,6 +104,7 @@ private fun PreviewAdvancedSettings() {
onSaveDnsClick = {},
onRemoveDnsClick = {},
onCancelDnsDialogClick = {},
+ onLocalNetworkSharingInfoClick = {},
onContentsBlockersInfoClicked = {},
onMalwareInfoClicked = {},
onCustomDnsInfoClicked = {},
@@ -121,6 +129,8 @@ fun AdvancedSettingScreen(
onRestoreMtuClick: () -> Unit = {},
onCancelMtuDialogClicked: () -> Unit = {},
onSplitTunnelingNavigationClick: () -> Unit = {},
+ onToggleAutoConnect: (Boolean) -> Unit = {},
+ onToggleLocalNetworkSharing: (Boolean) -> Unit = {},
onToggleDnsClick: (Boolean) -> Unit = {},
onToggleBlockAds: (Boolean) -> Unit = {},
onToggleBlockTrackers: (Boolean) -> Unit = {},
@@ -132,6 +142,7 @@ fun AdvancedSettingScreen(
onSaveDnsClick: () -> Unit = {},
onRemoveDnsClick: () -> Unit = {},
onCancelDnsDialogClick: () -> Unit = {},
+ onLocalNetworkSharingInfoClick: () -> Unit = {},
onContentsBlockersInfoClicked: () -> Unit = {},
onMalwareInfoClicked: () -> Unit = {},
onCustomDnsInfoClicked: () -> Unit = {},
@@ -165,6 +176,9 @@ fun AdvancedSettingScreen(
onDismiss = { onCancelDnsDialogClick() }
)
}
+ is AdvancedSettingsUiState.LocalNetworkSharingInfoDialogUiState -> {
+ LocalNetworkSharingInfoDialog(onDismissInfoClicked)
+ }
is AdvancedSettingsUiState.ContentBlockersInfoDialogUiState -> {
ContentBlockersInfoDialog(onDismissInfoClicked)
}
@@ -229,12 +243,36 @@ fun AdvancedSettingScreen(
LazyColumn(
modifier =
Modifier.drawVerticalScrollbar(lazyListState)
+ .testTag(LAZY_LIST_TEST_TAG)
.fillMaxWidth()
.wrapContentHeight()
.animateContentSize(),
state = lazyListState
) {
- item { MtuComposeCell(mtuValue = uiState.mtu, onEditMtu = { onMtuCellClick() }) }
+ item {
+ Spacer(modifier = Modifier.height(cellVerticalSpacing))
+ SwitchComposeCell(
+ title = stringResource(R.string.auto_connect),
+ subtitle = stringResource(id = R.string.auto_connect_footer),
+ isToggled = uiState.isAutoConnectEnabled,
+ isEnabled = true,
+ onCellClicked = { newValue -> onToggleAutoConnect(newValue) }
+ )
+ }
+ item {
+ Spacer(modifier = Modifier.height(cellVerticalSpacing))
+ SwitchComposeCell(
+ title = stringResource(R.string.local_network_sharing),
+ isToggled = uiState.isAllowLanEnabled,
+ isEnabled = true,
+ onCellClicked = { newValue -> onToggleLocalNetworkSharing(newValue) },
+ onInfoClicked = { onLocalNetworkSharingInfoClick() }
+ )
+ }
+ item {
+ Spacer(modifier = Modifier.height(cellVerticalSpacing))
+ MtuComposeCell(mtuValue = uiState.mtu, onEditMtu = { onMtuCellClick() })
+ }
itemWithDivider {
NavigationComposeCell(
@@ -417,6 +455,7 @@ fun AdvancedSettingScreen(
isCellClickable = uiState.contentBlockersOptions.isAnyBlockerEnabled().not(),
modifier =
Modifier.background(MullvadDarkBlue)
+ .testTag(LAZY_LIST_LAST_ITEM_TEST_TAG)
.padding(
start = cellHorizontalSpacing,
top = topPadding,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt
index f08a654078..261714f8f9 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt
@@ -7,6 +7,8 @@ import net.mullvad.mullvadvpn.viewmodel.StagedDns
sealed interface AdvancedSettingsUiState {
val mtu: String
+ val isAutoConnectEnabled: Boolean
+ val isLocalNetworkSharingEnabled: Boolean
val isCustomDnsEnabled: Boolean
val customDnsItems: List<CustomDnsItem>
val contentBlockersOptions: DefaultDnsOptions
@@ -15,66 +17,91 @@ sealed interface AdvancedSettingsUiState {
data class DefaultUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
data class MtuDialogUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
val mtuEditValue: String,
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
data class DnsDialogUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
val stagedDns: StagedDns,
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
+ ) : AdvancedSettingsUiState
+
+ data class LocalNetworkSharingInfoDialogUiState(
+ override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
+ override val isCustomDnsEnabled: Boolean = false,
+ override val isAllowLanEnabled: Boolean = false,
+ override val customDnsItems: List<CustomDnsItem> = listOf(),
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
data class ContentBlockersInfoDialogUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
data class CustomDnsInfoDialogUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
data class MalwareInfoDialogUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
data class ObfuscationInfoDialogUiState(
override val mtu: String = "",
+ override val isAutoConnectEnabled: Boolean = false,
+ override val isLocalNetworkSharingEnabled: Boolean = false,
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
- override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off,
+ override val selectedObfuscation: SelectedObfuscation = SelectedObfuscation.Off
) : AdvancedSettingsUiState
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt
new file mode 100644
index 0000000000..55251eb3ea
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/test/ComposeTestTagConstants.kt
@@ -0,0 +1,4 @@
+package net.mullvad.mullvadvpn.compose.test
+
+const val LAZY_LIST_TEST_TAG = "lazy_list_test_tag"
+const val LAZY_LIST_LAST_ITEM_TEST_TAG = "lazy_list_last_item_test_tag"
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 9ab6eb412f..c0b9215d37 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
@@ -50,10 +50,6 @@ class SettingsRepository(
)
}
- fun isLocalNetworkSharingEnabled(): Boolean {
- return serviceConnectionManager.settingsListener()?.allowLan ?: false
- }
-
fun setWireguardMtu(value: Int?) {
serviceConnectionManager.settingsListener()?.wireguardMtu = value
}
@@ -61,4 +57,12 @@ class SettingsRepository(
fun setObfuscationOptions(value: ObfuscationSettings) {
serviceConnectionManager.settingsListener()?.obfuscationSettings = value
}
+
+ fun setAutoConnect(isEnabled: Boolean) {
+ serviceConnectionManager.settingsListener()?.autoConnect = isEnabled
+ }
+
+ fun setLocalNetworkSharing(isEnabled: Boolean) {
+ serviceConnectionManager.settingsListener()?.allowLan = isEnabled
+ }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt
index 4bd7ea35b8..a7dbc8116d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt
@@ -34,6 +34,8 @@ class AdvancedFragment : BaseFragment() {
onRestoreMtuClick = vm::onRestoreMtuClick,
onCancelMtuDialogClicked = vm::onCancelDialogClick,
onSplitTunnelingNavigationClick = ::openSplitTunnelingFragment,
+ onToggleAutoConnect = vm::onToggleAutoConnect,
+ onToggleLocalNetworkSharing = vm::onToggleLocalNetworkSharing,
onToggleDnsClick = vm::onToggleDnsClick,
onToggleBlockAds = vm::onToggleBlockAds,
onToggleBlockTrackers = vm::onToggleBlockTrackers,
@@ -45,6 +47,7 @@ class AdvancedFragment : BaseFragment() {
onSaveDnsClick = vm::onSaveDnsClick,
onRemoveDnsClick = vm::onRemoveDnsClick,
onCancelDnsDialogClick = vm::onCancelDialogClick,
+ onLocalNetworkSharingInfoClick = vm::onLocalNetworkSharingInfoClick,
onContentsBlockersInfoClicked = vm::onContentsBlockerInfoClick,
onCustomDnsInfoClicked = vm::onCustomDnsInfoClick,
onMalwareInfoClicked = vm::onMalwareInfoClick,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/PreferencesFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/PreferencesFragment.kt
deleted file mode 100644
index 9e4631c9e3..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/PreferencesFragment.kt
+++ /dev/null
@@ -1,130 +0,0 @@
-package net.mullvad.mullvadvpn.ui.fragment
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.lifecycleScope
-import androidx.lifecycle.repeatOnLifecycle
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.emptyFlow
-import kotlinx.coroutines.flow.flatMapLatest
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.model.Settings
-import net.mullvad.mullvadvpn.ui.CollapsibleTitleController
-import net.mullvad.mullvadvpn.ui.extension.requireMainActivity
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
-import net.mullvad.mullvadvpn.ui.serviceconnection.settingsListener
-import net.mullvad.mullvadvpn.ui.widget.CellSwitch
-import net.mullvad.mullvadvpn.ui.widget.ToggleCell
-import net.mullvad.mullvadvpn.util.JobTracker
-import net.mullvad.mullvadvpn.util.callbackFlowFromNotifier
-import org.koin.android.ext.android.inject
-
-class PreferencesFragment : BaseFragment() {
-
- // Injected dependencies
- private val serviceConnectionManager: ServiceConnectionManager by inject()
-
- private lateinit var allowLanToggle: ToggleCell
- private lateinit var autoConnectToggle: ToggleCell
- private lateinit var titleController: CollapsibleTitleController
-
- @Deprecated("Refactor code to instead rely on Lifecycle.") private val jobTracker = JobTracker()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- lifecycleScope.launchUiSubscriptionsOnResume()
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- val view = inflater.inflate(R.layout.preferences, container, false)
-
- view.findViewById<View>(R.id.back).setOnClickListener {
- requireMainActivity().onBackPressed()
- }
-
- allowLanToggle =
- view.findViewById<ToggleCell>(R.id.allow_lan).apply {
- listener = { state ->
- serviceConnectionManager.settingsListener()?.allowLan =
- when (state) {
- CellSwitch.State.ON -> true
- else -> false
- }
- }
- }
-
- autoConnectToggle =
- view.findViewById<ToggleCell>(R.id.auto_connect).apply {
- listener = { state ->
- serviceConnectionManager.settingsListener()?.autoConnect =
- when (state) {
- CellSwitch.State.ON -> true
- else -> false
- }
- }
- }
-
- titleController = CollapsibleTitleController(view)
-
- return view
- }
-
- override fun onDestroyView() {
- titleController.onDestroy()
- super.onDestroyView()
- }
-
- private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch {
- repeatOnLifecycle(Lifecycle.State.RESUMED) { launchSettingsSubscription() }
- }
-
- private fun CoroutineScope.launchSettingsSubscription() = launch {
- serviceConnectionManager.connectionState
- .flatMapLatest { state ->
- if (state is ServiceConnectionState.ConnectedReady) {
- flowOf(state.container)
- } else {
- emptyFlow()
- }
- }
- .flatMapLatest { callbackFlowFromNotifier(it.settingsListener.settingsNotifier) }
- .collect { settings ->
- if (settings != null) {
- updateUi(settings)
- }
- }
- }
-
- private fun updateUi(settings: Settings) {
- jobTracker.newUiJob("updateUi") {
- val allowLanState = boolToSwitchState(settings.allowLan)
- val autoConnectState = boolToSwitchState(settings.autoConnect)
-
- if (isVisible) {
- allowLanToggle.state = allowLanState
- autoConnectToggle.state = autoConnectState
- } else {
- allowLanToggle.forcefullySetState(allowLanState)
- autoConnectToggle.forcefullySetState(autoConnectState)
- }
- }
- }
-
- private fun boolToSwitchState(pref: Boolean): CellSwitch.State {
- if (pref) {
- return CellSwitch.State.ON
- } else {
- return CellSwitch.State.OFF
- }
- }
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SettingsFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SettingsFragment.kt
index 777f014aa0..ff3a8edcf0 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SettingsFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SettingsFragment.kt
@@ -47,7 +47,6 @@ class SettingsFragment : BaseFragment(), StatusBarPainter, NavigationBarPainter
private lateinit var accountMenu: AccountCell
private lateinit var appVersionMenu: AppVersionCell
- private lateinit var preferencesMenu: View
private lateinit var advancedMenu: View
private lateinit var titleController: CollapsibleTitleController
@@ -72,11 +71,6 @@ class SettingsFragment : BaseFragment(), StatusBarPainter, NavigationBarPainter
targetFragment = AccountFragment::class
}
- preferencesMenu =
- view.findViewById<NavigateCell>(R.id.preferences).apply {
- targetFragment = PreferencesFragment::class
- }
-
advancedMenu =
view.findViewById<NavigateCell>(R.id.advanced).apply {
targetFragment = AdvancedFragment::class
@@ -185,7 +179,6 @@ class SettingsFragment : BaseFragment(), StatusBarPainter, NavigationBarPainter
}
accountMenu.visibility = visibility
- preferencesMenu.visibility = visibility
advancedMenu.visibility = visibility
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt
index 1d353f5457..6990b7036e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt
@@ -46,6 +46,8 @@ class AdvancedSettingsViewModel(
combine(repository.settingsUpdates, dialogState) { settings, dialogState ->
AdvancedSettingsViewModelState(
mtuValue = settings?.mtuString() ?: "",
+ isAutoConnectEnabled = settings?.autoConnect ?: false,
+ isLocalNetworkSharingEnabled = settings?.allowLan ?: false,
isCustomDnsEnabled = settings?.isCustomDnsEnabled() ?: false,
customDnsList = settings?.addresses()?.asStringAddressList() ?: listOf(),
contentBlockersOptions = settings?.contentBlockersSettings()
@@ -100,6 +102,10 @@ class AdvancedSettingsViewModel(
hideDialog()
}
+ fun onLocalNetworkSharingInfoClick() {
+ dialogState.update { AdvancedSettingsDialogState.LocalNetworkSharingInfoDialog }
+ }
+
fun onContentsBlockerInfoClick() {
dialogState.update { AdvancedSettingsDialogState.ContentBlockersInfoDialog }
}
@@ -210,6 +216,14 @@ class AdvancedSettingsViewModel(
hideDialog()
}
+ fun onToggleAutoConnect(isEnabled: Boolean) {
+ viewModelScope.launch(dispatcher) { repository.setAutoConnect(isEnabled) }
+ }
+
+ fun onToggleLocalNetworkSharing(isEnabled: Boolean) {
+ viewModelScope.launch(dispatcher) { repository.setLocalNetworkSharing(isEnabled) }
+ }
+
fun onToggleDnsClick(isEnabled: Boolean) {
updateCustomDnsState(isEnabled)
showApplySettingChangesWarningToast()
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt
index 3349e58b99..640f4f64ac 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt
@@ -6,6 +6,8 @@ import net.mullvad.mullvadvpn.model.SelectedObfuscation
data class AdvancedSettingsViewModelState(
val mtuValue: String,
+ val isAutoConnectEnabled: Boolean,
+ val isLocalNetworkSharingEnabled: Boolean,
val isCustomDnsEnabled: Boolean,
val isAllowLanEnabled: Boolean,
val customDnsList: List<CustomDnsItem>,
@@ -18,6 +20,8 @@ data class AdvancedSettingsViewModelState(
is AdvancedSettingsDialogState.MtuDialog ->
AdvancedSettingsUiState.MtuDialogUiState(
mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
@@ -28,6 +32,8 @@ data class AdvancedSettingsViewModelState(
is AdvancedSettingsDialogState.DnsDialog ->
AdvancedSettingsUiState.DnsDialogUiState(
mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
@@ -35,9 +41,21 @@ data class AdvancedSettingsViewModelState(
stagedDns = dialogState.stagedDns,
selectedObfuscation = selectedObfuscation
)
+ is AdvancedSettingsDialogState.LocalNetworkSharingInfoDialog ->
+ AdvancedSettingsUiState.LocalNetworkSharingInfoDialogUiState(
+ mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
+ isCustomDnsEnabled = isCustomDnsEnabled,
+ isAllowLanEnabled = isAllowLanEnabled,
+ customDnsItems = customDnsList,
+ contentBlockersOptions = contentBlockersOptions
+ )
is AdvancedSettingsDialogState.ContentBlockersInfoDialog ->
AdvancedSettingsUiState.ContentBlockersInfoDialogUiState(
mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
@@ -47,6 +65,8 @@ data class AdvancedSettingsViewModelState(
is AdvancedSettingsDialogState.CustomDnsInfoDialog ->
AdvancedSettingsUiState.CustomDnsInfoDialogUiState(
mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
@@ -55,6 +75,8 @@ data class AdvancedSettingsViewModelState(
is AdvancedSettingsDialogState.MalwareInfoDialog ->
AdvancedSettingsUiState.MalwareInfoDialogUiState(
mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
@@ -73,6 +95,8 @@ data class AdvancedSettingsViewModelState(
else ->
AdvancedSettingsUiState.DefaultUiState(
mtu = mtuValue,
+ isAutoConnectEnabled = isAutoConnectEnabled,
+ isLocalNetworkSharingEnabled = isLocalNetworkSharingEnabled,
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
@@ -88,6 +112,8 @@ data class AdvancedSettingsViewModelState(
fun default() =
AdvancedSettingsViewModelState(
mtuValue = EMPTY_STRING,
+ isAutoConnectEnabled = false,
+ isLocalNetworkSharingEnabled = false,
isCustomDnsEnabled = false,
customDnsList = listOf(),
contentBlockersOptions = DefaultDnsOptions(),
@@ -105,6 +131,8 @@ sealed class AdvancedSettingsDialogState {
data class DnsDialog(val stagedDns: StagedDns) : AdvancedSettingsDialogState()
+ object LocalNetworkSharingInfoDialog : AdvancedSettingsDialogState()
+
object ContentBlockersInfoDialog : AdvancedSettingsDialogState()
object CustomDnsInfoDialog : AdvancedSettingsDialogState()
diff --git a/android/app/src/main/res/layout/preferences.xml b/android/app/src/main/res/layout/preferences.xml
deleted file mode 100644
index 70489f4429..0000000000
--- a/android/app/src/main/res/layout/preferences.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:mullvad="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/darkBlue"
- android:gravity="left">
- <TextView android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/settings_preferences"
- style="@style/SettingsCollapsedHeader" />
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <FrameLayout android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <net.mullvad.mullvadvpn.ui.widget.BackButton android:id="@+id/back"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- mullvad:text="@string/settings" />
- <TextView android:id="@+id/collapsed_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="4dp"
- android:layout_gravity="center"
- android:text="@string/settings_preferences"
- style="@style/SettingsCollapsedHeader" />
- </FrameLayout>
- <net.mullvad.mullvadvpn.ui.widget.ListenableScrollView android:id="@+id/scroll_area"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/screen_vertical_margin"
- android:orientation="vertical">
- <TextView android:id="@+id/expanded_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="2dp"
- android:layout_marginLeft="@dimen/side_margin"
- android:lines="1"
- android:text="@string/settings_preferences"
- style="@style/SettingsExpandedHeader" />
- <net.mullvad.mullvadvpn.ui.widget.ToggleCell android:id="@+id/auto_connect"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/vertical_space"
- mullvad:text="@string/auto_connect"
- mullvad:footer="@string/auto_connect_footer" />
- <net.mullvad.mullvadvpn.ui.widget.ToggleCell android:id="@+id/allow_lan"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/vertical_space"
- mullvad:text="@string/local_network_sharing"
- mullvad:footer="@string/allow_lan_footer" />
- </LinearLayout>
- </net.mullvad.mullvadvpn.ui.widget.ListenableScrollView>
- </LinearLayout>
-</FrameLayout>
diff --git a/android/app/src/main/res/layout/settings.xml b/android/app/src/main/res/layout/settings.xml
index 8a00334fff..09426d0bca 100644
--- a/android/app/src/main/res/layout/settings.xml
+++ b/android/app/src/main/res/layout/settings.xml
@@ -48,11 +48,6 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/vertical_space"
mullvad:text="@string/settings_account" />
- <net.mullvad.mullvadvpn.ui.widget.NavigateCell android:id="@+id/preferences"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="1dp"
- mullvad:text="@string/settings_preferences" />
<net.mullvad.mullvadvpn.ui.widget.NavigateCell android:id="@+id/advanced"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 871ef46360..9baef011b7 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -194,4 +194,6 @@
<string name="off">Off</string>
<string name="udp_over_tcp_port_info">Which TCP port the UDP-over-TCP obfuscation protocol should connect to on the VPN server.</string>
<string name="created_x">Created: %s</string>
+ <string name="local_network_sharing_info">This feature allows access to other devices on the local network, such as for sharing, printing, streaming, etc.</string>
+ <string name="local_network_sharing_additional_info">It does this by allowing network communication outside the tunnel to local multicast and broadcast ranges as well as to and from these private IP ranges:</string>
</resources>
diff --git a/android/app/src/main/res/values/strings_non_translatable.xml b/android/app/src/main/res/values/strings_non_translatable.xml
index c9c92fe66d..7c8b868059 100644
--- a/android/app/src/main/res/values/strings_non_translatable.xml
+++ b/android/app/src/main/res/values/strings_non_translatable.xml
@@ -9,4 +9,7 @@
<string name="privacy_policy_url" translatable="false">https://mullvad.net/help/privacy-policy/</string>
<string name="split_tunneling" translatable="false">Split tunneling</string>
<string name="wireguard" translatable="false">WireGuard</string>
+ <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>0xfe80::/10</li><li>0xfc00::/7</li></ul>]]>
+ </string>
</resources>