diff options
author | 2025-01-15 13:56:07 -0800 | |
---|---|---|
committer | 2025-01-15 13:56:07 -0800 | |
commit | 17c69415fd6a9c4e76620a0ab13ece33b168c98f (patch) | |
tree | eb8c04fe06e221bc01c886a547e9feaed3d25480 | |
parent | 7b51c95ca7007029c23ea3efee890da7907b86ea (diff) | |
parent | 7a1e9beca25a6100f4c443bdeed56e95ee4e0ccc (diff) |
Merge "[Quickswitch] UI (1/n)" into main
10 files changed, 297 insertions, 6 deletions
diff --git a/packages/SystemUI/res/drawable/touchpad_tutorial_apps_icon.xml b/packages/SystemUI/res/drawable/touchpad_tutorial_apps_icon.xml new file mode 100644 index 000000000000..5f9d4212e440 --- /dev/null +++ b/packages/SystemUI/res/drawable/touchpad_tutorial_apps_icon.xml @@ -0,0 +1,25 @@ +<!-- + ~ Copyright (C) 2025 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="24dp" + android:width="24dp" + android:autoMirrored="true" + android:viewportHeight="960" + android:viewportWidth="960"> + <path android:fillColor="@android:color/white" + android:pathData="M240,800q-33,0 -56.5,-23.5T160,720q0,-33 23.5,-56.5T240,640q33,0 56.5,23.5T320,720q0,33 -23.5,56.5T240,800ZM480,800q-33,0 -56.5,-23.5T400,720q0,-33 23.5,-56.5T480,640q33,0 56.5,23.5T560,720q0,33 -23.5,56.5T480,800ZM720,800q-33,0 -56.5,-23.5T640,720q0,-33 23.5,-56.5T720,640q33,0 56.5,23.5T800,720q0,33 -23.5,56.5T720,800ZM240,560q-33,0 -56.5,-23.5T160,480q0,-33 23.5,-56.5T240,400q33,0 56.5,23.5T320,480q0,33 -23.5,56.5T240,560ZM480,560q-33,0 -56.5,-23.5T400,480q0,-33 23.5,-56.5T480,400q33,0 56.5,23.5T560,480q0,33 -23.5,56.5T480,560ZM720,560q-33,0 -56.5,-23.5T640,480q0,-33 23.5,-56.5T720,400q33,0 56.5,23.5T800,480q0,33 -23.5,56.5T720,560ZM240,320q-33,0 -56.5,-23.5T160,240q0,-33 23.5,-56.5T240,160q33,0 56.5,23.5T320,240q0,33 -23.5,56.5T240,320ZM480,320q-33,0 -56.5,-23.5T400,240q0,-33 23.5,-56.5T480,160q33,0 56.5,23.5T560,240q0,33 -23.5,56.5T480,320ZM720,320q-33,0 -56.5,-23.5T640,240q0,-33 23.5,-56.5T720,160q33,0 56.5,23.5T800,240q0,33 -23.5,56.5T720,320Z"/> +</vector> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index f2c648cb3ab0..414d3f1d17d5 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -3954,6 +3954,8 @@ <string name="touchpad_tutorial_home_gesture_button">Go home</string> <!-- Label for button opening tutorial for "view recent apps" gesture on touchpad [CHAR LIMIT=NONE] --> <string name="touchpad_tutorial_recent_apps_gesture_button">View recent apps</string> + <!-- Label for button opening tutorial for "switch apps" gesture on touchpad [CHAR LIMIT=NONE] --> + <string name="touchpad_tutorial_switch_apps_gesture_button">Switch apps</string> <!-- Label for button finishing touchpad tutorial [CHAR LIMIT=NONE] --> <string name="touchpad_tutorial_done_button">Done</string> <!-- Screen title after gesture was not done correctly [CHAR LIMIT=NONE] --> @@ -3991,6 +3993,17 @@ <string name="touchpad_recent_apps_gesture_success_body">You completed the view recent apps gesture.</string> <!-- Text shown to the user after recent gesture was not done correctly [CHAR LIMIT=NONE] --> <string name="touchpad_recent_gesture_error_body">To view recent apps, swipe up and hold using three fingers on your touchpad</string> + <!-- SWITCH APPS GESTURE --> + <!-- Touchpad switch apps gesture action name in tutorial [CHAR LIMIT=NONE] --> + <string name="touchpad_switch_apps_gesture_action_title">Switch apps</string> + <!-- Touchpad switch apps gesture guidance in gestures tutorial [CHAR LIMIT=NONE] --> + <string name="touchpad_switch_apps_gesture_guidance">Swipe left or right using four fingers on your touchpad</string> + <!-- Screen title after switch apps gesture was done successfully [CHAR LIMIT=NONE] --> + <string name="touchpad_switch_apps_gesture_success_title">Great job!</string> + <!-- Text shown to the user after they complete switch apps gesture tutorial [CHAR LIMIT=NONE] --> + <string name="touchpad_switch_apps_gesture_success_body">You completed the switch apps gesture.</string> + <!-- Text shown to the user after switch gesture was not done correctly [CHAR LIMIT=NONE] --> + <string name="touchpad_switch_gesture_error_body">Swipe left or right using four fingers on your touchpad to switch apps</string> <!-- KEYBOARD TUTORIAL--> <!-- Action key tutorial title [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt index c43f31beb5bc..a2125c8f0955 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt @@ -39,6 +39,8 @@ import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureRecognizer import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureScreenViewModel import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureRecognizerProvider import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureScreenViewModel +import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureRecognizerProvider +import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureScreenViewModel import dagger.Binds import dagger.Module import dagger.Provides @@ -69,6 +71,14 @@ interface TouchpadTutorialModule { } @Provides + fun switchAppsViewModel( + recognizerProvider: SwitchAppsGestureRecognizerProvider, + adapterFactory: GestureRecognizerAdapter.Factory, + ): SwitchAppsGestureScreenViewModel { + return SwitchAppsGestureScreenViewModel(adapterFactory.create(recognizerProvider)) + } + + @Provides fun recentAppsViewModel( recognizerProvider: RecentAppsGestureRecognizerProvider, adapterFactory: GestureRecognizerAdapter.Factory, diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/SwitchAppsGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/SwitchAppsGestureTutorialScreen.kt new file mode 100644 index 000000000000..3bb0dd779613 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/SwitchAppsGestureTutorialScreen.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.tutorial.ui.composable + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import com.airbnb.lottie.compose.rememberLottieDynamicProperties +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.viewmodel.EasterEggGestureViewModel +import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureScreenViewModel + +@Composable +fun SwitchAppsGestureTutorialScreen( + viewModel: SwitchAppsGestureScreenViewModel, + easterEggGestureViewModel: EasterEggGestureViewModel, + onDoneButtonClicked: () -> Unit, + onBack: () -> Unit, +) { + val screenConfig = + TutorialScreenConfig( + colors = rememberScreenColors(), + strings = + TutorialScreenConfig.Strings( + titleResId = R.string.touchpad_switch_apps_gesture_action_title, + bodyResId = R.string.touchpad_switch_apps_gesture_guidance, + titleSuccessResId = R.string.touchpad_switch_apps_gesture_success_title, + bodySuccessResId = R.string.touchpad_switch_apps_gesture_success_body, + titleErrorResId = R.string.gesture_error_title, + bodyErrorResId = R.string.touchpad_switch_gesture_error_body, + ), + // TODO: replace animation + animations = TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_back_edu), + ) + GestureTutorialScreen( + screenConfig = screenConfig, + tutorialStateFlow = viewModel.tutorialState, + motionEventConsumer = { + easterEggGestureViewModel.accept(it) + viewModel.handleEvent(it) + }, + easterEggTriggeredFlow = easterEggGestureViewModel.easterEggTriggered, + onEasterEggFinished = easterEggGestureViewModel::onEasterEggFinished, + onDoneButtonClicked = onDoneButtonClicked, + onBack = onBack, + ) +} + +@Composable +private fun rememberScreenColors(): TutorialScreenConfig.Colors { + val onTertiary = MaterialTheme.colorScheme.onTertiary + val onTertiaryFixed = LocalAndroidColorScheme.current.onTertiaryFixed + val onTertiaryFixedVariant = LocalAndroidColorScheme.current.onTertiaryFixedVariant + val tertiaryFixedDim = LocalAndroidColorScheme.current.tertiaryFixedDim + val dynamicProperties = + rememberLottieDynamicProperties( + rememberColorFilterProperty(".tertiaryFixedDim", tertiaryFixedDim), + rememberColorFilterProperty(".onTertiaryFixed", onTertiaryFixed), + rememberColorFilterProperty(".onTertiary", onTertiary), + rememberColorFilterProperty(".onTertiaryFixedVariant", onTertiaryFixedVariant), + ) + val screenColors = + remember(dynamicProperties) { + TutorialScreenConfig.Colors( + background = onTertiaryFixed, + title = tertiaryFixedDim, + animationColors = dynamicProperties, + ) + } + return screenColors +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt index c8a58400069e..69b7e892a380 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/TutorialSelectionScreen.kt @@ -61,6 +61,7 @@ fun TutorialSelectionScreen( onBackTutorialClicked: () -> Unit, onHomeTutorialClicked: () -> Unit, onRecentAppsTutorialClicked: () -> Unit, + onSwitchAppsTutorialClicked: () -> Unit, onDoneButtonClicked: () -> Unit, lastSelectedScreen: Screen, ) { @@ -86,6 +87,7 @@ fun TutorialSelectionScreen( onBackTutorialClicked = onBackTutorialClicked, onHomeTutorialClicked = onHomeTutorialClicked, onRecentAppsTutorialClicked = onRecentAppsTutorialClicked, + onSwitchAppsTutorialClicked = onSwitchAppsTutorialClicked, modifier = Modifier.weight(1f).padding(60.dp), lastSelectedScreen, ) @@ -95,6 +97,7 @@ fun TutorialSelectionScreen( onBackTutorialClicked = onBackTutorialClicked, onHomeTutorialClicked = onHomeTutorialClicked, onRecentAppsTutorialClicked = onRecentAppsTutorialClicked, + onSwitchAppsTutorialClicked = onSwitchAppsTutorialClicked, modifier = Modifier.weight(1f).padding(60.dp), lastSelectedScreen, ) @@ -113,6 +116,7 @@ private fun HorizontalSelectionButtons( onBackTutorialClicked: () -> Unit, onHomeTutorialClicked: () -> Unit, onRecentAppsTutorialClicked: () -> Unit, + onSwitchAppsTutorialClicked: () -> Unit, modifier: Modifier = Modifier, lastSelectedScreen: Screen, ) { @@ -121,10 +125,11 @@ private fun HorizontalSelectionButtons( verticalAlignment = Alignment.CenterVertically, modifier = modifier, ) { - ThreeTutorialButtons( + FourTutorialButtons( onBackTutorialClicked, onHomeTutorialClicked, onRecentAppsTutorialClicked, + onSwitchAppsTutorialClicked, modifier = Modifier.weight(1f).fillMaxSize(), lastSelectedScreen, ) @@ -136,6 +141,7 @@ private fun VerticalSelectionButtons( onBackTutorialClicked: () -> Unit, onHomeTutorialClicked: () -> Unit, onRecentAppsTutorialClicked: () -> Unit, + onSwitchAppsTutorialClicked: () -> Unit, modifier: Modifier = Modifier, lastSelectedScreen: Screen, ) { @@ -144,10 +150,11 @@ private fun VerticalSelectionButtons( horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier, ) { - ThreeTutorialButtons( + FourTutorialButtons( onBackTutorialClicked, onHomeTutorialClicked, onRecentAppsTutorialClicked, + onSwitchAppsTutorialClicked, modifier = Modifier.weight(1f).fillMaxSize(), lastSelectedScreen, ) @@ -155,21 +162,24 @@ private fun VerticalSelectionButtons( } @Composable -private fun ThreeTutorialButtons( +private fun FourTutorialButtons( onBackTutorialClicked: () -> Unit, onHomeTutorialClicked: () -> Unit, onRecentAppsTutorialClicked: () -> Unit, + onSwitchAppsTutorialClicked: () -> Unit, modifier: Modifier = Modifier, lastSelectedScreen: Screen, ) { val homeFocusRequester = remember { FocusRequester() } val backFocusRequester = remember { FocusRequester() } val recentAppsFocusRequester = remember { FocusRequester() } + val switchAppsFocusRequester = remember { FocusRequester() } LaunchedEffect(Unit) { when (lastSelectedScreen) { Screen.HOME_GESTURE -> homeFocusRequester.requestFocus() Screen.BACK_GESTURE -> backFocusRequester.requestFocus() Screen.RECENT_APPS_GESTURE -> recentAppsFocusRequester.requestFocus() + Screen.SWITCH_APPS_GESTURE -> switchAppsFocusRequester.requestFocus() else -> {} // No-Op. } } @@ -197,6 +207,14 @@ private fun ThreeTutorialButtons( backgroundColor = MaterialTheme.colorScheme.secondary, modifier = modifier.focusRequester(recentAppsFocusRequester).focusable(), ) + TutorialButton( + text = stringResource(R.string.touchpad_tutorial_switch_apps_gesture_button), + icon = ImageVector.vectorResource(id = R.drawable.touchpad_tutorial_apps_icon), + iconColor = MaterialTheme.colorScheme.primary, + onClick = onSwitchAppsTutorialClicked, + backgroundColor = MaterialTheme.colorScheme.onPrimary, + modifier = modifier.focusRequester(switchAppsFocusRequester).focusable(), + ) } @Composable @@ -227,7 +245,7 @@ private fun TutorialButton( tint = iconColor, ) Spacer(modifier = Modifier.height(16.dp)) - Text(text = text, style = MaterialTheme.typography.headlineLarge) + Text(text = text, style = MaterialTheme.typography.headlineLarge, color = iconColor) } } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt new file mode 100644 index 000000000000..470048bd3b20 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/SwitchAppsGestureRecognizer.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.tutorial.ui.gesture + +import android.view.MotionEvent + +// TODO: javadoc +class SwitchAppsGestureRecognizer(private val gestureDistanceThresholdPx: Int) : GestureRecognizer { + + private val distanceTracker = DistanceTracker() + private var gestureStateChangedCallback: (GestureState) -> Unit = {} + + override fun addGestureStateCallback(callback: (GestureState) -> Unit) { + gestureStateChangedCallback = callback + } + + override fun clearGestureStateCallback() { + gestureStateChangedCallback = {} + } + + // TODO: recognizer logic + override fun accept(event: MotionEvent) { + if (!isMultifingerTouchpadSwipe(event)) return + } +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt index 3264300ed908..0a139125afa2 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt @@ -37,6 +37,7 @@ import com.android.systemui.res.R import com.android.systemui.touchpad.tutorial.ui.composable.BackGestureTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.HomeGestureTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.RecentAppsGestureTutorialScreen +import com.android.systemui.touchpad.tutorial.ui.composable.SwitchAppsGestureTutorialScreen import com.android.systemui.touchpad.tutorial.ui.composable.TutorialSelectionScreen import com.android.systemui.touchpad.tutorial.ui.viewmodel.BackGestureScreenViewModel import com.android.systemui.touchpad.tutorial.ui.viewmodel.EasterEggGestureViewModel @@ -45,7 +46,9 @@ import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureScre import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.BACK_GESTURE import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.HOME_GESTURE import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.RECENT_APPS_GESTURE +import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.SWITCH_APPS_GESTURE import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.TUTORIAL_SELECTION +import com.android.systemui.touchpad.tutorial.ui.viewmodel.SwitchAppsGestureScreenViewModel import com.android.systemui.touchpad.tutorial.ui.viewmodel.TouchpadTutorialViewModel import javax.inject.Inject @@ -58,6 +61,7 @@ constructor( private val backGestureViewModel: BackGestureScreenViewModel, private val homeGestureViewModel: HomeGestureScreenViewModel, private val recentAppsGestureViewModel: RecentAppsGestureScreenViewModel, + private val switchAppsGestureScreenViewModel: SwitchAppsGestureScreenViewModel, private val easterEggGestureViewModel: EasterEggGestureViewModel, ) : ComponentActivity() { @@ -75,6 +79,7 @@ constructor( backGestureViewModel, homeGestureViewModel, recentAppsGestureViewModel, + switchAppsGestureScreenViewModel, easterEggGestureViewModel, closeTutorial = ::finishTutorial, ) @@ -108,6 +113,7 @@ fun TouchpadTutorialScreen( backGestureViewModel: BackGestureScreenViewModel, homeGestureViewModel: HomeGestureScreenViewModel, recentAppsGestureViewModel: RecentAppsGestureScreenViewModel, + switchAppsGestureScreenViewModel: SwitchAppsGestureScreenViewModel, easterEggGestureViewModel: EasterEggGestureViewModel, closeTutorial: () -> Unit, ) { @@ -128,6 +134,10 @@ fun TouchpadTutorialScreen( lastSelectedScreen = RECENT_APPS_GESTURE vm.goTo(RECENT_APPS_GESTURE) }, + onSwitchAppsTutorialClicked = { + lastSelectedScreen = SWITCH_APPS_GESTURE + vm.goTo(SWITCH_APPS_GESTURE) + }, onDoneButtonClicked = closeTutorial, lastSelectedScreen, ) @@ -152,5 +162,12 @@ fun TouchpadTutorialScreen( onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) }, onBack = { vm.goTo(TUTORIAL_SELECTION) }, ) + SWITCH_APPS_GESTURE -> + SwitchAppsGestureTutorialScreen( + switchAppsGestureScreenViewModel, + easterEggGestureViewModel, + onDoneButtonClicked = { vm.goTo(SWITCH_APPS_GESTURE) }, + onBack = { vm.goTo(TUTORIAL_SELECTION) }, + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt new file mode 100644 index 000000000000..b1e163b55377 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureRecognizerProvider.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.tutorial.ui.viewmodel + +import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer +import com.android.systemui.touchpad.tutorial.ui.gesture.SwitchAppsGestureRecognizer +import com.android.systemui.touchpad.tutorial.ui.gesture.VelocityTracker +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +class SwitchAppsGestureRecognizerProvider +@Inject +constructor(val resources: TouchpadGestureResources, val velocityTracker: VelocityTracker) : + GestureRecognizerProvider { + + override val recognizer: Flow<GestureRecognizer> = + resources.distanceThreshold().map { + SwitchAppsGestureRecognizer(gestureDistanceThresholdPx = it) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureScreenViewModel.kt new file mode 100644 index 000000000000..6593db49745d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/SwitchAppsGestureScreenViewModel.kt @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.touchpad.tutorial.ui.viewmodel + +import android.view.MotionEvent +import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState +import com.android.systemui.res.R +import com.android.systemui.touchpad.tutorial.ui.gesture.handleTouchpadMotionEvent +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +class SwitchAppsGestureScreenViewModel(private val gestureRecognizer: GestureRecognizerAdapter) : + TouchpadTutorialScreenViewModel { + + // TODO: replace with correct markers and resource + override val tutorialState: Flow<TutorialActionState> = + gestureRecognizer.gestureState + .map { + it to + TutorialAnimationProperties( + progressStartMarker = "drag with gesture", + progressEndMarker = "onPause", + successAnimation = R.raw.trackpad_recent_apps_success, + ) + } + .mapToTutorialState() + + override fun handleEvent(event: MotionEvent): Boolean { + return gestureRecognizer.handleTouchpadMotionEvent(event) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt index c56dcf3bf062..c6d5e7ad0a71 100644 --- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialViewModel.kt @@ -27,7 +27,7 @@ import kotlinx.coroutines.flow.StateFlow class TouchpadTutorialViewModel( private val gesturesInteractor: TouchpadGesturesInteractor, - private val logger: InputDeviceTutorialLogger + private val logger: InputDeviceTutorialLogger, ) : ViewModel() { private val _screen = MutableStateFlow(Screen.TUTORIAL_SELECTION) @@ -50,7 +50,7 @@ class TouchpadTutorialViewModel( @Inject constructor( private val gesturesInteractor: TouchpadGesturesInteractor, - private val logger: InputDeviceTutorialLogger + private val logger: InputDeviceTutorialLogger, ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") @@ -65,4 +65,5 @@ enum class Screen { BACK_GESTURE, HOME_GESTURE, RECENT_APPS_GESTURE, + SWITCH_APPS_GESTURE, } |