From bf74edd5518c85b6b88d434ab1572f2d663b6b3d Mon Sep 17 00:00:00 2001 From: Andrea Gottardo Date: Mon, 25 Mar 2024 13:27:16 -0700 Subject: [PATCH] android: add ExitNodeAllowLANAccess toggle in exit node picker (#241) Updates ENG-3011 Just like on iOS, we should show a switch to toggle the ExitNodeAllowLANAccess preference. Signed-off-by: Andrea Gottardo --- .../java/com/tailscale/ipn/ui/model/Ipn.kt | 2 +- .../tailscale/ipn/ui/view/ExitNodePicker.kt | 2 ++ .../com/tailscale/ipn/ui/view/MainView.kt | 2 +- .../ipn/ui/viewModel/DNSSettingsViewModel.kt | 5 +--- .../ui/viewModel/ExitNodePickerViewModel.kt | 29 +++++++++++++++++-- android/src/main/res/values/strings.xml | 1 + 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/android/src/main/java/com/tailscale/ipn/ui/model/Ipn.kt b/android/src/main/java/com/tailscale/ipn/ui/model/Ipn.kt index f95647f..a330626 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/model/Ipn.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/model/Ipn.kt @@ -42,7 +42,7 @@ class Ipn { var LocalTCPPort: Int? = null, var IncomingFiles: List? = null, var ClientVersion: Tailcfg.ClientVersion? = null, - var TailFSShares: Map? = null, + var TailFSShares: List? = null, ) @Serializable diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt b/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt index 96f0e48..c7f7772 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt @@ -109,6 +109,8 @@ fun ExitNodePicker( }) } } + + item("allowLANAccessToggle") { SettingRow(model.allowLANAccessSetting) } } } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt index 160346d..b1d5e6a 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/MainView.kt @@ -210,7 +210,7 @@ fun SettingsButton(user: IpnLocal.LoginProfile?, action: () -> Unit) { fun StartingView() { // (jonathan) TODO: On iOS this is the game-of-life Tailscale animation. Column( - modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background), + modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.secondaryContainer), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally) { Text( diff --git a/android/src/main/java/com/tailscale/ipn/ui/viewModel/DNSSettingsViewModel.kt b/android/src/main/java/com/tailscale/ipn/ui/viewModel/DNSSettingsViewModel.kt index 1539bef..761391c 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/viewModel/DNSSettingsViewModel.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/viewModel/DNSSettingsViewModel.kt @@ -43,10 +43,7 @@ class DNSSettingsViewModel() : IpnViewModel() { isOn = MutableStateFlow(Notifier.prefs.value?.CorpDNS), onToggle = { LoadingIndicator.start() - toggleCorpDNS { - LoadingIndicator.stop() - // (jonathan) TODO: Error handling - } + toggleCorpDNS { LoadingIndicator.stop() } }) init { diff --git a/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt b/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt index f97dbba..27b4ec2 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt @@ -6,6 +6,7 @@ package com.tailscale.ipn.ui.viewModel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope +import com.tailscale.ipn.R import com.tailscale.ipn.ui.localapi.Client import com.tailscale.ipn.ui.model.Ipn import com.tailscale.ipn.ui.model.StableNodeID @@ -51,7 +52,18 @@ class ExitNodePickerViewModel(private val nav: ExitNodePickerNav) : IpnViewModel MutableStateFlow(TreeMap()) val mullvadBestAvailableByCountry: StateFlow> = MutableStateFlow(TreeMap()) val anyActive: StateFlow = MutableStateFlow(false) - val isRunningExitNode: StateFlow = MutableStateFlow(false) + val isRunningExitNode: StateFlow = MutableStateFlow(false) + + val allowLANAccessSetting = + Setting( + R.string.allow_lan_access, + SettingType.SWITCH, + isOn = MutableStateFlow(Notifier.prefs.value?.ExitNodeAllowLANAccess), + enabled = MutableStateFlow(true), + onToggle = { + LoadingIndicator.start() + toggleAllowLANAccess { LoadingIndicator.stop() } + }) init { viewModelScope.launch { @@ -59,7 +71,7 @@ class ExitNodePickerViewModel(private val nav: ExitNodePickerNav) : IpnViewModel .combine(Notifier.prefs) { netmap, prefs -> Pair(netmap, prefs) } .stateIn(viewModelScope) .collect { (netmap, prefs) -> - isRunningExitNode.set(prefs?.let { AdvertisedRoutesHelper.exitNodeOnFromPrefs(it) }) + isRunningExitNode.set(prefs?.let { AdvertisedRoutesHelper.exitNodeOnFromPrefs(it) }) val exitNodeId = prefs?.ExitNodeID netmap?.Peers?.let { peers -> val allNodes = @@ -137,4 +149,17 @@ class ExitNodePickerViewModel(private val nav: ExitNodePickerNav) : IpnViewModel LoadingIndicator.stop() } } + + fun toggleAllowLANAccess(callback: (Result) -> Unit) { + val prefs = + Notifier.prefs.value + ?: run { + callback(Result.failure(Exception("no prefs"))) + return@toggleAllowLANAccess + } + + val prefsOut = Ipn.MaskedPrefs() + prefsOut.ExitNodeAllowLANAccess = !prefs.ExitNodeAllowLANAccess + Client(viewModelScope).editPrefs(prefsOut, callback) + } } diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml index ea09e51..93f3482 100644 --- a/android/src/main/res/values/strings.xml +++ b/android/src/main/res/values/strings.xml @@ -124,5 +124,6 @@ Tailscale is not running. This device is using the system\'s DNS resolver. This device is using the system DNS resolver. Not Using Tailscale DNS + Allow LAN Access