From 91c1a8d0f3ed39bc79fb34d3d2eb1ca6c0a7d3b8 Mon Sep 17 00:00:00 2001 From: Percy Wegmann Date: Tue, 2 Apr 2024 08:20:35 -0500 Subject: [PATCH] android/ui: distinguish Tailnet domains in user view Updates tailscale/corp#18202 Signed-off-by: Percy Wegmann --- .../java/com/tailscale/ipn/ui/theme/Theme.kt | 4 ++ .../com/tailscale/ipn/ui/view/MainView.kt | 47 +++++++------------ .../com/tailscale/ipn/ui/view/PeerDetails.kt | 6 +-- .../com/tailscale/ipn/ui/view/UserView.kt | 7 ++- .../ipn/ui/viewModel/MainViewModel.kt | 5 -- 5 files changed, 30 insertions(+), 39 deletions(-) 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 03c6b0a..cf59a29 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 @@ -20,6 +20,7 @@ import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.sp import com.google.accompanist.systemuicontroller.rememberSystemUiController @@ -225,3 +226,6 @@ val ColorScheme.searchBarColors: TextFieldColors focusedBorderColor = Color.Transparent, unfocusedBorderColor = Color.Transparent) } + +val TextStyle.short: TextStyle + get() = copy(lineHeight = 20.sp) 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 6dff210..a70bd55 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 @@ -57,7 +57,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted @@ -74,6 +73,7 @@ import com.tailscale.ipn.ui.theme.listItem import com.tailscale.ipn.ui.theme.primaryListItem import com.tailscale.ipn.ui.theme.searchBarColors import com.tailscale.ipn.ui.theme.secondaryButton +import com.tailscale.ipn.ui.theme.short import com.tailscale.ipn.ui.theme.surfaceContainerListItem import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.LoadingIndicator @@ -97,11 +97,10 @@ fun MainView(navigation: MainViewNavigation, viewModel: MainViewModel = viewMode Column( modifier = Modifier.fillMaxWidth().padding(paddingInsets), verticalArrangement = Arrangement.Center) { - val state = viewModel.ipnState.collectAsState(initial = Ipn.State.NoState) - val user = viewModel.loggedInUser.collectAsState(initial = null) - val stateVal = viewModel.stateRes.collectAsState(initial = R.string.placeholder) - val stateStr = stringResource(id = stateVal.value) - val username = viewModel.userName + val state = viewModel.ipnState.collectAsState(initial = Ipn.State.NoState).value + val user = viewModel.loggedInUser.collectAsState(initial = null).value + val stateVal = viewModel.stateRes.collectAsState(initial = R.string.placeholder).value + val stateStr = stringResource(id = stateVal) ListItem( colors = MaterialTheme.colorScheme.surfaceContainerListItem, @@ -110,39 +109,31 @@ fun MainView(navigation: MainViewNavigation, viewModel: MainViewModel = viewMode TintedSwitch( onCheckedChange = { viewModel.toggleVpn() }, checked = isOn.value, - enabled = state.value != Ipn.State.NoState) + enabled = state != Ipn.State.NoState) }, headlineContent = { - if (username.isNotEmpty()) { + user?.NetworkProfile?.DomainName?.let { domain -> Text( - text = username, - style = MaterialTheme.typography.titleMedium.copy(lineHeight = 20.sp)) + text = domain, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.titleMedium.short) } }, supportingContent = { - if (username.isNotEmpty()) { - Text( - text = stateStr, - style = MaterialTheme.typography.bodyMedium.copy(lineHeight = 20.sp)) - } else { - Text( - text = stateStr, - style = MaterialTheme.typography.bodyMedium.copy(lineHeight = 20.sp)) - } + Text(text = stateStr, style = MaterialTheme.typography.bodyMedium.short) }, trailingContent = { Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.CenterEnd) { - when (user.value) { - null -> SettingsButton(user.value) { navigation.onNavigateToSettings() } + when (user) { + null -> SettingsButton { navigation.onNavigateToSettings() } else -> - Avatar(profile = user.value, size = 36) { - navigation.onNavigateToSettings() - } + Avatar(profile = user, size = 36) { navigation.onNavigateToSettings() } } } }) - when (state.value) { + when (state) { Ipn.State.Running -> { PromptPermissionsIfNecessary(permissions = Permissions.all) @@ -156,9 +147,7 @@ fun MainView(navigation: MainViewNavigation, viewModel: MainViewModel = viewMode } Ipn.State.NoState, Ipn.State.Starting -> StartingView() - else -> - ConnectView( - state.value, user.value, { viewModel.toggleVpn() }, { viewModel.login {} }) + else -> ConnectView(state, user, { viewModel.toggleVpn() }, { viewModel.login {} }) } } } @@ -225,7 +214,7 @@ fun ExitNodeStatus(navAction: () -> Unit, viewModel: MainViewModel) { } @Composable -fun SettingsButton(user: IpnLocal.LoginProfile?, action: () -> Unit) { +fun SettingsButton(action: () -> Unit) { // (jonathan) TODO: On iOS this is the users avatar or a letter avatar. IconButton(modifier = Modifier.size(24.dp), onClick = { action() }) { 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 fb61cde..3b04052 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 @@ -31,10 +31,10 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R import com.tailscale.ipn.ui.theme.listItem +import com.tailscale.ipn.ui.theme.short import com.tailscale.ipn.ui.theme.ts_color_light_blue import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.itemsWithDividers @@ -58,7 +58,7 @@ fun PeerDetails( Column { Text( text = node.displayName, - style = MaterialTheme.typography.titleMedium.copy(lineHeight = 20.sp), + style = MaterialTheme.typography.titleMedium.short, color = MaterialTheme.colorScheme.onSurface) Row(verticalAlignment = Alignment.CenterVertically) { Box( @@ -70,7 +70,7 @@ fun PeerDetails( Spacer(modifier = Modifier.size(8.dp)) Text( text = stringResource(id = node.connectedStrRes(netmap)), - style = MaterialTheme.typography.bodyMedium.copy(lineHeight = 20.sp), + style = MaterialTheme.typography.bodyMedium.short, color = MaterialTheme.colorScheme.onSurfaceVariant) } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/UserView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/UserView.kt index aaab3e2..5360057 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/UserView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/UserView.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.tailscale.ipn.R import com.tailscale.ipn.ui.model.IpnLocal +import com.tailscale.ipn.ui.theme.short // Used to decorate UserViews. // NONE indicates no decoration @@ -40,10 +41,12 @@ fun UserView( headlineContent = { Text( text = profile.UserProfile.DisplayName, - style = MaterialTheme.typography.titleMedium) + style = MaterialTheme.typography.titleMedium.short) }, supportingContent = { - Text(text = profile.Name, style = MaterialTheme.typography.bodyMedium) + Text( + text = profile.NetworkProfile?.DomainName ?: "", + style = MaterialTheme.typography.bodyMedium.short) }, trailingContent = { when (actionState) { diff --git a/android/src/main/java/com/tailscale/ipn/ui/viewModel/MainViewModel.kt b/android/src/main/java/com/tailscale/ipn/ui/viewModel/MainViewModel.kt index 11f5b0a..f99d407 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/viewModel/MainViewModel.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/viewModel/MainViewModel.kt @@ -39,11 +39,6 @@ class MainViewModel : IpnViewModel() { private val peerCategorizer = PeerCategorizer() - val userName: String - get() { - return loggedInUser.value?.Name ?: "" - } - init { viewModelScope.launch { Notifier.state.collect { state ->