Signed-off-by: Percy Wegmann <percy@tailscale.com>
ox/move_admin_account_info
Percy Wegmann 1 month ago
parent 3d422fafd4
commit cfc3f4bb59
No known key found for this signature in database
GPG Key ID: 29D8CDEB4C13D48B

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

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

@ -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<Boolean> = MutableStateFlow(false)
val managedByOrganization = MDMSettings.managedByOrganizationName.flow
init {
viewModelScope.launch {
Notifier.netmap.collect { netmap -> isAdmin.set(netmap?.SelfNode?.isAdmin ?: false) }
}
}
}

@ -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<Boolean> = MutableStateFlow(false)
// Sets the custom control URL and immediatly invokes the login flow
val isAdmin: StateFlow<Boolean> = 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,

@ -98,7 +98,7 @@
<string name="logout_failed">Unable to logout at this time. Please try again.</string>
<string name="error">Error</string>
<string name="accounts">Accounts</string>
<string name="add_account">Add another account</string>
<string name="add_account">Add another account</string>
<string name="add_account_short">Add account</string>
<string name="reauthenticate">Reauthenticate</string>
<string name="switch_user_failed">Unable to switch users. Please try again.</string>

Loading…
Cancel
Save