diff --git a/android/src/main/java/com/tailscale/ipn/ui/util/ClipboardValueView.kt b/android/src/main/java/com/tailscale/ipn/ui/util/ClipboardValueView.kt index 9b327b1..9fac0c6 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/util/ClipboardValueView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/util/ClipboardValueView.kt @@ -4,28 +4,21 @@ package com.tailscale.ipn.ui.util import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.tailscale.ipn.R @@ -39,44 +32,33 @@ fun ClipboardValueView( fontFamily: FontFamily = FontFamily.Monospace ) { val localClipboardManager = LocalClipboardManager.current - Surface( - color = MaterialTheme.colorScheme.secondaryContainer, - modifier = Modifier.clip(shape = RoundedCornerShape(8.dp))) { - Row( - horizontalArrangement = - Arrangement.spacedBy(8.dp, alignment = Alignment.CenterHorizontally), - modifier = - Modifier.fillMaxWidth() - .padding(8.dp) - .clickable(onClick = { localClipboardManager.setText(AnnotatedString(value)) }), - verticalAlignment = Alignment.CenterVertically) { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.fillMaxWidth().weight(10f)) { - title?.let { title -> - Text( - title, - style = MaterialTheme.typography.bodyMedium, - fontWeight = FontWeight.SemiBold) - } - Text( - text = value, - style = MaterialTheme.typography.bodyMedium, - fontFamily = fontFamily, - maxLines = 2, - overflow = TextOverflow.Ellipsis) - subtitle?.let { subtitle -> - Text( - subtitle, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.secondary) - } - } - Icon( - painterResource(R.drawable.clipboard), - stringResource(R.string.copy_to_clipboard), - modifier = Modifier.width(24.dp).height(24.dp), - tint = ts_color_light_blue) - } - } + Row { + ListItem( + modifier = Modifier.clickable { localClipboardManager.setText(AnnotatedString(value)) }, + overlineContent = { title?.let { Text(it, style = MaterialTheme.typography.titleMedium) } }, + headlineContent = { + Text( + text = value, + style = MaterialTheme.typography.bodyMedium, + fontFamily = fontFamily, + maxLines = 2, + overflow = TextOverflow.Ellipsis) + }, + supportingContent = { + subtitle?.let { subtitle -> + Text( + subtitle, + modifier = Modifier.padding(top = 8.dp), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.secondary) + } + }, + trailingContent = { + Icon( + painterResource(R.drawable.clipboard), + stringResource(R.string.copy_to_clipboard), + modifier = Modifier.width(24.dp).height(24.dp), + tint = ts_color_light_blue) + }) + } } 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 246c7ef..c53364c 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 @@ -8,15 +8,20 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp object Lists { @Composable - fun SectionDivider() { - Box(Modifier.size(0.dp, 8.dp)) + fun SectionDivider(title: String? = null) { + Box(Modifier.size(0.dp, 16.dp)) + title?.let { + ListItem(headlineContent = { Text(title, style = MaterialTheme.typography.titleMedium) }) + } } @Composable 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 7a2adf3..27502e1 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 @@ -4,12 +4,11 @@ package com.tailscale.ipn.ui.view import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.ClickableText +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -24,12 +23,12 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign 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 import com.tailscale.ipn.ui.theme.ts_color_light_blue import com.tailscale.ipn.ui.util.ClipboardValueView +import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.viewModel.BugReportViewModel @Composable @@ -38,26 +37,31 @@ fun BugReportView(nav: BackNavigation, model: BugReportViewModel = viewModel()) val bugReportID = model.bugReportID.collectAsState().value Scaffold(topBar = { Header(R.string.bug_report_title, onBack = nav.onBack) }) { innerPadding -> - Column( - modifier = Modifier.padding(innerPadding).padding(24.dp).fillMaxWidth().fillMaxHeight()) { - ClickableText( - text = contactText(), - modifier = Modifier.fillMaxWidth(), - onClick = { handler.openUri(Links.SUPPORT_URL) }) + Column(modifier = Modifier.padding(innerPadding).fillMaxWidth().fillMaxHeight()) { + ListItem( + headlineContent = { + ClickableText( + text = contactText(), + modifier = Modifier.fillMaxWidth(), + onClick = { handler.openUri(Links.SUPPORT_URL) }) + }) - Spacer(modifier = Modifier.height(16.dp)) + Lists.SectionDivider() - ClipboardValueView(bugReportID, title = stringResource(R.string.bug_report_id)) + ClipboardValueView(bugReportID, title = stringResource(R.string.bug_report_id)) - Spacer(modifier = Modifier.height(16.dp)) - - Text( - text = stringResource(id = R.string.bug_report_id_desc), - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Left, - color = MaterialTheme.colorScheme.secondary, - style = MaterialTheme.typography.bodySmall) - } + Lists.SectionDivider() + + ListItem( + headlineContent = { + Text( + text = stringResource(id = R.string.bug_report_id_desc), + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Left, + color = MaterialTheme.colorScheme.secondary, + style = MaterialTheme.typography.bodySmall) + }) + } } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt index 469c0a8..0c18207 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/DNSSettingsView.kt @@ -3,32 +3,28 @@ package com.tailscale.ipn.ui.view -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.R import com.tailscale.ipn.ui.model.DnsType import com.tailscale.ipn.ui.util.ClipboardValueView +import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.LoadingIndicator +import com.tailscale.ipn.ui.util.itemsWithDividers import com.tailscale.ipn.ui.viewModel.DNSEnablementState import com.tailscale.ipn.ui.viewModel.DNSSettingsViewModel import com.tailscale.ipn.ui.viewModel.DNSSettingsViewModelFactory data class ViewableRoute(val name: String, val resolvers: List) +@OptIn(ExperimentalFoundationApi::class) @Composable fun DNSSettingsView( nav: BackNavigation, @@ -44,43 +40,30 @@ fun DNSSettingsView( Scaffold(topBar = { Header(R.string.dns_settings, onBack = nav.onBack) }) { innerPadding -> LoadingIndicator.Wrap { - LazyColumn(Modifier.padding(innerPadding).padding(16.dp)) { + LazyColumn(Modifier.padding(innerPadding)) { item("state") { FeatureStateView(state) } item("toggle") { SettingRow(model.useDNSSetting) } if (resolvers.isNotEmpty()) { - item("resolversHeader") { - Text(stringResource(R.string.resolvers), fontWeight = FontWeight.SemiBold) - Spacer(Modifier.size(8.dp)) - } + item("resolversHeader") { Lists.SectionDivider(stringResource(R.string.resolvers)) } - items(resolvers) { resolver -> - ClipboardValueView(resolver.Addr.orEmpty()) - Spacer(Modifier.size(8.dp)) - } + itemsWithDividers(resolvers) { resolver -> ClipboardValueView(resolver.Addr.orEmpty()) } } if (domains.isNotEmpty()) { - item("domainsHeader") { - Text(stringResource(R.string.search_domains), fontWeight = FontWeight.SemiBold) - Spacer(Modifier.size(8.dp)) - } - items(domains) { domain -> - ClipboardValueView(domain) - Spacer(Modifier.size(8.dp)) - } + item("domainsHeader") { Lists.SectionDivider(stringResource(R.string.search_domains)) } + + itemsWithDividers(domains) { domain -> ClipboardValueView(domain) } } if (routes.isNotEmpty()) { - item("routesHeader") { Spacer(Modifier.size(8.dp)) } - items(routes) { route -> - Text("Route: ${route.name}", fontWeight = FontWeight.SemiBold) - Spacer(Modifier.size(8.dp)) - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - route.resolvers.forEach { ClipboardValueView(it.Addr.orEmpty()) } + routes.forEach { route -> + item { Lists.SectionDivider("Route: ${route.name}") } + + itemsWithDividers(route.resolvers) { resolver -> + ClipboardValueView(resolver.Addr.orEmpty()) } - Spacer(Modifier.size(16.dp)) } } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt b/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt index 053217c..4ed98c6 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/ExitNodePicker.kt @@ -13,6 +13,7 @@ import androidx.compose.material.icons.outlined.Check import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -45,12 +46,11 @@ fun ExitNodePicker( val anyActive = model.anyActive.collectAsState() LazyColumn(modifier = Modifier.padding(innerPadding)) { - item(key = "runExitNode") { - RunAsExitNodeItem(nav = nav, viewModel = model) - Lists.SectionDivider() - } + item("allowLANAccessToggle") { SettingRow(model.allowLANAccessSetting) } item(key = "none") { + Lists.SectionDivider() + ExitNodeItem( model, ExitNodePickerViewModel.ExitNode( @@ -72,7 +72,10 @@ fun ExitNodePicker( } } - item("allowLANAccessToggle") { SettingRow(model.allowLANAccessSetting) } + item(key = "runExitNode") { + Lists.SectionDivider() + RunAsExitNodeItem(nav = nav, viewModel = model) + } } } } @@ -88,8 +91,17 @@ fun ExitNodeItem( ListItem( modifier = Modifier.clickableOrGrayedOut(enabled = node.online) { viewModel.setExitNode(node) }, - headlineContent = { Text(node.city.ifEmpty { node.label }) }, - supportingContent = { if (!node.online) Text(stringResource(R.string.offline)) }, + headlineContent = { + Text( + node.city.ifEmpty { node.label }, + style = + if (node.online) MaterialTheme.typography.titleMedium + else MaterialTheme.typography.bodyMedium) + }, + supportingContent = { + if (!node.online) + Text(stringResource(R.string.offline), style = MaterialTheme.typography.bodyMedium) + }, trailingContent = { Row { if (node.selected) { @@ -105,8 +117,16 @@ fun MullvadItem(nav: ExitNodePickerNav, count: Int, selected: Boolean) { Box { ListItem( modifier = Modifier.clickable { nav.onNavigateToMullvad() }, - headlineContent = { Text(stringResource(R.string.mullvad_exit_nodes)) }, - supportingContent = { Text("$count ${stringResource(R.string.nodes_available)}") }, + headlineContent = { + Text( + stringResource(R.string.mullvad_exit_nodes), + style = MaterialTheme.typography.titleMedium) + }, + supportingContent = { + Text( + "$count ${stringResource(R.string.nodes_available)}", + style = MaterialTheme.typography.bodyMedium) + }, trailingContent = { if (selected) { Icon(Icons.Outlined.Check, contentDescription = stringResource(R.string.selected)) @@ -122,7 +142,11 @@ fun RunAsExitNodeItem(nav: ExitNodePickerNav, viewModel: ExitNodePickerViewModel Box { ListItem( modifier = Modifier.clickable { nav.onNavigateToRunAsExitNode() }, - headlineContent = { Text(stringResource(id = R.string.run_as_exit_node)) }, + headlineContent = { + Text( + stringResource(id = R.string.run_as_exit_node), + style = MaterialTheme.typography.titleMedium) + }, trailingContent = { if (isRunningExitNode) { Text(stringResource(R.string.enabled)) diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/FeatureStateView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/FeatureStateView.kt index 538fbff..6affe18 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/FeatureStateView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/FeatureStateView.kt @@ -3,19 +3,15 @@ package com.tailscale.ipn.ui.view -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.tailscale.ipn.ui.util.FeatureStateRepresentation @@ -23,22 +19,16 @@ import com.tailscale.ipn.ui.util.FeatureStateRepresentation // a FeatureStateRepresentation. @Composable fun FeatureStateView(state: FeatureStateRepresentation) { - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.padding(bottom = 16.dp)) { + ListItem( + leadingContent = { Icon( painter = painterResource(state.symbolDrawable), contentDescription = null, tint = state.tint, modifier = Modifier.size(64.dp)) - Column { - Text( - stringResource(state.title), - fontSize = MaterialTheme.typography.titleMedium.fontSize, - fontWeight = FontWeight.SemiBold) - Text( - stringResource(state.caption), - color = MaterialTheme.colorScheme.secondary) - } - } + }, + headlineContent = { + Text(stringResource(state.title), style = MaterialTheme.typography.titleMedium) + }, + supportingContent = { Text(stringResource(state.caption)) }) } diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/MDMSettingsDebugView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/MDMSettingsDebugView.kt index c58e2a9..c8d3044 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/MDMSettingsDebugView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/MDMSettingsDebugView.kt @@ -32,37 +32,40 @@ fun MDMSettingsDebugView(nav: BackNavigation, model: IpnViewModel = viewModel()) -> val mdmSettings = IpnViewModel.mdmSettings.collectAsState().value LazyColumn(modifier = Modifier.padding(innerPadding)) { - itemsWithDividers(enumValues()) { booleanSetting -> + itemsWithDividers(enumValues(), key = { it.key }) { booleanSetting -> MDMSettingView( title = booleanSetting.localizedTitle, caption = booleanSetting.key, valueDescription = mdmSettings.get(booleanSetting).toString()) } - itemsWithDividers(enumValues(), forceLeading = true) { stringSetting -> + itemsWithDividers(enumValues(), key = { it.key }, forceLeading = true) { + stringSetting -> MDMSettingView( title = stringSetting.localizedTitle, caption = stringSetting.key, valueDescription = mdmSettings.get(stringSetting).toString()) } - itemsWithDividers(enumValues(), forceLeading = true) { showHideSetting -> + itemsWithDividers(enumValues(), key = { it.key }, forceLeading = true) { + showHideSetting -> MDMSettingView( title = showHideSetting.localizedTitle, caption = showHideSetting.key, valueDescription = mdmSettings.get(showHideSetting).toString()) } - itemsWithDividers(enumValues(), forceLeading = true) { - anuSetting -> - MDMSettingView( - title = anuSetting.localizedTitle, - caption = anuSetting.key, - valueDescription = mdmSettings.get(anuSetting).toString()) - } + itemsWithDividers( + enumValues(), key = { it.key }, forceLeading = true) { + anuSetting -> + MDMSettingView( + title = anuSetting.localizedTitle, + caption = anuSetting.key, + valueDescription = mdmSettings.get(anuSetting).toString()) + } - itemsWithDividers(enumValues(), forceLeading = true) { stringArraySetting - -> + itemsWithDividers(enumValues(), key = { it.key }, forceLeading = true) { + stringArraySetting -> MDMSettingView( title = stringArraySetting.localizedTitle, caption = stringArraySetting.key, diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePickerList.kt b/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePickerList.kt index 7012376..63527bb 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePickerList.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/MullvadExitNodePickerList.kt @@ -69,11 +69,14 @@ fun MullvadExitNodePickerList( style = MaterialTheme.typography.titleLarge, ) }, - headlineContent = { Text(first.country) }, + headlineContent = { + Text(first.country, style = MaterialTheme.typography.titleMedium) + }, supportingContent = { Text( if (nodes.size == 1) first.city - else "${nodes.size} ${stringResource(R.string.cities_available)}") + else "${nodes.size} ${stringResource(R.string.cities_available)}", + style = MaterialTheme.typography.bodyMedium) }, trailingContent = { if (nodes.size > 1 && nodes.selected || first.selected) { 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 1adb737..e302854 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,9 +3,6 @@ package com.tailscale.ipn.ui.view -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -13,6 +10,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.ClickableText import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text @@ -33,6 +31,7 @@ import com.tailscale.ipn.R import com.tailscale.ipn.ui.Links import com.tailscale.ipn.ui.theme.ts_color_light_blue import com.tailscale.ipn.ui.util.ClipboardValueView +import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.LoadingIndicator import com.tailscale.ipn.ui.viewModel.TailnetLockSetupViewModel import com.tailscale.ipn.ui.viewModel.TailnetLockSetupViewModelFactory @@ -48,49 +47,39 @@ fun TailnetLockSetupView( Scaffold(topBar = { Header(R.string.tailnet_lock, onBack = nav.onBack) }) { innerPadding -> LoadingIndicator.Wrap { - LazyColumn( - verticalArrangement = Arrangement.spacedBy(10.dp), - modifier = Modifier.padding(innerPadding)) { - item(key = "header") { - ExplainerView() - Spacer(Modifier.size(4.dp)) - } + LazyColumn(modifier = Modifier.padding(innerPadding)) { + item(key = "header") { + ExplainerView() + Spacer(Modifier.size(4.dp)) + } - items(items = statusItems) { statusItem -> - Row( - horizontalArrangement = Arrangement.spacedBy(12.dp), - modifier = Modifier.padding(horizontal = 16.dp)) { - Icon( - painter = painterResource(id = statusItem.icon), - contentDescription = null, - tint = ts_color_light_blue) - Text(stringResource(statusItem.title)) - } - } + items(items = statusItems, key = { "status_${it.title}" }) { statusItem -> + ListItem( + leadingContent = { + Icon( + painter = painterResource(id = statusItem.icon), + contentDescription = null, + tint = ts_color_light_blue) + }, + headlineContent = { Text(stringResource(statusItem.title)) }) + } - item(key = "nodeKey") { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(horizontal = 16.dp)) { - Spacer(Modifier.size(4.dp)) - ClipboardValueView( - value = nodeKey, - title = stringResource(R.string.node_key), - subtitle = stringResource(R.string.node_key_explainer)) - } - } + item(key = "nodeKey") { + Lists.SectionDivider() - item(key = "tailnetLockKey") { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(horizontal = 16.dp)) { - ClipboardValueView( - value = tailnetLockKey, - title = stringResource(R.string.tailnet_lock_key), - subtitle = stringResource(R.string.tailnet_lock_key_explainer)) - } - } - } + ClipboardValueView( + value = nodeKey, + title = stringResource(R.string.node_key), + subtitle = stringResource(R.string.node_key_explainer)) + } + + item(key = "tailnetLockKey") { + ClipboardValueView( + value = tailnetLockKey, + title = stringResource(R.string.tailnet_lock_key), + subtitle = stringResource(R.string.tailnet_lock_key_explainer)) + } + } } } }