Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt +14 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt +37 −12 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 } } Loading @@ -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) } Loading @@ -84,7 +109,7 @@ fun GestureTutorialScreen( @Composable private fun TouchpadGesturesHandlingBox( gestureHandler: TouchpadGestureHandler, gestureState: GestureState, gestureState: GestureUiState, easterEggTriggered: Boolean, resetEasterEggFlag: () -> Unit, modifier: Modifier = Modifier, Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt +14 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt +14 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt +4 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt +14 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt +37 −12 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 } } Loading @@ -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) } Loading @@ -84,7 +109,7 @@ fun GestureTutorialScreen( @Composable private fun TouchpadGesturesHandlingBox( gestureHandler: TouchpadGestureHandler, gestureState: GestureState, gestureState: GestureUiState, easterEggTriggered: Boolean, resetEasterEggFlag: () -> Unit, modifier: Modifier = Modifier, Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt +14 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt +14 −1 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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 Loading
packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt +4 −0 Original line number Diff line number Diff line Loading @@ -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