From cfc3f4bb59227b54393537ca26d0108739a2c722 Mon Sep 17 00:00:00 2001 From: Percy Wegmann Date: Fri, 5 Apr 2024 11:29:35 -0500 Subject: [PATCH] WIP Signed-off-by: Percy Wegmann --- .../com/tailscale/ipn/ui/view/SettingsView.kt | 41 ----------------- .../tailscale/ipn/ui/view/UserSwitcherView.kt | 46 ++++++++++++++++++- .../ipn/ui/viewModel/SettingsViewModel.kt | 13 ------ .../ipn/ui/viewModel/UserSwitcherViewModel.kt | 11 ++++- android/src/main/res/values/strings.xml | 2 +- 5 files changed, 55 insertions(+), 58 deletions(-) diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt index 7e569d4..fb0b2db 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/SettingsView.kt @@ -6,7 +6,6 @@ package com.tailscale.ipn.ui.view import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column 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 @@ -15,17 +14,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource -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.lifecycle.viewmodel.compose.viewModel import com.tailscale.ipn.BuildConfig import com.tailscale.ipn.R -import com.tailscale.ipn.ui.Links -import com.tailscale.ipn.ui.theme.link import com.tailscale.ipn.ui.theme.listItem import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.viewModel.SettingsNav @@ -33,9 +25,7 @@ import com.tailscale.ipn.ui.viewModel.SettingsViewModel @Composable fun SettingsView(settingsNav: SettingsNav, viewModel: SettingsViewModel = viewModel()) { - val handler = LocalUriHandler.current val user = viewModel.loggedInUser.collectAsState().value - val isAdmin = viewModel.isAdmin.collectAsState().value val managedByOrganization = viewModel.managedByOrganization.collectAsState().value Scaffold( @@ -48,10 +38,6 @@ fun SettingsView(settingsNav: SettingsNav, viewModel: SettingsViewModel = viewMo actionState = UserActionState.NAV, onClick = settingsNav.onNavigateToUserSwitcher) - if (isAdmin) { - AdminTextView { handler.openUri(Links.ADMIN_URL) } - } - Lists.SectionDivider() Setting.Text(R.string.dns_settings, onClick = settingsNav.onNavigateToDNSSettings) @@ -129,30 +115,3 @@ object Setting { }) } } - -@Composable -fun AdminTextView(onNavigateToAdminConsole: () -> Unit) { - val adminStr = buildAnnotatedString { - withStyle(style = SpanStyle(color = MaterialTheme.colorScheme.onSurfaceVariant)) { - append(stringResource(id = R.string.settings_admin_prefix)) - } - - pushStringAnnotation(tag = "link", annotation = Links.ADMIN_URL) - withStyle( - style = - SpanStyle( - color = MaterialTheme.colorScheme.link, - textDecoration = TextDecoration.Underline)) { - append(stringResource(id = R.string.settings_admin_link)) - } - pop() - } - - ListItem( - headlineContent = { - ClickableText( - text = adminStr, - style = MaterialTheme.typography.bodyMedium, - onClick = { onNavigateToAdminConsole() }) - }) -} diff --git a/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt b/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt index 02b91cc..4bd2d68 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/view/UserSwitcherView.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.text.ClickableText import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material3.DropdownMenu @@ -18,6 +19,7 @@ import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold @@ -31,10 +33,17 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource +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 +import com.tailscale.ipn.ui.theme.link import com.tailscale.ipn.ui.util.Lists import com.tailscale.ipn.ui.util.itemsWithDividers import com.tailscale.ipn.ui.util.set @@ -47,10 +56,11 @@ fun UserSwitcherView( onNavigateHome: () -> Unit, viewModel: UserSwitcherViewModel = viewModel() ) { - + val handler = LocalUriHandler.current val users = viewModel.loginProfiles.collectAsState().value val currentUser = viewModel.loggedInUser.collectAsState().value val showHeaderMenu = viewModel.showHeaderMenu.collectAsState().value + val isAdmin = viewModel.isAdmin.collectAsState().value Scaffold( topBar = { @@ -119,7 +129,12 @@ fun UserSwitcherView( } } - Lists.ItemDivider() + // if (isAdmin) { + // Lists.ItemDivider() + // AdminTextView { handler.openUri(Links.ADMIN_URL) } + // } + + Lists.SectionDivider() Setting.Text(R.string.reauthenticate) { viewModel.login {} } if (currentUser != null) { @@ -189,3 +204,30 @@ fun FusMenu(viewModel: UserSwitcherViewModel) { }) } } + +@Composable +fun AdminTextView(onNavigateToAdminConsole: () -> Unit) { + val adminStr = buildAnnotatedString { + withStyle(style = SpanStyle(color = MaterialTheme.colorScheme.onSurfaceVariant)) { + append(stringResource(id = R.string.settings_admin_prefix)) + } + + pushStringAnnotation(tag = "link", annotation = Links.ADMIN_URL) + withStyle( + style = + SpanStyle( + color = MaterialTheme.colorScheme.link, + textDecoration = TextDecoration.Underline)) { + append(stringResource(id = R.string.settings_admin_link)) + } + pop() + } + + ListItem( + headlineContent = { + ClickableText( + text = adminStr, + style = MaterialTheme.typography.bodyMedium, + onClick = { onNavigateToAdminConsole() }) + }) +} diff --git a/android/src/main/java/com/tailscale/ipn/ui/viewModel/SettingsViewModel.kt b/android/src/main/java/com/tailscale/ipn/ui/viewModel/SettingsViewModel.kt index afc59ed..e91a4a6 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/viewModel/SettingsViewModel.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/viewModel/SettingsViewModel.kt @@ -3,13 +3,7 @@ package com.tailscale.ipn.ui.viewModel -import androidx.lifecycle.viewModelScope import com.tailscale.ipn.mdm.MDMSettings -import com.tailscale.ipn.ui.notifier.Notifier -import com.tailscale.ipn.ui.util.set -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch data class SettingsNav( val onNavigateToBugReport: () -> Unit, @@ -25,12 +19,5 @@ data class SettingsNav( class SettingsViewModel() : IpnViewModel() { // Display name for the logged in user - val isAdmin: StateFlow = MutableStateFlow(false) val managedByOrganization = MDMSettings.managedByOrganizationName.flow - - init { - viewModelScope.launch { - Notifier.netmap.collect { netmap -> isAdmin.set(netmap?.SelfNode?.isAdmin ?: false) } - } - } } diff --git a/android/src/main/java/com/tailscale/ipn/ui/viewModel/UserSwitcherViewModel.kt b/android/src/main/java/com/tailscale/ipn/ui/viewModel/UserSwitcherViewModel.kt index d468fe3..c102922 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/viewModel/UserSwitcherViewModel.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/viewModel/UserSwitcherViewModel.kt @@ -11,6 +11,7 @@ import com.tailscale.ipn.ui.util.set import com.tailscale.ipn.ui.view.ErrorDialogType import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch class UserSwitcherViewModel : IpnViewModel() { @@ -20,7 +21,15 @@ class UserSwitcherViewModel : IpnViewModel() { // True if we should render the kebab menu val showHeaderMenu: StateFlow = MutableStateFlow(false) - // Sets the custom control URL and immediatly invokes the login flow + val isAdmin: StateFlow = MutableStateFlow(false) + + init { + viewModelScope.launch { + Notifier.netmap.collect { netmap -> isAdmin.set(netmap?.SelfNode?.isAdmin ?: false) } + } + } + + // Sets the custom control URL and immediately invokes the login flow fun setControlURL(urlStr: String) { // Some basic checks that the entered URL is "reasonable". The underlying // localAPIClient will use the default server if we give it a broken URL, diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml index bef3719..68d63b9 100644 --- a/android/src/main/res/values/strings.xml +++ b/android/src/main/res/values/strings.xml @@ -98,7 +98,7 @@ Unable to logout at this time. Please try again. Error Accounts - Add another account… + Add another account Add account Reauthenticate Unable to switch users. Please try again.