Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39288dc4 authored by Istvan Nagy's avatar Istvan Nagy Committed by Android (Google) Code Review
Browse files

Merge "Change User switcher dropdown into pill on Bouncer" into main

parents 2eb3cba1 c4fd7e79
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -10,6 +10,13 @@ flag {
    bug: "416223998"
    bug: "416223998"
}
}


flag {
    name: "disable_user_switcher_dropdown_on_bouncer"
    namespace: "desktop_users_and_accounts"
    description: "Show pill with current user's name instead of user switcher dropdown"
    bug: "425357051"
}

flag {
flag {
    name: "sign_out_button_on_keyguard_status_bar"
    name: "sign_out_button_on_keyguard_status_bar"
    namespace: "desktop_users_and_accounts"
    namespace: "desktop_users_and_accounts"
+80 −40
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ import androidx.compose.foundation.layout.offset
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.width
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowDown
@@ -104,6 +105,7 @@ import com.android.compose.animation.scene.rememberMutableSceneTransitionLayoutS
import com.android.compose.animation.scene.transitions
import com.android.compose.animation.scene.transitions
import com.android.compose.modifiers.thenIf
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.Flags
import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel
import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel
import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.AuthMethodBouncerViewModel
@@ -898,6 +900,7 @@ private fun Dialog(
@Composable
@Composable
private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) {
private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Modifier = Modifier) {
    val isUserSwitcherVisible by viewModel.isUserSwitcherVisible.collectAsStateWithLifecycle()
    val isUserSwitcherVisible by viewModel.isUserSwitcherVisible.collectAsStateWithLifecycle()
    val dropdownItems by viewModel.userSwitcherDropdown.collectAsStateWithLifecycle(emptyList())
    if (!isUserSwitcherVisible) {
    if (!isUserSwitcherVisible) {
        // Take up the same space as the user switcher normally would, but with nothing inside it.
        // Take up the same space as the user switcher normally would, but with nothing inside it.
        Box(modifier = modifier)
        Box(modifier = modifier)
@@ -905,10 +908,8 @@ private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Mo
    }
    }


    val selectedUserImage by viewModel.selectedUserImage.collectAsStateWithLifecycle(null)
    val selectedUserImage by viewModel.selectedUserImage.collectAsStateWithLifecycle(null)
    val dropdownItems by viewModel.userSwitcherDropdown.collectAsStateWithLifecycle(emptyList())
    val userSwitcherIconSize = dimensionResource(R.dimen.bouncer_user_switcher_icon_size)
    val userSwitcherIconSize = dimensionResource(R.dimen.bouncer_user_switcher_icon_size)
    val dropDownWidth = userSwitcherIconSize + UserSwitcherDropdownExtraWidth
    val maxUserSwitcherWidth = userSwitcherIconSize + UserSwitcherDropdownExtraWidth

    Column(
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
        verticalArrangement = Arrangement.Center,
@@ -921,19 +922,59 @@ private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Mo
                modifier = Modifier.size(userSwitcherIconSize).sysuiResTag("user_icon"),
                modifier = Modifier.size(userSwitcherIconSize).sysuiResTag("user_icon"),
            )
            )
        }
        }
        if (Flags.disableUserSwitcherDropdownOnBouncer() && dropdownItems.size <= 1) {
            Spacer(modifier = Modifier.height(24.dp))
            UserNamePill(viewModel = viewModel, maxWidth = maxUserSwitcherWidth)
        } else {
            Spacer(modifier = Modifier.height(40.dp))
            UserSwitcherDropdown(viewModel = viewModel, width = maxUserSwitcherWidth)
        }
    }
}

/**
 * Displays the current user's name in a stylized pill shape. This is used when the user switcher
 * dropdown is disabled.
 */
@Composable
private fun UserNamePill(viewModel: BouncerOverlayContentViewModel, maxWidth: Dp) {
    val selectedUserName by viewModel.selectedUserName.collectAsStateWithLifecycle()
    val context = LocalContext.current
    selectedUserName.loadText(context)?.let { userName ->
        Text(
            text = userName,
            style = MaterialTheme.typography.titleMedium,
            color = MaterialTheme.colorScheme.onSurface,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
            modifier =
                Modifier.widthIn(max = maxWidth)
                    .background(
                        color = MaterialTheme.colorScheme.surfaceContainer,
                        shape = RoundedCornerShape(percent = 50),
                    )
                    .padding(horizontal = 24.dp, vertical = 16.dp),
        )
    }
}


