android/ui: more UI tweaks

1. Add title to internal debug options

Updates tailscale/corp#19045

Signed-off-by: Percy Wegmann <percy@tailscale.com>
angott/reintroduce-dark-mode
Percy Wegmann 3 weeks ago committed by Percy Wegmann
parent 0ae9da385e
commit d396fdab27

@ -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

@ -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. */

@ -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))
}
}
}

@ -322,7 +322,8 @@ fun PeerList(
) {
val peerList = viewModel.peers.collectAsState(initial = emptyList<PeerSet>())
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,

@ -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 }) {

@ -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)
}
}

@ -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

@ -47,6 +47,7 @@
<string name="about_tailscale">About Tailscale</string>
<string name="bug_report">Bug report</string>
<string name="use_ts_dns">Use Tailscale DNS</string>
<string name="internal_debug_options">Internal debug options</string>
<!-- Strings for the main screen -->
<string name="exit_node">EXIT NODE</string>

Loading…
Cancel
Save