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

Commit 3af89971 authored by Ale Nijamkin's avatar Ale Nijamkin Committed by Android (Google) Code Review
Browse files

Merge "[flexiglass] Splits up PIN user input when split layout." into main

parents 33bc892f 14a7b0a8
Loading
Loading
Loading
Loading
+71 −24
Original line number Diff line number Diff line
@@ -154,7 +154,7 @@ private fun SceneScope.BouncerScene(
                Bouncer(
                    viewModel = viewModel,
                    dialogFactory = dialogFactory,
                    isUserInputAreaVisible = true,
                    userInputAreaVisibility = UserInputAreaVisibility.FULL,
                    modifier = childModifier,
                )
            Layout.SIDE_BY_SIDE ->
@@ -189,7 +189,7 @@ private fun SceneScope.BouncerScene(
private fun Bouncer(
    viewModel: BouncerViewModel,
    dialogFactory: BouncerSceneDialogFactory,
    isUserInputAreaVisible: Boolean,
    userInputAreaVisibility: UserInputAreaVisibility,
    modifier: Modifier = Modifier,
) {
    val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
@@ -214,13 +214,12 @@ private fun Bouncer(
        }

        Box(Modifier.weight(1f)) {
            if (isUserInputAreaVisible) {
            UserInputArea(
                viewModel = viewModel,
                visibility = userInputAreaVisibility,
                modifier = Modifier.align(Alignment.Center),
            )
        }
        }

        if (viewModel.isEmergencyButtonVisible) {
            Button(
@@ -269,6 +268,7 @@ private fun Bouncer(
@Composable
private fun UserInputArea(
    viewModel: BouncerViewModel,
    visibility: UserInputAreaVisibility,
    modifier: Modifier = Modifier,
) {
    val authMethodViewModel: AuthMethodBouncerViewModel? by
@@ -276,21 +276,46 @@ private fun UserInputArea(

    when (val nonNullViewModel = authMethodViewModel) {
        is PinBouncerViewModel ->
            when (visibility) {
                UserInputAreaVisibility.FULL ->
                    PinBouncer(
                        viewModel = nonNullViewModel,
                        modifier = modifier,
                    )
                UserInputAreaVisibility.INPUT_ONLY ->
                    PinPad(
                        viewModel = nonNullViewModel,
                        modifier = modifier,
                    )
                UserInputAreaVisibility.OUTPUT_ONLY ->
                    PinInputDisplay(
                        viewModel = nonNullViewModel,
                        modifier = modifier,
                    )
                UserInputAreaVisibility.NONE -> {}
            }
        is PasswordBouncerViewModel ->
            when (visibility) {
                UserInputAreaVisibility.FULL,
                UserInputAreaVisibility.INPUT_ONLY ->
                    PasswordBouncer(
                        viewModel = nonNullViewModel,
                        modifier = modifier,
                    )
                else -> {}
            }
        is PatternBouncerViewModel ->
            when (visibility) {
                UserInputAreaVisibility.FULL,
                UserInputAreaVisibility.INPUT_ONLY ->
                    PatternBouncer(
                        viewModel = nonNullViewModel,
                        modifier =
                    Modifier.aspectRatio(1f, matchHeightConstraintsFirst = false).then(modifier)
                            Modifier.aspectRatio(1f, matchHeightConstraintsFirst = false)
                                .then(modifier)
                    )
                else -> {}
            }
        else -> Unit
    }
}
@@ -435,13 +460,14 @@ private fun Split(
            Bouncer(
                viewModel = viewModel,
                dialogFactory = dialogFactory,
                isUserInputAreaVisible = false,
                userInputAreaVisibility = UserInputAreaVisibility.OUTPUT_ONLY,
                modifier = startContentModifier,
            )
        },
        endContent = { endContentModifier ->
            UserInputArea(
                viewModel = viewModel,
                visibility = UserInputAreaVisibility.INPUT_ONLY,
                modifier = endContentModifier,
            )
        },
@@ -545,7 +571,7 @@ private fun SideBySide(
            Bouncer(
                viewModel = viewModel,
                dialogFactory = dialogFactory,
                isUserInputAreaVisible = true,
                userInputAreaVisibility = UserInputAreaVisibility.FULL,
                modifier = endContentModifier,
            )
        },
@@ -574,7 +600,7 @@ private fun Stacked(
        Bouncer(
            viewModel = viewModel,
            dialogFactory = dialogFactory,
            isUserInputAreaVisible = true,
            userInputAreaVisibility = UserInputAreaVisibility.FULL,
            modifier = Modifier.fillMaxWidth().weight(1f),
        )
    }
@@ -630,6 +656,27 @@ private enum class Layout {
    SPLIT,
}

/** Enumerates all supported user-input area visibilities. */
private enum class UserInputAreaVisibility {
    /**
     * The entire user input area is shown, including where the user enters input and where it's
     * reflected to the user.
     */
    FULL,
    /**
     * Only the area where the user enters the input is shown; the area where the input is reflected
     * back to the user is not shown.
     */
    INPUT_ONLY,
    /**
     * Only the area where the input is reflected back to the user is shown; the area where the
     * input is entered by the user is not shown.
     */
    OUTPUT_ONLY,
    /** The entire user input area is hidden. */
    NONE,
}

/**
 * Calculates an alpha for the user switcher and bouncer such that it's at `1` when the offset of
 * the two reaches a stopping point but `0` in the middle of the transition.
+6 −2
Original line number Diff line number Diff line
@@ -55,12 +55,12 @@ import androidx.compose.ui.unit.dp
import com.android.compose.animation.Easings
import com.android.compose.grid.VerticalGrid
import com.android.compose.modifiers.thenIf
import com.android.systemui.res.R
import com.android.systemui.bouncer.ui.viewmodel.ActionButtonAppearance
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.res.R
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.DurationUnit
import kotlinx.coroutines.async
@@ -93,7 +93,10 @@ internal fun PinBouncer(
}

@Composable
private fun PinPad(viewModel: PinBouncerViewModel) {
fun PinPad(
    viewModel: PinBouncerViewModel,
    modifier: Modifier = Modifier,
) {
    val isInputEnabled: Boolean by viewModel.isInputEnabled.collectAsState()
    val backspaceButtonAppearance by viewModel.backspaceButtonAppearance.collectAsState()
    val confirmButtonAppearance by viewModel.confirmButtonAppearance.collectAsState()
@@ -112,6 +115,7 @@ private fun PinPad(viewModel: PinBouncerViewModel) {
        columns = 3,
        verticalSpacing = 12.dp,
        horizontalSpacing = 20.dp,
        modifier = modifier,
    ) {
        repeat(9) { index ->
            DigitButton(
+14 −8
Original line number Diff line number Diff line
@@ -51,10 +51,10 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.android.compose.animation.Easings
import com.android.keyguard.PinShapeAdapter
import com.android.systemui.res.R
import com.android.systemui.bouncer.ui.viewmodel.EntryToken.Digit
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PinInputViewModel
import com.android.systemui.res.R
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
@@ -65,7 +65,10 @@ import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch

@Composable
fun PinInputDisplay(viewModel: PinBouncerViewModel) {
fun PinInputDisplay(
    viewModel: PinBouncerViewModel,
    modifier: Modifier = Modifier,
) {
    val hintedPinLength: Int? by viewModel.hintedPinLength.collectAsState()
    val shapeAnimations = rememberShapeAnimations(viewModel.pinShapes)

@@ -81,8 +84,8 @@ fun PinInputDisplay(viewModel: PinBouncerViewModel) {
    // unifying into a single, more complex implementation.

    when (val length = hintedPinLength) {
        null -> RegularPinInputDisplay(viewModel, shapeAnimations)
        else -> HintingPinInputDisplay(viewModel, shapeAnimations, length)
        null -> RegularPinInputDisplay(viewModel, shapeAnimations, modifier)
        else -> HintingPinInputDisplay(viewModel, shapeAnimations, length, modifier)
    }
}

@@ -97,6 +100,7 @@ private fun HintingPinInputDisplay(
    viewModel: PinBouncerViewModel,
    shapeAnimations: ShapeAnimations,
    hintedPinLength: Int,
    modifier: Modifier = Modifier,
) {
    val pinInput: PinInputViewModel by viewModel.pinInput.collectAsState()
    // [ClearAll] marker pointing at the beginning of the current pin input.
@@ -151,7 +155,7 @@ private fun HintingPinInputDisplay(
    LaunchedEffect(Unit) { playAnimation = true }

    val dotColor = MaterialTheme.colorScheme.onSurfaceVariant
    Row(modifier = Modifier.heightIn(min = shapeAnimations.shapeSize)) {
    Row(modifier = modifier.heightIn(min = shapeAnimations.shapeSize)) {
        pinEntryDrawable.forEachIndexed { index, drawable ->
            // Key the loop by [index] and [drawable], so that updating a shape drawable at the same
            // index will play the new animation (by remembering a new [atEnd]).
@@ -183,6 +187,7 @@ private fun HintingPinInputDisplay(
private fun RegularPinInputDisplay(
    viewModel: PinBouncerViewModel,
    shapeAnimations: ShapeAnimations,
    modifier: Modifier = Modifier,
) {
    // Holds all currently [VisiblePinEntry] composables. This cannot be simply derived from
    // `viewModel.pinInput` at composition, since deleting a pin entry needs to play a remove
@@ -226,7 +231,7 @@ private fun RegularPinInputDisplay(
            }
    }

    pinInputRow.Content()
    pinInputRow.Content(modifier)
}

private class PinInputRow(
@@ -235,10 +240,11 @@ private class PinInputRow(
    private val entries = mutableStateListOf<PinInputEntry>()

    @Composable
    fun Content() {
    fun Content(modifier: Modifier) {
        Row(
            modifier =
                Modifier.heightIn(min = shapeAnimations.shapeSize)
                modifier
                    .heightIn(min = shapeAnimations.shapeSize)
                    // Pins overflowing horizontally should still be shown as scrolling.
                    .wrapContentSize(unbounded = true),
        ) {