More styling changes

Signed-off-by: Percy Wegmann <percy@tailscale.com>
ox/styling_bak
Percy Wegmann 2 years ago
parent c881a7b3ef
commit 45fbd08ee3
No known key found for this signature in database
GPG Key ID: 29D8CDEB4C13D48B

@ -141,6 +141,23 @@ val ColorScheme.listItem: ListItemColors
disabledTrailingIconColor = default.disabledTrailingIconColor) disabledTrailingIconColor = default.disabledTrailingIconColor)
} }
/** Color scheme for disabled list items. */
val ColorScheme.disabledListItem: ListItemColors
@Composable
get() {
val default = ListItemDefaults.colors()
return ListItemColors(
containerColor = default.containerColor,
headlineColor = MaterialTheme.colorScheme.disabled,
leadingIconColor = default.leadingIconColor,
overlineColor = default.overlineColor,
supportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
trailingIconColor = default.trailingIconColor,
disabledHeadlineColor = default.disabledHeadlineColor,
disabledLeadingIconColor = default.disabledLeadingIconColor,
disabledTrailingIconColor = default.disabledTrailingIconColor)
}
/** Color scheme for list items that should be styled as a surface container. */ /** Color scheme for list items that should be styled as a surface container. */
val ColorScheme.surfaceContainerListItem: ListItemColors val ColorScheme.surfaceContainerListItem: ListItemColors
@Composable @Composable
@ -197,3 +214,6 @@ val ColorScheme.secondaryButton: ButtonColors
disabledContainerColor = defaults.disabledContainerColor, disabledContainerColor = defaults.disabledContainerColor,
disabledContentColor = defaults.disabledContentColor) disabledContentColor = defaults.disabledContentColor)
} }
val ColorScheme.disabled: Color
get() = Color(0xFFAFACAB) // gray-400

@ -1,27 +0,0 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package com.tailscale.ipn.ui.util
import androidx.compose.foundation.clickable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.semantics.Role
/**
* Similar to Modifier.clickable, but if enabled == false, this adds a 75% alpha to make disabled
* items appear grayed out.
*/
@Composable
fun Modifier.clickableOrGrayedOut(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
) =
if (enabled) {
clickable(onClickLabel = onClickLabel, role = role, onClick = onClick)
} else {
alpha(0.75f)
}

