From d396fdab27f6fe71e8476b6daa5312f5237e391d Mon Sep 17 00:00:00 2001 From: Percy Wegmann Date: Tue, 9 Apr 2024 08:56:18 -0500 Subject: [PATCH] android/ui: more UI tweaks 1. Add title to internal debug options Updates tailscale/corp#19045 Signed-off-by: Percy Wegmann --- .../java/com/tailscale/ipn/MainActivity.kt | 10 +++++-- .../java/com/tailscale/ipn/ui/util/Lists.kt | 26 +++++++++++++++++-- .../tailscale/ipn/ui/view/BugReportView.kt | 19 ++++++++------ .../com/tailscale/ipn/ui/view/MainView.kt | 7 ++--- .../com/tailscale/ipn/ui/view/PeerDetails.kt | 14 +--------- .../com/tailscale/ipn/ui/view/SettingsView.kt | 1 + .../ipn/ui/view/TailnetLockSetupView.kt | 17 +++++------- android/src/main/res/values/strings.xml | 1 + 8 files changed, 56 insertions(+), 39 deletions(-) diff --git a/android/src/main/java/com/tailscale/ipn/MainActivity.kt b/android/src/main/java/com/tailscale/ipn/MainActivity.kt index 0b8d22e..e45d23f 100644 --- a/android/src/main/java/com/tailscale/ipn/MainActivity.kt +++ b/android/src/main/java/com/tailscale/ipn/MainActivity.kt @@ -22,6 +22,8 @@ import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContract import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideOutHorizontally import androidx.compose.material3.MaterialTheme @@ -159,7 +161,9 @@ class MainActivity : ComponentActivity() { onNavigateToMullvadCountry = { navController.navigate("mullvad/$it") }, onNavigateToRunAsExitNode = { navController.navigate("runExitNode") }) - composable("main") { MainView(navigation = mainViewNav) } + composable("main", enterTransition = { fadeIn(animationSpec = tween(150)) }) { + MainView(navigation = mainViewNav) + } composable("settings") { SettingsView(settingsNav) } composable("exitNodes") { ExitNodePicker(exitNodePickerNav) } composable("mullvad") { MullvadExitNodePickerList(exitNodePickerNav) } @@ -188,7 +192,9 @@ class MainActivity : ComponentActivity() { composable("permissions") { PermissionsView(backTo("settings"), ::openApplicationSettings) } - composable("intro") { IntroView(backTo("main")) } + composable("intro", exitTransition = { fadeOut(animationSpec = tween(150)) }) { + IntroView(backTo("main")) + } } // Show the intro screen one time 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 9bf6594..bf92437 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 @@ -28,7 +28,7 @@ object Lists { @Composable fun SectionDivider(title: String? = null) { Box(Modifier.size(0.dp, 16.dp)) - title?.let { SectionTitle(title) } + title?.let { LargeTitle(title) } } @Composable @@ -37,7 +37,7 @@ object Lists { } @Composable - fun SectionTitle( + fun LargeTitle( title: String, bottomPadding: Dp = 0.dp, style: TextStyle = MaterialTheme.typography.titleMedium, @@ -56,6 +56,20 @@ object Lists { } } + @Composable + fun MutedHeader(text: String) { + Box( + modifier = + Modifier.fillMaxWidth() + .background(color = MaterialTheme.colorScheme.surface, shape = RectangleShape)) { + Text( + modifier = Modifier.padding(start = 16.dp, top = 16.dp), + text = text, + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant) + } + } + @Composable fun InfoItem(text: CharSequence, onClick: (() -> Unit)? = null) { val style = @@ -69,6 +83,14 @@ object Lists { } }) } + + @Composable + fun MultilineDescription(headlineContent: @Composable () -> Unit) { + ListItem( + headlineContent = { + Box(modifier = Modifier.padding(vertical = 8.dp)) { headlineContent() } + }) + } } /** Similar to items() but includes a horizontal divider between items. */ diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt index 5ec5b4b..bcfcb1c 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/BugReportView.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable @@ -38,19 +37,23 @@ fun BugReportView(backToSettings: BackNavigation, model: BugReportViewModel = vi Scaffold(topBar = { Header(R.string.bug_report_title, onBack = backToSettings) }) { innerPadding -> - Column(modifier = Modifier.padding(innerPadding).fillMaxWidth().fillMaxHeight().verticalScroll(rememberScrollState())) { - ListItem( - headlineContent = { + Column( + modifier = + Modifier.padding(innerPadding) + .fillMaxWidth() + .fillMaxHeight() + .verticalScroll(rememberScrollState())) { + Lists.MultilineDescription { ClickableText( text = contactText(), style = MaterialTheme.typography.bodyMedium, onClick = { handler.openUri(Links.SUPPORT_URL) }) - }) + } - ClipboardValueView(bugReportID, title = stringResource(R.string.bug_report_id)) + ClipboardValueView(bugReportID, title = stringResource(R.string.bug_report_id)) - Lists.InfoItem(stringResource(id = R.string.bug_report_id_desc)) - } + Lists.InfoItem(stringResource(id = R.string.bug_report_id_desc)) + } } } 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 afdd57e..0ad1f43 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 @@ -322,7 +322,8 @@ fun PeerList( ) { val peerList = viewModel.peers.collectAsState(initial = emptyList()) val searchTermStr by viewModel.searchTerm.collectAsState(initial = "") - val showNoResults = derivedStateOf { searchTermStr.isNotEmpty() && peerList.value.isEmpty() }.value + val showNoResults = + derivedStateOf { searchTermStr.isNotEmpty() && peerList.value.isEmpty() }.value val netmap = viewModel.netmap.collectAsState() val focusManager = LocalFocusManager.current @@ -373,7 +374,7 @@ fun PeerList( .fillMaxSize() .background(color = MaterialTheme.colorScheme.surface)) - Lists.SectionTitle( + Lists.LargeTitle( stringResource(id = R.string.no_results), bottomPadding = 8.dp, style = MaterialTheme.typography.bodyMedium, @@ -394,7 +395,7 @@ fun PeerList( .fillMaxSize() .background(color = MaterialTheme.colorScheme.surface)) - Lists.SectionTitle( + Lists.LargeTitle( peerSet.user?.DisplayName ?: stringResource(id = R.string.unknown_user), bottomPadding = 8.dp, style = MaterialTheme.typography.titleLarge, diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/PeerDetails.kt b/android/src/main/java/com/tailscale/ipn/ui/view/PeerDetails.kt index 09fd45d..b65bb0f 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/PeerDetails.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/PeerDetails.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -24,7 +23,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -81,17 +79,7 @@ fun PeerDetails( modifier = Modifier.padding(innerPadding), ) { item(key = "tailscaleAddresses") { - Box( - modifier = - Modifier.fillMaxWidth() - .background( - color = MaterialTheme.colorScheme.surface, shape = RectangleShape)) { - Text( - modifier = Modifier.padding(start = 16.dp, top = 16.dp), - text = stringResource(R.string.tailscale_addresses), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.onSurfaceVariant) - } + Lists.MutedHeader(stringResource(R.string.tailscale_addresses)) } itemsWithDividers(node.displayAddresses, key = { it.address }) { diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt index 7bd0374..055e2f8 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt @@ -97,6 +97,7 @@ fun SettingsView(settingsNav: SettingsNav, viewModel: SettingsViewModel = viewMo // TODO: put a heading for the debug section if (BuildConfig.DEBUG) { Lists.SectionDivider() + Lists.MutedHeader(text = stringResource(R.string.internal_debug_options)) Setting.Text(R.string.mdm_settings, onClick = settingsNav.onNavigateToMDMSettings) } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt index 374d164..1d2235e 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/TailnetLockSetupView.kt @@ -3,7 +3,6 @@ package com.tailscale.ipn.ui.view -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -24,7 +23,6 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R import com.tailscale.ipn.ui.Links @@ -88,15 +86,12 @@ fun TailnetLockSetupView( private fun ExplainerView() { val handler = LocalUriHandler.current - ListItem( - headlineContent = { - Box(modifier = Modifier.padding(vertical = 8.dp)) { - ClickableText( - explainerText(), - onClick = { handler.openUri(Links.TAILNET_LOCK_KB_URL) }, - style = MaterialTheme.typography.bodyMedium) - } - }) + Lists.MultilineDescription { + ClickableText( + explainerText(), + onClick = { handler.openUri(Links.TAILNET_LOCK_KB_URL) }, + style = MaterialTheme.typography.bodyMedium) + } } @Composable diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml index ef7e3ef..7816f48 100644 --- a/android/src/main/res/values/strings.xml +++ b/android/src/main/res/values/strings.xml @@ -47,6 +47,7 @@ About Tailscale Bug report Use Tailscale DNS + Internal debug options EXIT NODE