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

Commit 28138dc4 authored by Michał Brzeziński's avatar Michał Brzeziński Committed by Android (Google) Code Review
Browse files

Merge "Introducing GestureUiState with extra animation info" into main

parents 81dc2f34 3b282f6a
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -27,7 +27,10 @@ import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenCon
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

@Composable
fun BackGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
@@ -48,7 +51,17 @@ fun BackGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Uni
                ),
        )
    val recognizer = rememberBackGestureRecognizer(LocalContext.current.resources)
    GestureTutorialScreen(screenConfig, recognizer, onDoneButtonClicked, onBack)
    val gestureUiState: Flow<GestureUiState> =
        remember(recognizer) {
            GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
                it.toGestureUiState(
                    progressStartMark = "",
                    progressEndMark = "",
                    successAnimation = R.raw.trackpad_back_success,
                )
            }
        }
    GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
}

@Composable
+37 −12
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.touchpad.tutorial.ui.composable

import androidx.activity.compose.BackHandler
import androidx.annotation.RawRes
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
@@ -31,23 +32,49 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.inputdevice.tutorial.ui.composable.ActionTutorialContent
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.NotStarted
import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted
import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
import kotlinx.coroutines.flow.Flow

fun GestureState.toTutorialActionState(): TutorialActionState {
sealed interface GestureUiState {
    data object NotStarted : GestureUiState

    data class Finished(@RawRes val successAnimation: Int) : GestureUiState

    data class InProgress(
        val progress: Float = 0f,
        val progressStartMark: String = "",
        val progressEndMark: String = "",
    ) : GestureUiState
}

fun GestureState.toGestureUiState(
    progressStartMark: String,
    progressEndMark: String,
    successAnimation: Int,
): GestureUiState {
    return when (this) {
        GestureState.NotStarted -> NotStarted
        is GestureState.InProgress ->
            GestureUiState.InProgress(this.progress, progressStartMark, progressEndMark)
        is GestureState.Finished -> GestureUiState.Finished(successAnimation)
    }
}

fun GestureUiState.toTutorialActionState(): TutorialActionState {
    return when (this) {
        NotStarted -> TutorialActionState.NotStarted
        // progress is disabled for now as views are not ready to handle varying progress
        is InProgress -> TutorialActionState.InProgress(0f)
        Finished -> TutorialActionState.Finished
        is GestureUiState.InProgress -> TutorialActionState.InProgress(progress = 0f)
        is Finished -> TutorialActionState.Finished
    }
}

@@ -55,15 +82,13 @@ fun GestureState.toTutorialActionState(): TutorialActionState {
fun GestureTutorialScreen(
    screenConfig: TutorialScreenConfig,
    gestureRecognizer: GestureRecognizer,
    gestureUiStateFlow: Flow<GestureUiState>,
    onDoneButtonClicked: () -> Unit,
    onBack: () -> Unit,
) {
    BackHandler(onBack = onBack)
    var gestureState: GestureState by remember { mutableStateOf(NotStarted) }
    var easterEggTriggered by remember { mutableStateOf(false) }
    LaunchedEffect(gestureRecognizer) {
        gestureRecognizer.addGestureStateCallback { gestureState = it }
    }
    val gestureState by gestureUiStateFlow.collectAsStateWithLifecycle(NotStarted)
    val easterEggMonitor = EasterEggGestureMonitor { easterEggTriggered = true }
    val gestureHandler =
        remember(gestureRecognizer) { TouchpadGestureHandler(gestureRecognizer, easterEggMonitor) }
@@ -84,7 +109,7 @@ fun GestureTutorialScreen(
@Composable
private fun TouchpadGesturesHandlingBox(
    gestureHandler: TouchpadGestureHandler,
    gestureState: GestureState,
    gestureState: GestureUiState,
    easterEggTriggered: Boolean,
    resetEasterEggFlag: () -> Unit,
    modifier: Modifier = Modifier,
@@ -110,7 +135,7 @@ private fun TouchpadGesturesHandlingBox(
                .pointerInteropFilter(
                    onTouchEvent = { event ->
                        // FINISHED is the final state so we don't need to process touches anymore
                        if (gestureState == Finished) {
                        if (gestureState is Finished) {
                            false
                        } else {
                            gestureHandler.onMotionEvent(event)
+14 −1
Original line number Diff line number Diff line
@@ -25,8 +25,11 @@ import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.HomeGestureRecognizer
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

@Composable
fun HomeGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
@@ -47,7 +50,17 @@ fun HomeGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Uni
                ),
        )
    val recognizer = rememberHomeGestureRecognizer(LocalContext.current.resources)
    GestureTutorialScreen(screenConfig, recognizer, onDoneButtonClicked, onBack)
    val gestureUiState: Flow<GestureUiState> =
        remember(recognizer) {
            GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
                it.toGestureUiState(
                    progressStartMark = "",
                    progressEndMark = "",
                    successAnimation = R.raw.trackpad_home_success,
                )
            }
        }
    GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
}

@Composable
+14 −1
Original line number Diff line number Diff line
@@ -25,8 +25,11 @@ import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.RecentAppsGestureRecognizer
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

@Composable
fun RecentAppsGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
@@ -47,7 +50,17 @@ fun RecentAppsGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: ()
                ),
        )
    val recognizer = rememberRecentAppsGestureRecognizer(LocalContext.current.resources)
    GestureTutorialScreen(screenConfig, recognizer, onDoneButtonClicked, onBack)
    val gestureUiState: Flow<GestureUiState> =
        remember(recognizer) {
            GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
                it.toGestureUiState(
                    progressStartMark = "",
                    progressEndMark = "",
                    successAnimation = R.raw.trackpad_recent_apps_success,
                )
            }
        }
    GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
}

@Composable
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ class BackGestureRecognizer(private val gestureDistanceThresholdPx: Int) : Gestu
        gestureStateChangedCallback = callback
    }

    override fun clearGestureStateCallback() {
        gestureStateChangedCallback = {}
    }

    override fun accept(event: MotionEvent) {
        if (!isThreeFingerTouchpadSwipe(event)) return
        val gestureState = distanceTracker.processEvent(event)
Loading