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

Commit c8b2a14b authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Foldable UI support for bouncer.

A small tweak to get the foldable UI just right.

Because the user switcher UI shouldn't be available on non-tablet
devices like foldables, the presentation logic in the composable is
slightly changed.

Note that for the unfolded + landscape case we do want to use the side-by-side layout, but we want an
empty placeholder instead of the user switcher.

Fix: 299343639
Test: manually tested folded, unfolded + landscape, unfolded + portrait
on foldable device with pattern unlock
Test: manually tested tablet device in landscape and portrait, also with
pattern unlock

Change-Id: Ibe9611209ea9b2b4f03ecf72db72e7dbab88a072
parent ed928340
Loading
Loading
Loading
Loading
+21 −11
Original line number Diff line number Diff line
@@ -144,15 +144,17 @@ private fun SceneScope.BouncerScene(
        }

        val childModifier = Modifier.element(Bouncer.Elements.Content).fillMaxSize()
        val isFullScreenUserSwitcherEnabled = viewModel.isUserSwitcherVisible

        when (windowSizeClass.widthSizeClass) {
            WindowWidthSizeClass.Expanded ->
        when {
            windowSizeClass.widthSizeClass == WindowWidthSizeClass.Expanded ->
                SideBySide(
                    viewModel = viewModel,
                    dialogFactory = dialogFactory,
                    modifier = childModifier,
                )
            WindowWidthSizeClass.Medium ->
            isFullScreenUserSwitcherEnabled &&
                windowSizeClass.widthSizeClass == WindowWidthSizeClass.Medium ->
                Stacked(
                    viewModel = viewModel,
                    dialogFactory = dialogFactory,
@@ -442,14 +444,22 @@ private fun SideBySide(
                label = "offset",
            )

        UserSwitcher(
            viewModel = viewModel,
            modifier =
        val userSwitcherModifier =
            Modifier.fillMaxHeight().weight(1f).graphicsLayer {
                translationX = size.width * animatedOffset
                alpha = animatedAlpha(animatedOffset)
                },
            }
        if (viewModel.isUserSwitcherVisible) {
            UserSwitcher(
                viewModel = viewModel,
                modifier = userSwitcherModifier,
            )
        } else {
            Box(
                modifier = userSwitcherModifier,
            )
        }

        Box(
            modifier =
                Modifier.fillMaxHeight().weight(1f).graphicsLayer {
+10 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.systemui.bouncer.data.repository

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -24,11 +26,18 @@ import kotlinx.coroutines.flow.asStateFlow

/** Provides access to bouncer-related application state. */
@SysUISingleton
class BouncerRepository @Inject constructor() {
class BouncerRepository
@Inject
constructor(
    flags: FeatureFlagsClassic,
) {
    private val _message = MutableStateFlow<String?>(null)
    /** The user-facing message to show in the bouncer. */
    val message: StateFlow<String?> = _message.asStateFlow()

    /** Whether the user switcher should be displayed within the bouncer UI on large screens. */
    val isUserSwitcherVisible: Boolean = flags.isEnabled(Flags.FULL_SCREEN_USER_SWITCHER)

    fun setMessage(message: String?) {
        _message.value = message
    }
+3 −0
Original line number Diff line number Diff line
@@ -96,6 +96,9 @@ constructor(
    /** Whether the pattern should be visible for the currently-selected user. */
    val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible

    /** Whether the user switcher should be displayed within the bouncer UI on large screens. */
    val isUserSwitcherVisible: Boolean = repository.isUserSwitcherVisible

    init {
        if (flags.isEnabled()) {
            // Clear the message if moved from throttling to no-longer throttling.
+2 −0
Original line number Diff line number Diff line
@@ -99,6 +99,8 @@ class BouncerViewModel(
                initialValue = emptyList(),
            )

    val isUserSwitcherVisible: Boolean = bouncerInteractor.isUserSwitcherVisible

    private val isInputEnabled: StateFlow<Boolean> =
        bouncerInteractor.isThrottled
            .map { !it }
+6 −2
Original line number Diff line number Diff line
@@ -82,7 +82,11 @@ class SceneTestUtils(
) {
    val testDispatcher = StandardTestDispatcher()
    val testScope = TestScope(testDispatcher)
    val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
    val featureFlags =
        FakeFeatureFlagsClassic().apply {
            set(Flags.FACE_AUTH_REFACTOR, false)
            set(Flags.FULL_SCREEN_USER_SWITCHER, false)
        }
    val sceneContainerFlags = FakeSceneContainerFlags().apply { enabled = true }
    val deviceEntryRepository: FakeDeviceEntryRepository by lazy { FakeDeviceEntryRepository() }
    val authenticationRepository: FakeAuthenticationRepository by lazy {
@@ -215,7 +219,7 @@ class SceneTestUtils(
        return BouncerInteractor(
            applicationScope = applicationScope(),
            applicationContext = context,
            repository = BouncerRepository(),
            repository = BouncerRepository(featureFlags),
            deviceEntryInteractor = deviceEntryInteractor,
            authenticationInteractor = authenticationInteractor,
            sceneInteractor = sceneInteractor,