diff options
6 files changed, 136 insertions, 65 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt index 639737b37efd..76434ee54627 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModelTest.kt @@ -27,9 +27,11 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE @@ -66,8 +68,8 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { private val sysUiState = kosmos.sysUiState private val touchpadRepo = PrettyFakeTouchpadRepository() private val keyboardRepo = kosmos.keyboardRepository - private var startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD - private val viewModel by lazy { createViewModel(startingPeripheral) } + private var tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD + private val viewModel by lazy { createViewModel(tutorialScope) } // createUnsafe so its methods don't have to be called on Main thread private val lifecycle = LifecycleRegistry.createUnsafe(mock(LifecycleOwner::class.java)) @@ -75,7 +77,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @get:Rule val mainDispatcherRule = MainDispatcherRule(kosmos.testDispatcher) private fun createViewModel( - startingPeripheral: String = INTENT_TUTORIAL_TYPE_TOUCHPAD, + scope: String = INTENT_TUTORIAL_SCOPE_TOUCHPAD, hasTouchpadTutorialScreens: Boolean = true, ): KeyboardTouchpadTutorialViewModel { val viewModel = @@ -84,7 +86,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { KeyboardTouchpadConnectionInteractor(keyboardRepo, touchpadRepo), hasTouchpadTutorialScreens, mock<InputDeviceTutorialLogger>(), - SavedStateHandle(mapOf(INTENT_TUTORIAL_TYPE_KEY to startingPeripheral)) + SavedStateHandle(mapOf(INTENT_TUTORIAL_SCOPE_KEY to scope)), ) lifecycle.addObserver(viewModel) return viewModel @@ -169,7 +171,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun screensOrder_whenGoingBackAndOnlyKeyboardConnected() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD + tutorialScope = INTENT_TUTORIAL_SCOPE_KEYBOARD val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) peripheralsState(keyboardConnected = true, touchpadConnected = false) @@ -185,7 +187,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun screensOrder_whenTouchpadConnected() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) @@ -193,22 +195,47 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { goToNextScreen() goToNextScreen() - goToNextScreen() assertThat(screens).containsExactly(BACK_GESTURE, HOME_GESTURE).inOrder() assertThat(closeActivity).isTrue() } @Test - fun screensOrder_whenKeyboardConnected() = + fun screensOrder_withBackGestureScope() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_KEYBOARD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(touchpadConnected = true) - peripheralsState(keyboardConnected = true) + goToNextScreen() + + assertThat(screens).containsExactly(BACK_GESTURE).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_withHomeGestureScope() = + testScope.runTest { + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(touchpadConnected = true) goToNextScreen() + + assertThat(screens).containsExactly(HOME_GESTURE).inOrder() + assertThat(closeActivity).isTrue() + } + + @Test + fun screensOrder_withKeyboardScope() = + testScope.runTest { + tutorialScope = INTENT_TUTORIAL_SCOPE_KEYBOARD + val screens by collectValues(viewModel.screen) + val closeActivity by collectLastValue(viewModel.closeActivity) + peripheralsState(keyboardConnected = true) + goToNextScreen() assertThat(screens).containsExactly(ACTION_KEY).inOrder() @@ -218,7 +245,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun touchpadGesturesDisabled_onlyDuringTouchpadTutorial() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD collectValues(viewModel.screen) // just to initialize viewModel peripheralsState(keyboardConnected = true, touchpadConnected = true) @@ -234,8 +261,8 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { testScope.runTest { val viewModel = createViewModel( - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD, - hasTouchpadTutorialScreens = false + scope = INTENT_TUTORIAL_SCOPE_TOUCHPAD, + hasTouchpadTutorialScreens = false, ) val screens by collectValues(viewModel.screen) val closeActivity by collectLastValue(viewModel.closeActivity) @@ -248,7 +275,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun touchpadGesturesDisabled_whenTutorialGoesToForeground() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD collectValues(viewModel.screen) // just to initialize viewModel peripheralsState(touchpadConnected = true) @@ -260,7 +287,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { @Test fun touchpadGesturesNotDisabled_whenTutorialGoesToBackground() = testScope.runTest { - startingPeripheral = INTENT_TUTORIAL_TYPE_TOUCHPAD + tutorialScope = INTENT_TUTORIAL_SCOPE_TOUCHPAD collectValues(viewModel.screen) peripheralsState(touchpadConnected = true) @@ -288,7 +315,7 @@ class KeyboardTouchpadTutorialViewModelTest : SysuiTestCase() { private fun TestScope.peripheralsState( keyboardConnected: Boolean = false, - touchpadConnected: Boolean = false + touchpadConnected: Boolean = false, ) { keyboardRepo.setIsAnyKeyboardConnected(keyboardConnected) touchpadRepo.setIsAnyTouchpadConnected(touchpadConnected) diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt index 092a25aa1cad..7bd09b915d1a 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.os.Build import android.os.UserHandle import com.android.systemui.CoreStartable import com.android.systemui.broadcast.BroadcastDispatcher @@ -52,13 +53,13 @@ constructor( receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - applicationContext.startActivityAsUser( - Intent( - applicationContext, - KeyboardTouchpadTutorialActivity::class.java - ), - UserHandle.SYSTEM - ) + val activityIntent = + Intent(applicationContext, KeyboardTouchpadTutorialActivity::class.java) + if (Build.IS_DEBUGGABLE) { + // helpful for testing different cases but pointless for public builds + intent.extras?.let { activityIntent.putExtras(it) } + } + applicationContext.startActivityAsUser(activityIntent, UserHandle.SYSTEM) } }, filter = IntentFilter("com.android.systemui.action.KEYBOARD_TOUCHPAD_TUTORIAL"), diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt index 144c5ead1bb8..ae6cbbc4315e 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialMetricsLogger.kt @@ -18,8 +18,8 @@ package com.android.systemui.inputdevice.tutorial import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_CONTEXTUAL_EDU import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD import com.android.systemui.shared.system.SysUiStatsLog import javax.inject.Inject @@ -37,9 +37,9 @@ class KeyboardTouchpadTutorialMetricsLogger @Inject constructor() { val tutorialType = when (tutorialTypeExtra) { - INTENT_TUTORIAL_TYPE_KEYBOARD -> + INTENT_TUTORIAL_SCOPE_KEYBOARD -> SysUiStatsLog.PERIPHERAL_TUTORIAL_LAUNCHED__TUTORIAL_TYPE__KEYBOARD - INTENT_TUTORIAL_TYPE_TOUCHPAD -> + INTENT_TUTORIAL_SCOPE_TOUCHPAD -> SysUiStatsLog.PERIPHERAL_TUTORIAL_LAUNCHED__TUTORIAL_TYPE__TOUCHPAD else -> SysUiStatsLog.PERIPHERAL_TUTORIAL_LAUNCHED__TUTORIAL_TYPE__BOTH } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt index 9dae64921d26..3cba70e39e66 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt @@ -34,10 +34,10 @@ import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSched import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_KEY import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_BOTH -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_ALL +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import javax.inject.Inject @@ -108,7 +108,7 @@ constructor( private fun createPendingIntent(tutorialType: String): PendingIntent { val intent = Intent(context, KeyboardTouchpadTutorialActivity::class.java).apply { - putExtra(INTENT_TUTORIAL_TYPE_KEY, tutorialType) + putExtra(INTENT_TUTORIAL_SCOPE_KEY, tutorialType) putExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY, INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER) flags = Intent.FLAG_ACTIVITY_NEW_TASK } @@ -128,13 +128,13 @@ constructor( NotificationInfo( context.getString(R.string.launch_keyboard_tutorial_notification_title), context.getString(R.string.launch_keyboard_tutorial_notification_content), - INTENT_TUTORIAL_TYPE_KEYBOARD, + INTENT_TUTORIAL_SCOPE_KEYBOARD, ) TutorialType.TOUCHPAD -> NotificationInfo( context.getString(R.string.launch_touchpad_tutorial_notification_title), context.getString(R.string.launch_touchpad_tutorial_notification_content), - INTENT_TUTORIAL_TYPE_TOUCHPAD, + INTENT_TUTORIAL_SCOPE_TOUCHPAD, ) TutorialType.BOTH -> NotificationInfo( @@ -144,7 +144,7 @@ constructor( context.getString( R.string.launch_keyboard_touchpad_tutorial_notification_content ), - INTENT_TUTORIAL_TYPE_BOTH, + INTENT_TUTORIAL_SCOPE_ALL, ) TutorialType.NONE -> null } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt index fee08b31bd93..67b307fb7a36 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt @@ -56,10 +56,13 @@ constructor( ) : ComponentActivity() { companion object { - const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type" - const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad" - const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard" - const val INTENT_TUTORIAL_TYPE_BOTH = "both" + const val INTENT_TUTORIAL_SCOPE_KEY = "tutorial_scope" + const val INTENT_TUTORIAL_SCOPE_TOUCHPAD = "touchpad" + const val INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK = "touchpad_back" + const val INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME = "touchpad_home" + const val INTENT_TUTORIAL_SCOPE_KEYBOARD = "keyboard" + const val INTENT_TUTORIAL_SCOPE_ALL = "all" + const val INTENT_TUTORIAL_ENTRY_POINT_KEY = "entry_point" const val INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER = "scheduler" const val INTENT_TUTORIAL_ENTRY_POINT_CONTEXTUAL_EDU = "contextual_edu" @@ -94,7 +97,7 @@ constructor( if (savedInstanceState == null) { metricsLogger.logPeripheralTutorialLaunched( intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY), - intent.getStringExtra(INTENT_TUTORIAL_TYPE_KEY), + intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY), ) logger.logOpenTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL) } diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt index 896bdc068154..eeb4b697a5fc 100644 --- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/viewmodel/KeyboardTouchpadTutorialViewModel.kt @@ -22,15 +22,21 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger import com.android.systemui.inputdevice.tutorial.domain.interactor.ConnectionState import com.android.systemui.inputdevice.tutorial.domain.interactor.KeyboardTouchpadConnectionInteractor -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY -import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_ALL +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEY +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_KEYBOARD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK +import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.KEYBOARD import com.android.systemui.inputdevice.tutorial.ui.viewmodel.RequiredHardware.TOUCHPAD import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE +import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -42,27 +48,23 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.runningFold -import com.android.app.tracing.coroutines.launchTraced as launch class KeyboardTouchpadTutorialViewModel( private val gesturesInteractor: Optional<TouchpadGesturesInteractor>, private val keyboardTouchpadConnectionInteractor: KeyboardTouchpadConnectionInteractor, private val hasTouchpadTutorialScreens: Boolean, private val logger: InputDeviceTutorialLogger, - handle: SavedStateHandle + handle: SavedStateHandle, ) : ViewModel(), DefaultLifecycleObserver { - private fun startingScreen(handle: SavedStateHandle): Screen { - val tutorialType: String? = handle[INTENT_TUTORIAL_TYPE_KEY] - return if (tutorialType == INTENT_TUTORIAL_TYPE_KEYBOARD) ACTION_KEY else BACK_GESTURE - } - private val _screen = MutableStateFlow(startingScreen(handle)) val screen: Flow<Screen> = _screen.filter { it.canBeShown() } private val _closeActivity: MutableStateFlow<Boolean> = MutableStateFlow(false) val closeActivity: StateFlow<Boolean> = _closeActivity + private val screenSequence: ScreenSequence = chooseScreenSequence(handle) + private val screensBackStack = ArrayDeque(listOf(_screen.value)) private var connectionState: ConnectionState = @@ -105,6 +107,33 @@ class KeyboardTouchpadTutorialViewModel( } } + private fun startingScreen(handle: SavedStateHandle): Screen { + val scope: String? = handle[INTENT_TUTORIAL_SCOPE_KEY] + return when (scope) { + INTENT_TUTORIAL_SCOPE_KEYBOARD -> ACTION_KEY + INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME -> HOME_GESTURE + INTENT_TUTORIAL_SCOPE_TOUCHPAD, + INTENT_TUTORIAL_SCOPE_ALL, + INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK -> BACK_GESTURE + else -> { + logger.w("Intent didn't specify tutorial scope, starting with default") + BACK_GESTURE + } + } + } + + private fun chooseScreenSequence(handle: SavedStateHandle): ScreenSequence { + val scope: String? = handle[INTENT_TUTORIAL_SCOPE_KEY] + return if ( + scope == INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME || + scope == INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK + ) { + SingleScreenOnly + } else { + AllSupportedScreens + } + } + override fun onCleared() { // this shouldn't be needed as onTutorialInvisible should already clear device state but // it'd be really bad if we'd block gestures/shortcuts after leaving tutorial so just to be @@ -121,13 +150,13 @@ class KeyboardTouchpadTutorialViewModel( } fun onDoneButtonClicked() { - var nextScreen = _screen.value.next() + var nextScreen = screenSequence.nextScreen(_screen.value) while (nextScreen != null) { if (requiredHardwarePresent(nextScreen)) { break } logger.logNextScreenMissingHardware(nextScreen) - nextScreen = nextScreen.next() + nextScreen = screenSequence.nextScreen(nextScreen) } if (nextScreen == null) { logger.d("Final screen reached, closing tutorial") @@ -192,33 +221,44 @@ class KeyboardTouchpadTutorialViewModel( override fun <T : ViewModel> create( key: String, modelClass: Class<T>, - handle: SavedStateHandle + handle: SavedStateHandle, ): T = KeyboardTouchpadTutorialViewModel( gesturesInteractor, keyboardTouchpadConnected, hasTouchpadTutorialScreens, logger, - handle + handle, ) as T } + + private interface ScreenSequence { + fun nextScreen(current: Screen): Screen? + } + + private object AllSupportedScreens : ScreenSequence { + override fun nextScreen(current: Screen): Screen? { + return when (current) { + BACK_GESTURE -> HOME_GESTURE + HOME_GESTURE -> ACTION_KEY + ACTION_KEY -> null + } + } + } + + private object SingleScreenOnly : ScreenSequence { + override fun nextScreen(current: Screen): Screen? = null + } } enum class RequiredHardware { TOUCHPAD, - KEYBOARD + KEYBOARD, } enum class Screen(val requiredHardware: RequiredHardware) { BACK_GESTURE(requiredHardware = TOUCHPAD), HOME_GESTURE(requiredHardware = TOUCHPAD), - ACTION_KEY(requiredHardware = KEYBOARD); - - fun next(): Screen? = - when (this) { - BACK_GESTURE -> HOME_GESTURE - HOME_GESTURE -> ACTION_KEY - ACTION_KEY -> null - } + ACTION_KEY(requiredHardware = KEYBOARD), } |