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

Commit 3cd3d80e authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Left and right edges of pattern bouncer are touchable

This CL makes drag gestures that start inside the gaps between the
left and right edges of the pattern bouncer pattern area and the edges
of the display still work as legitimate drag gestures.

Before this CL, drag gestures that started in those gaps to the left and
right of the pattern dot matrix did not cause dots to be selected, even
if the drag continued well into the pattern dot matrix UI area.

The approach was to make the touchable area as wide as the available
space which required a coordinate system transform when calling the
onDrag method of the view-model.

Test: manually verified that drags that start to the left or right, outside of the dot pattern matrix area are picked up and the correct dots are selected
Test: manually verified that password and PIN bouncer layouts are
unaffected
Test: manually verified that all PIN bouncer layouts (folded, unfolded,
half-folded, landscape) are unaffected
Flag: com.android.systemui.scene_container

Change-Id: I9c51a94467cc95c31a5dc7d60f4683901b1e2937
parent 865eb36b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ private fun StandardLayout(viewModel: BouncerSceneContentViewModel, modifier: Mo
        LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Expanded

    FoldAware(
        modifier = modifier.padding(start = 32.dp, top = 92.dp, end = 32.dp, bottom = 48.dp),
        modifier = modifier.padding(top = 92.dp, bottom = 48.dp),
        viewModel = viewModel,
        aboveFold = {
            Column(
+128 −100
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material3.MaterialTheme
@@ -35,6 +37,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.geometry.Offset
@@ -45,6 +48,7 @@ import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.integerResource
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.Easings
@@ -212,23 +216,27 @@ fun PatternBouncer(
    var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
    var offset: Offset by remember { mutableStateOf(Offset.Zero) }
    var scale: Float by remember { mutableStateOf(1f) }

    Canvas(
        modifier
            .sysuiResTag("bouncer_pattern_root")
    // This is the size of the drawing area, in dips.
    val dotDrawingArea =
        remember(colCount, rowCount) {
            DpSize(
                // Because the width also includes spacing to the left and right of the leftmost and
                // rightmost dots in the grid and because UX mocks specify the width without that
            // spacing, the actual width needs to be defined slightly bigger than the UX mock width.
            .width((262 * colCount / 2).dp)
            // Because the height also includes spacing above and below the topmost and bottommost
            // dots in the grid and because UX mocks specify the height without that spacing, the
                // spacing, the actual width needs to be defined slightly bigger than the UX mock
                // width.
                width = (262 * colCount / 2).dp,
                // Because the height also includes spacing above and below the topmost and
                // bottommost
                // dots in the grid and because UX mocks specify the height without that spacing,
                // the
                // actual height needs to be defined slightly bigger than the UX mock height.
            .height((262 * rowCount / 2).dp)
            // Need to clip to bounds to make sure that the lines don't follow the input pointer
            // when it leaves the bounds of the dot grid.
            .clipToBounds()
            .onGloballyPositioned { coordinates -> gridCoordinates = coordinates }
            .thenIf(isInputEnabled) {
                height = (262 * rowCount / 2).dp,
            )
        }

    Box(
        modifier =
            modifier.fillMaxWidth().thenIf(isInputEnabled) {
                Modifier.pointerInput(Unit) {
                        awaitEachGesture {
                            awaitFirstDown()
@@ -257,14 +265,26 @@ fun PatternBouncer(
                            inputPosition = change.position
                            change.position.minus(offset).div(scale).let {
                                viewModel.onDrag(
                                    xPx = it.x,
                                    xPx =
                                        it.x -
                                            ((size.width - dotDrawingArea.width.roundToPx()) / 2),
                                    yPx = it.y,
                                    containerSizePx = size.width,
                                    containerSizePx = dotDrawingArea.width.roundToPx(),
                                )
                            }
                        }
                    }
            }
    ) {
        Canvas(
            Modifier.sysuiResTag("bouncer_pattern_root")
                .width(dotDrawingArea.width)
                .height(dotDrawingArea.height)
                // Need to clip to bounds to make sure that the lines don't follow the input pointer
                // when it leaves the bounds of the dot grid.
                .clipToBounds()
                .align(Alignment.Center)
                .onGloballyPositioned { coordinates -> gridCoordinates = coordinates }
                .motionTestValues {
                    entryAnimationCompleted exportAs entryCompleted
                    dotAppearFadeInAnimatables.map { it.value.value } exportAs dotAppearFadeIn
@@ -351,15 +371,23 @@ fun PatternBouncer(
                        (1 - checkNotNull(dotAppearMoveUpAnimatables[dot]).value) * initialOffset
                    drawCircle(
                        center =
                        pixelOffset(dot, spacing, horizontalOffset, verticalOffset + appearOffset),
                            pixelOffset(
                                dot,
                                spacing,
                                horizontalOffset,
                                verticalOffset + appearOffset,
                            ),
                        color =
                        dotColor.copy(alpha = checkNotNull(dotAppearFadeInAnimatables[dot]).value),
                            dotColor.copy(
                                alpha = checkNotNull(dotAppearFadeInAnimatables[dot]).value
                            ),
                        radius = dotRadius * checkNotNull(dotScalingAnimatables[dot]).value,
                    )
                }
            }
        }
    }
}

private suspend fun showEntryAnimation(
    dotAppearFadeInAnimatables: Map<PatternDotViewModel, Animatable<Float, AnimationVector1D>>,