1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.quickstep.interaction; 17 18 import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL; 19 20 import android.graphics.PointF; 21 22 import com.android.launcher3.R; 23 import com.android.launcher3.Utilities; 24 import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult; 25 import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult; 26 import com.android.quickstep.util.LottieAnimationColorUtils; 27 28 import java.util.Map; 29 30 /** A {@link TutorialController} for the Home tutorial. */ 31 final class HomeGestureTutorialController extends SwipeUpGestureTutorialController { 32 HomeGestureTutorialController(HomeGestureTutorialFragment fragment, TutorialType tutorialType)33 HomeGestureTutorialController(HomeGestureTutorialFragment fragment, TutorialType tutorialType) { 34 super(fragment, tutorialType); 35 36 // Set the Lottie animation colors specifically for the Home gesture 37 if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) { 38 LottieAnimationColorUtils.updateToArgbColors( 39 mAnimatedGestureDemonstration, 40 Map.of(".onSurfaceHome", fragment.mRootView.mColorOnSurfaceHome, 41 ".surfaceHome", fragment.mRootView.mColorSurfaceHome, 42 ".secondaryHome", fragment.mRootView.mColorSecondaryHome)); 43 44 LottieAnimationColorUtils.updateToArgbColors( 45 mCheckmarkAnimation, 46 Map.of(".checkmark", 47 Utilities.isDarkTheme(mContext) 48 ? fragment.mRootView.mColorOnSurfaceHome 49 : fragment.mRootView.mColorSecondaryHome, 50 ".checkmarkBackground", fragment.mRootView.mColorSurfaceHome)); 51 } 52 } 53 54 @Override getIntroductionTitle()55 public int getIntroductionTitle() { 56 return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get() 57 ? R.string.home_gesture_tutorial_title 58 : R.string.home_gesture_intro_title; 59 } 60 61 @Override getIntroductionSubtitle()62 public int getIntroductionSubtitle() { 63 return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get() 64 ? R.string.home_gesture_tutorial_subtitle 65 : R.string.home_gesture_intro_subtitle; 66 } 67 68 @Override getSpokenIntroductionSubtitle()69 public int getSpokenIntroductionSubtitle() { 70 return R.string.home_gesture_spoken_intro_subtitle; 71 } 72 73 @Override getSuccessFeedbackTitle()74 public int getSuccessFeedbackTitle() { 75 return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get() 76 ? R.string.home_gesture_tutorial_success 77 : R.string.gesture_tutorial_nice; 78 } 79 80 @Override getSuccessFeedbackSubtitle()81 public int getSuccessFeedbackSubtitle() { 82 return mTutorialFragment.isAtFinalStep() 83 ? R.string.home_gesture_feedback_complete_without_follow_up 84 : R.string.home_gesture_feedback_complete_with_follow_up; 85 } 86 87 @Override getTitleTextAppearance()88 public int getTitleTextAppearance() { 89 return R.style.TextAppearance_GestureTutorial_MainTitle_Home; 90 } 91 92 @Override getSuccessTitleTextAppearance()93 public int getSuccessTitleTextAppearance() { 94 return R.style.TextAppearance_GestureTutorial_MainTitle_Success_Home; 95 } 96 97 @Override getDoneButtonTextAppearance()98 public int getDoneButtonTextAppearance() { 99 return R.style.TextAppearance_GestureTutorial_ButtonLabel_Home; 100 } 101 102 @Override getDoneButtonColor()103 public int getDoneButtonColor() { 104 return Utilities.isDarkTheme(mContext) 105 ? mTutorialFragment.mRootView.mColorOnSurfaceHome 106 : mTutorialFragment.mRootView.mColorSecondaryHome; 107 } 108 109 @Override getMockAppTaskLayoutResId()110 protected int getMockAppTaskLayoutResId() { 111 return mTutorialFragment.isLargeScreen() 112 ? R.layout.gesture_tutorial_tablet_mock_webpage 113 : R.layout.gesture_tutorial_mock_webpage; 114 } 115 116 @Override getGestureLottieAnimationId()117 protected int getGestureLottieAnimationId() { 118 return mTutorialFragment.isLargeScreen() 119 ? mTutorialFragment.isFoldable() 120 ? R.raw.home_gesture_tutorial_open_foldable_animation 121 : R.raw.home_gesture_tutorial_tablet_animation 122 : R.raw.home_gesture_tutorial_animation; 123 } 124 125 @Override getFakeTaskViewColor()126 protected int getFakeTaskViewColor() { 127 return isGestureCompleted() ? getFakeLauncherColor() : getExitingAppColor(); 128 } 129 130 @Override getFakeLauncherColor()131 protected int getFakeLauncherColor() { 132 return mTutorialFragment.mRootView.mColorSurfaceContainer; 133 } 134 135 @Override getExitingAppColor()136 protected int getExitingAppColor() { 137 return mTutorialFragment.mRootView.mColorSurfaceHome; 138 } 139 140 @Override getHotseatIconColor()141 protected int getHotseatIconColor() { 142 return getExitingAppColor(); 143 } 144 145 @Override onBackGestureAttempted(BackGestureResult result)146 public void onBackGestureAttempted(BackGestureResult result) { 147 if (isGestureCompleted()) { 148 return; 149 } 150 switch (mTutorialType) { 151 case HOME_NAVIGATION: 152 switch (result) { 153 case BACK_COMPLETED_FROM_LEFT: 154 case BACK_COMPLETED_FROM_RIGHT: 155 case BACK_CANCELLED_FROM_LEFT: 156 case BACK_CANCELLED_FROM_RIGHT: 157 case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE: 158 resetTaskViews(); 159 showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge); 160 break; 161 } 162 break; 163 case HOME_NAVIGATION_COMPLETE: 164 if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT 165 || result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) { 166 mTutorialFragment.close(); 167 } 168 break; 169 } 170 } 171 172 @Override onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity)173 public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) { 174 if (isGestureCompleted()) { 175 return; 176 } 177 switch (mTutorialType) { 178 case HOME_NAVIGATION: 179 switch (result) { 180 case HOME_GESTURE_COMPLETED: { 181 mTutorialFragment.releaseFeedbackAnimation(); 182 animateFakeTaskViewHome(finalVelocity, null); 183 showSuccessFeedback(); 184 break; 185 } 186 case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE: 187 case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE: 188 resetTaskViews(); 189 showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge); 190 break; 191 case OVERVIEW_GESTURE_COMPLETED: 192 fadeOutFakeTaskView(false, () -> { 193 showFeedback(R.string.home_gesture_feedback_overview_detected); 194 showFakeTaskbar(/* animateFromHotseat= */ false); 195 }); 196 break; 197 case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION: 198 case HOME_OR_OVERVIEW_CANCELLED: 199 fadeOutFakeTaskView(false, null); 200 showFeedback(R.string.home_gesture_feedback_wrong_swipe_direction); 201 break; 202 } 203 break; 204 case HOME_NAVIGATION_COMPLETE: 205 if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) { 206 mTutorialFragment.close(); 207 } 208 break; 209 } 210 } 211 212 } 213