android/ui: distinguish Tailnet domains in user view

Updates tailscale/corp#18202

Signed-off-by: Percy Wegmann <percy@tailscale.com>
pull/275/head
Percy Wegmann 2 months ago committed by Percy Wegmann
parent e9465988dd
commit 91c1a8d0f3

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

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

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

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

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

Loading…
Cancel
Save