@ -23,9 +23,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.tailscale.ipn.R import com.tailscale.ipn.R
import com.tailscale.ipn.ui.theme.disabledListItem
import com.tailscale.ipn.ui.theme.listItem
import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.Lists
import com.tailscale.ipn.ui.util.LoadingIndicator import com.tailscale.ipn.ui.util.LoadingIndicator
import com.tailscale.ipn.ui.util.clickableOrGrayedOut
import com.tailscale.ipn.ui.util.itemsWithDividers import com.tailscale.ipn.ui.util.itemsWithDividers
import com.tailscale.ipn.ui.viewModel.ExitNodePickerNav import com.tailscale.ipn.ui.viewModel.ExitNodePickerNav
import com.tailscale.ipn.ui.viewModel.ExitNodePickerViewModel import com.tailscale.ipn.ui.viewModel.ExitNodePickerViewModel
@ -39,23 +40,17 @@ fun ExitNodePicker(
model: ExitNodePickerViewModel = viewModel(factory = ExitNodePickerViewModelFactory(nav)) model: ExitNodePickerViewModel = viewModel(factory = ExitNodePickerViewModelFactory(nav))
) { ) {
LoadingIndicator.Wrap { LoadingIndicator.Wrap {
Scaffold(topBar = { Header(R.string.choose_exit_node, onBack = nav.onNavigateBack) }) { Scaffold(
innerPadding -> topBar = { Header(R.string.choose_exit_node, onBack = nav.onNavigateBack) },
bottomBar = { SettingRow(model.allowLANAccessSetting) }) { innerPadding ->
val tailnetExitNodes = model.tailnetExitNodes.collectAsState().value val tailnetExitNodes = model.tailnetExitNodes.collectAsState().value
val mullvadExitNodesByCountryCode = model.mullvadExitNodesByCountryCode.collectAsState().value val mullvadExitNodesByCountryCode =
model.mullvadExitNodesByCountryCode.collectAsState().value
val mullvadExitNodeCount = model.mullvadExitNodeCount.collectAsState().value val mullvadExitNodeCount = model.mullvadExitNodeCount.collectAsState().value
val anyActive = model.anyActive.collectAsState() val anyActive = model.anyActive.collectAsState()
LazyColumn(modifier = Modifier.padding(innerPadding)) { LazyColumn(modifier = Modifier.padding(innerPadding)) {
stickyHeader { stickyHeader {
RunAsExitNodeItem(nav = nav, viewModel = model)
Lists.ItemDivider()
SettingRow(model.allowLANAccessSetting)
}
item(key = "none") {
Lists.SectionDivider()
ExitNodeItem( ExitNodeItem(
model, model,
ExitNodePickerViewModel.ExitNode( ExitNodePickerViewModel.ExitNode(
@ -63,16 +58,19 @@ fun ExitNodePicker(
online = true, online = true,
selected = !anyActive.value, selected = !anyActive.value,
)) ))
Lists.ItemDivider()
RunAsExitNodeItem(nav = nav, viewModel = model)
} }
item { Lists.ItemDivider() } item(key = "divider1") { Lists.SectionDivider() }
itemsWithDividers(tailnetExitNodes, key = { it.id!! }) { node -> ExitNodeItem(model, node) }
item { Lists.SectionDivider() } itemsWithDividers(tailnetExitNodes, key = { it.id!! }) { node ->
ExitNodeItem(model, node)
}
if (mullvadExitNodeCount > 0) { if (mullvadExitNodeCount > 0) {
item(key = "mullvad") { item(key = "mullvad") {
Lists.SectionDivider()
MullvadItem(nav, mullvadExitNodeCount, mullvadExitNodesByCountryCode.selected) MullvadItem(nav, mullvadExitNodeCount, mullvadExitNodesByCountryCode.selected)
} }
} }
@ -87,16 +85,17 @@ fun ExitNodeItem(
node: ExitNodePickerViewModel.ExitNode, node: ExitNodePickerViewModel.ExitNode,
) { ) {
Box { Box {
// TODO: add disabled styling var modifier: Modifier = Modifier
if (node.online) {
modifier = modifier.clickable { viewModel.setExitNode(node) }
}
ListItem( ListItem(
modifier = modifier = modifier,
Modifier.clickableOrGrayedOut(enabled = node.online) { viewModel.setExitNode(node) }, colors =
if (node.online) MaterialTheme.colorScheme.listItem
else MaterialTheme.colorScheme.disabledListItem,
headlineContent = { headlineContent = {
Text( Text(node.city.ifEmpty { node.label }, style = MaterialTheme.typography.bodyMedium)
node.city.ifEmpty { node.label },
style =
if (node.online) MaterialTheme.typography.titleMedium
else MaterialTheme.typography.bodyMedium)
}, },
supportingContent = { supportingContent = {
if (!node.online) if (!node.online)
@ -120,7 +119,7 @@ fun MullvadItem(nav: ExitNodePickerNav, count: Int, selected: Boolean) {
headlineContent = { headlineContent = {
Text( Text(
stringResource(R.string.mullvad_exit_nodes), stringResource(R.string.mullvad_exit_nodes),
style = MaterialTheme.typography.titleMedium) style = MaterialTheme.typography.bodyMedium)
}, },
supportingContent = { supportingContent = {
Text( Text(

@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBars
@ -43,6 +45,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -59,6 +63,7 @@ import com.tailscale.ipn.ui.model.IpnLocal
import com.tailscale.ipn.ui.model.Permission import com.tailscale.ipn.ui.model.Permission
import com.tailscale.ipn.ui.model.Permissions import com.tailscale.ipn.ui.model.Permissions
import com.tailscale.ipn.ui.model.Tailcfg import com.tailscale.ipn.ui.model.Tailcfg
import com.tailscale.ipn.ui.theme.disabled
import com.tailscale.ipn.ui.theme.listItem import com.tailscale.ipn.ui.theme.listItem
import com.tailscale.ipn.ui.theme.primaryListItem import com.tailscale.ipn.ui.theme.primaryListItem
import com.tailscale.ipn.ui.theme.secondaryButton import com.tailscale.ipn.ui.theme.secondaryButton
@ -252,7 +257,7 @@ fun ConnectView(
painter = painterResource(id = R.drawable.power), painter = painterResource(id = R.drawable.power),
contentDescription = null, contentDescription = null,
modifier = Modifier.size(40.dp), modifier = Modifier.size(40.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant) tint = MaterialTheme.colorScheme.disabled)
Text( Text(
text = stringResource(id = R.string.not_connected), text = stringResource(id = R.string.not_connected),
fontSize = MaterialTheme.typography.titleMedium.fontSize, fontSize = MaterialTheme.typography.titleMedium.fontSize,
@ -261,7 +266,13 @@ fun ConnectView(
fontFamily = MaterialTheme.typography.titleMedium.fontFamily) fontFamily = MaterialTheme.typography.titleMedium.fontFamily)
val tailnetName = user.NetworkProfile?.DomainName ?: "" val tailnetName = user.NetworkProfile?.DomainName ?: ""
Text( Text(
stringResource(id = R.string.connect_to_tailnet, tailnetName), buildAnnotatedString {
append(stringResource(id = R.string.connect_to_tailnet_prefix))
pushStyle(SpanStyle(fontWeight = FontWeight.Bold))
append(tailnetName)
pop()
append(stringResource(id = R.string.connect_to_tailnet_suffix))
},
fontSize = MaterialTheme.typography.titleMedium.fontSize, fontSize = MaterialTheme.typography.titleMedium.fontSize,
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Normal,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
@ -327,9 +338,16 @@ fun PeerList(
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
) { ) {
var first = true
peerList.value.forEach { peerSet -> peerList.value.forEach { peerSet ->
if (!first) {
item(key = "spacer_${peerSet.user?.DisplayName}") { Spacer(Modifier.height(24.dp)) }
}
first = false
stickyHeader { stickyHeader {
ListItem( ListItem(
modifier = Modifier.heightIn(max = 48.dp),
headlineContent = { headlineContent = {
Text( Text(
text = text =
@ -338,6 +356,7 @@ fun PeerList(
fontWeight = FontWeight.SemiBold) fontWeight = FontWeight.SemiBold)
}) })
} }
itemsWithDividers(peerSet.peers, key = { it.StableID }) { peer -> itemsWithDividers(peerSet.peers, key = { it.StableID }) { peer ->
ListItem( ListItem(
modifier = Modifier.clickable { onNavigateToPeerDetails(peer) }, modifier = Modifier.clickable { onNavigateToPeerDetails(peer) },

@ -70,7 +70,7 @@ fun MullvadExitNodePickerList(
) )
}, },
headlineContent = { headlineContent = {
Text(first.country, style = MaterialTheme.typography.titleMedium) Text(first.country, style = MaterialTheme.typography.bodyMedium)
}, },
supportingContent = { supportingContent = {
Text( Text(

@ -46,7 +46,8 @@
<!-- Strings for the main screen --> <!-- Strings for the main screen -->
<string name="exit_node">EXIT NODE</string> <string name="exit_node">EXIT NODE</string>
<string name="starting">Starting…</string> <string name="starting">Starting…</string>
<string name="connect_to_tailnet">"Connect again to talk to the other devices in the %1$s tailnet."</string> <string name="connect_to_tailnet_prefix">"Connect again to talk to the other devices in the "</string>
<string name="connect_to_tailnet_suffix">" tailnet."</string>
<string name="welcome_to_tailscale">Welcome to Tailscale</string> <string name="welcome_to_tailscale">Welcome to Tailscale</string>
<string name="login_to_join_your_tailnet">Log in to join your tailnet and connect your devices.</string> <string name="login_to_join_your_tailnet">Log in to join your tailnet and connect your devices.</string>

Loading…
Cancel
Save