diff --git a/android/src/main/java/com/tailscale/ipn/ui/theme/Theme.kt b/android/src/main/java/com/tailscale/ipn/ui/theme/Theme.kt index f71b608..6957b6f 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/theme/Theme.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/theme/Theme.kt @@ -55,10 +55,10 @@ private val LightColors = lightColorScheme( primary = Color(0xFF4B70CC), // blue-500 onPrimary = Color(0xFFFFFFFF), // white - // primaryContainer = Color(0xFFF0F5FF), // blue-0 - primaryContainer = Color(0xFF6D94EC), // blue-400 - // onPrimaryContainer = Color(0xFF3E5DB3), // blue-600 - onPrimaryContainer = Color(0xFFFFFFFF), // white, + primaryContainer = Color(0xFFF0F5FF), // blue-0 + // primaryContainer = Color(0xFF6D94EC), // blue-400 + onPrimaryContainer = Color(0xFF3E5DB3), // blue-600 + // onPrimaryContainer = Color(0xFFFFFFFF), // white, error = Color(0xFFB22C30), // red-500 onError = Color(0xFFFFFFFF), // white errorContainer = Color(0xFFFEF6F3), // red-0 @@ -209,8 +209,8 @@ val ColorScheme.secondaryButton: ButtonColors get() { val defaults = ButtonDefaults.buttonColors() return ButtonColors( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer, + containerColor = Color(0xFF6D94EC), // blue-400 + contentColor = Color(0xFFFFFFFF), // white disabledContainerColor = defaults.disabledContainerColor, disabledContentColor = defaults.disabledContentColor) } diff --git a/android/src/main/java/com/tailscale/ipn/ui/util/Lists.kt b/android/src/main/java/com/tailscale/ipn/ui/util/Lists.kt index 256b19d..9b5502c 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/util/Lists.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/util/Lists.kt @@ -26,7 +26,7 @@ object Lists { @Composable fun ItemDivider() { - HorizontalDivider(color = MaterialTheme.colorScheme.surfaceContainer) + HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant) } } 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 6e0735a..6d21c9e 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 @@ -3,7 +3,6 @@ package com.tailscale.ipn.ui.view -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -11,7 +10,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Check -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme @@ -33,49 +31,50 @@ import com.tailscale.ipn.ui.viewModel.ExitNodePickerViewModel import com.tailscale.ipn.ui.viewModel.ExitNodePickerViewModelFactory import com.tailscale.ipn.ui.viewModel.selected -@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun ExitNodePicker( nav: ExitNodePickerNav, model: ExitNodePickerViewModel = viewModel(factory = ExitNodePickerViewModelFactory(nav)) ) { LoadingIndicator.Wrap { - Scaffold( - topBar = { Header(R.string.choose_exit_node, onBack = nav.onNavigateBack) }, - bottomBar = { SettingRow(model.allowLANAccessSetting) }) { innerPadding -> - val tailnetExitNodes = model.tailnetExitNodes.collectAsState().value - val mullvadExitNodesByCountryCode = - model.mullvadExitNodesByCountryCode.collectAsState().value - val mullvadExitNodeCount = model.mullvadExitNodeCount.collectAsState().value - val anyActive = model.anyActive.collectAsState() + Scaffold(topBar = { Header(R.string.choose_exit_node, onBack = nav.onNavigateBack) }) { + innerPadding -> + val tailnetExitNodes = model.tailnetExitNodes.collectAsState().value + val mullvadExitNodesByCountryCode = model.mullvadExitNodesByCountryCode.collectAsState().value + val mullvadExitNodeCount = model.mullvadExitNodeCount.collectAsState().value + val anyActive = model.anyActive.collectAsState() - LazyColumn(modifier = Modifier.padding(innerPadding)) { - stickyHeader { - ExitNodeItem( - model, - ExitNodePickerViewModel.ExitNode( - label = stringResource(R.string.none), - online = true, - selected = !anyActive.value, - )) - Lists.ItemDivider() - RunAsExitNodeItem(nav = nav, viewModel = model) - } + LazyColumn(modifier = Modifier.padding(innerPadding)) { + item(key = "header") { + ExitNodeItem( + model, + ExitNodePickerViewModel.ExitNode( + label = stringResource(R.string.none), + online = true, + selected = !anyActive.value, + )) + Lists.ItemDivider() + RunAsExitNodeItem(nav = nav, viewModel = model) + } - item(key = "divider1") { Lists.SectionDivider() } + item(key = "divider1") { Lists.SectionDivider() } - itemsWithDividers(tailnetExitNodes, key = { it.id!! }) { node -> - ExitNodeItem(model, node) - } + itemsWithDividers(tailnetExitNodes, key = { it.id!! }) { node -> ExitNodeItem(model, node) } - if (mullvadExitNodeCount > 0) { - item(key = "mullvad") { - Lists.SectionDivider() - MullvadItem(nav, mullvadExitNodeCount, mullvadExitNodesByCountryCode.selected) - } - } + if (mullvadExitNodeCount > 0) { + item(key = "mullvad") { + Lists.SectionDivider() + MullvadItem(nav, mullvadExitNodeCount, mullvadExitNodesByCountryCode.selected) } } + + // TODO: make sure this actually works, and if not, leave it out for now + item(key = "allowLANAccess") { + Lists.SectionDivider() + SettingRow(model.allowLANAccessSetting) + } + } + } } } @@ -146,7 +145,7 @@ fun RunAsExitNodeItem(nav: ExitNodePickerNav, viewModel: ExitNodePickerViewModel stringResource(id = R.string.run_as_exit_node), style = MaterialTheme.typography.bodyMedium) }, - trailingContent = { + supportingContent = { if (isRunningExitNode) { Text(stringResource(R.string.enabled)) } else { diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePicker.kt b/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePicker.kt index 5e5784c..a31063e 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePicker.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePicker.kt @@ -51,7 +51,7 @@ fun MullvadExitNodePicker( online = bestAvailableNode.online, selected = false, )) - Lists.ItemDivider() + Lists.SectionDivider() } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/SharedViews.kt b/android/src/main/java/com/tailscale/ipn/ui/view/SharedViews.kt index 21685bf..bc64897 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/SharedViews.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/SharedViews.kt @@ -42,7 +42,7 @@ fun Header(@StringRes title: Int = 0, titleText: String? = null, onBack: (() -> @Composable fun BackArrow(action: () -> Unit) { - Box(modifier = Modifier.padding(start = 15.dp, end = 20.dp)) { + Box(modifier = Modifier.padding(start = 8.dp, end = 8.dp)) { Icon(Icons.AutoMirrored.Filled.ArrowBack, null, modifier = Modifier.clickable { action() }) } } diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml index d371083..ffb08ea 100644 --- a/android/src/main/res/values/strings.xml +++ b/android/src/main/res/values/strings.xml @@ -91,19 +91,19 @@ Unable to add a new profile. Please try again. - Choose Exit Node - Mullvad Exit Nodes - Tailnet Exit Nodes + Choose exit node + Mullvad exit nodes + Tailnet exit nodes Mullvad VPN - Best Available - Run as Exit Node + Best available + Run as exit node Run this device as an exit node? - Other devices in your tailnet will be able to route their Internet traffic through this Android device. Make sure to approve this exit node in the admin console in order for other devices to see it. + Other devices in your tailnet will be able to route their internet traffic through this Android device. Make sure to approve this exit node in the admin console in order for other devices to see it. Caution: Running an exit node will severely impact battery life. On a metered data plan, significant cellular data charges may also apply. Always disable this feature when no longer needed. - Stop Running as Exit Node - Start Running as Exit Node - Now Running as Exit Node - Other devices in your tailnet can now route their Internet traffic through this Android device. Make sure to approve this exit node in the admin console in order for other devices to see it. + Stop running as exit node + Start running as exit node + Now running as exit node + Other devices in your tailnet can now route their internet traffic through this Android device. Make sure to approve this exit node in the admin console in order for other devices to see it. Enabled Disabled Disable