/**
 * Displays the current user's name and an arrow, which can be clicked to expand a dropdown menu for
 * switching users.
 */
@Composable
private fun UserSwitcherDropdown(viewModel: BouncerOverlayContentViewModel, width: Dp) {
    val dropdownItems by viewModel.userSwitcherDropdown.collectAsStateWithLifecycle(emptyList())
    val (isDropdownExpanded, setDropdownExpanded) = remember { mutableStateOf(false) }
    val (isDropdownExpanded, setDropdownExpanded) = remember { mutableStateOf(false) }


    dropdownItems.firstOrNull()?.let { firstDropdownItem ->
    dropdownItems.firstOrNull()?.let { firstDropdownItem ->
            Spacer(modifier = Modifier.height(40.dp))

        Box {
        Box {
            PlatformButton(
            PlatformButton(
                modifier =
                modifier =
                    Modifier
                    Modifier
                        // Remove the built-in padding applied inside PlatformButton:
                        // Remove the built-in padding applied inside PlatformButton:
                        .padding(vertical = 0.dp)
                        .padding(vertical = 0.dp)
                            .width(dropDownWidth)
                        .width(width)
                        .height(UserSwitcherDropdownHeight),
                        .height(UserSwitcherDropdownHeight),
                colors =
                colors =
                    ButtonDefaults.buttonColors(
                    ButtonDefaults.buttonColors(
@@ -945,7 +986,7 @@ private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Mo
                val context = LocalContext.current
                val context = LocalContext.current
                Text(
                Text(
                    text = checkNotNull(firstDropdownItem.text.loadText(context)),
                    text = checkNotNull(firstDropdownItem.text.loadText(context)),
                        style = MaterialTheme.typography.labelMedium,
                    style = MaterialTheme.typography.headlineSmall,
                    maxLines = 1,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    overflow = TextOverflow.Ellipsis,
                )
                )
@@ -962,13 +1003,12 @@ private fun UserSwitcher(viewModel: BouncerOverlayContentViewModel, modifier: Mo
            UserSwitcherDropdownMenu(
            UserSwitcherDropdownMenu(
                isExpanded = isDropdownExpanded,
                isExpanded = isDropdownExpanded,
                items = dropdownItems,
                items = dropdownItems,
                    dropDownWidth = dropDownWidth,
                dropDownWidth = width,
                onDismissed = { setDropdownExpanded(false) },
                onDismissed = { setDropdownExpanded(false) },
            )
            )
        }
        }
    }
    }
}
}
}


/**
/**
 * Renders the dropdown menu that displays the actual users and/or user actions that can be
 * Renders the dropdown menu that displays the actual users and/or user actions that can be
+7 −0
Original line number Original line Diff line number Diff line
@@ -84,6 +84,9 @@ constructor(
    private val _selectedUserImage = MutableStateFlow<Bitmap?>(null)
    private val _selectedUserImage = MutableStateFlow<Bitmap?>(null)
    val selectedUserImage: StateFlow<Bitmap?> = _selectedUserImage.asStateFlow()
    val selectedUserImage: StateFlow<Bitmap?> = _selectedUserImage.asStateFlow()


    private val _selectedUserName = MutableStateFlow<Text?>(null)
    val selectedUserName: StateFlow<Text?> = _selectedUserName.asStateFlow()

    val message: BouncerMessageViewModel by lazy { bouncerMessageViewModelFactory.create() }
    val message: BouncerMessageViewModel by lazy { bouncerMessageViewModelFactory.create() }


    private val _userSwitcherDropdown =
    private val _userSwitcherDropdown =
@@ -212,6 +215,10 @@ constructor(
                    .collect { _selectedUserImage.value = it }
                    .collect { _selectedUserImage.value = it }
            }
            }


            launch {
                userSwitcher.selectedUser.map { it.name }.collect { _selectedUserName.value = it }
            }

            launch {
            launch {
                combine(userSwitcher.users, userSwitcher.menu) { users, actions ->
                combine(userSwitcher.users, userSwitcher.menu) { users, actions ->
                        users.map { user ->
                        users.map { user ->