1 /* 2 * Copyright (C) 2022 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.launcher3.taskbar.allapps; 17 18 import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_TASKBAR_ALL_APPS; 19 import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT; 20 21 import androidx.annotation.Nullable; 22 23 import com.android.internal.jank.Cuj; 24 import com.android.launcher3.AbstractFloatingView; 25 import com.android.launcher3.allapps.AllAppsTransitionListener; 26 import com.android.launcher3.anim.PendingAnimation; 27 import com.android.launcher3.appprediction.AppsDividerView; 28 import com.android.launcher3.taskbar.NavbarButtonsViewController; 29 import com.android.launcher3.taskbar.TaskbarControllers; 30 import com.android.launcher3.taskbar.TaskbarSharedState; 31 import com.android.launcher3.taskbar.TaskbarStashController; 32 import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext; 33 import com.android.launcher3.taskbar.overlay.TaskbarOverlayController; 34 import com.android.launcher3.util.DisplayController; 35 import com.android.systemui.shared.system.InteractionJankMonitorWrapper; 36 37 import java.util.Optional; 38 39 /** 40 * Handles the {@link TaskbarAllAppsContainerView} behavior and synchronizes its transitions with 41 * taskbar stashing. 42 */ 43 final class TaskbarAllAppsViewController { 44 45 private final TaskbarOverlayContext mContext; 46 private final TaskbarAllAppsSlideInView mSlideInView; 47 private final TaskbarAllAppsContainerView mAppsView; 48 private final TaskbarStashController mTaskbarStashController; 49 private final NavbarButtonsViewController mNavbarButtonsViewController; 50 private final TaskbarOverlayController mOverlayController; 51 private final @Nullable TaskbarSharedState mTaskbarSharedState; 52 private final boolean mShowKeyboard; 53 TaskbarAllAppsViewController( TaskbarOverlayContext context, TaskbarAllAppsSlideInView slideInView, TaskbarControllers taskbarControllers, TaskbarSearchSessionController searchSessionController, boolean showKeyboard)54 TaskbarAllAppsViewController( 55 TaskbarOverlayContext context, 56 TaskbarAllAppsSlideInView slideInView, 57 TaskbarControllers taskbarControllers, 58 TaskbarSearchSessionController searchSessionController, 59 boolean showKeyboard) { 60 61 mContext = context; 62 mSlideInView = slideInView; 63 mAppsView = mSlideInView.getAppsView(); 64 mTaskbarStashController = taskbarControllers.taskbarStashController; 65 mNavbarButtonsViewController = taskbarControllers.navbarButtonsViewController; 66 mOverlayController = taskbarControllers.taskbarOverlayController; 67 mTaskbarSharedState = taskbarControllers.getSharedState(); 68 mShowKeyboard = showKeyboard; 69 70 mSlideInView.init(new TaskbarAllAppsCallbacks(searchSessionController)); 71 setUpAppDivider(); 72 setUpTaskbarStashing(); 73 } 74 75 /** Starts the {@link TaskbarAllAppsSlideInView} enter transition. */ show(boolean animate)76 void show(boolean animate) { 77 mSlideInView.show(animate); 78 } 79 80 /** Closes the {@link TaskbarAllAppsSlideInView}. */ close(boolean animate)81 void close(boolean animate) { 82 mSlideInView.close(animate); 83 } 84 setUpAppDivider()85 private void setUpAppDivider() { 86 mAppsView.getFloatingHeaderView() 87 .findFixedRowByType(AppsDividerView.class) 88 .setShowAllAppsLabel(!ALL_APPS_VISITED_COUNT.hasReachedMax(mContext)); 89 ALL_APPS_VISITED_COUNT.increment(mContext); 90 } 91 setUpTaskbarStashing()92 private void setUpTaskbarStashing() { 93 if (DisplayController.isTransientTaskbar(mContext)) { 94 mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, true); 95 mTaskbarStashController.applyState(); 96 } 97 98 Optional.ofNullable(mTaskbarSharedState).ifPresent(s -> s.allAppsVisible = true); 99 mNavbarButtonsViewController.setSlideInViewVisible(true); 100 mSlideInView.setOnCloseBeginListener(() -> { 101 Optional.ofNullable(mTaskbarSharedState).ifPresent(s -> s.allAppsVisible = false); 102 mNavbarButtonsViewController.setSlideInViewVisible(false); 103 AbstractFloatingView.closeOpenContainer( 104 mContext, AbstractFloatingView.TYPE_ACTION_POPUP); 105 106 if (DisplayController.isTransientTaskbar(mContext)) { 107 mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false); 108 mTaskbarStashController.applyState(); 109 } 110 }); 111 } 112 113 class TaskbarAllAppsCallbacks implements AllAppsTransitionListener { 114 private final TaskbarSearchSessionController mSearchSessionController; 115 TaskbarAllAppsCallbacks(TaskbarSearchSessionController searchSessionController)116 private TaskbarAllAppsCallbacks(TaskbarSearchSessionController searchSessionController) { 117 mSearchSessionController = searchSessionController; 118 } 119 getOpenDuration()120 int getOpenDuration() { 121 return mOverlayController.getOpenDuration(); 122 } 123 getCloseDuration()124 int getCloseDuration() { 125 return mOverlayController.getCloseDuration(); 126 } 127 128 @Override onAllAppsTransitionStart(boolean toAllApps)129 public void onAllAppsTransitionStart(boolean toAllApps) { 130 mSearchSessionController.onAllAppsTransitionStart(toAllApps); 131 } 132 133 @Override onAllAppsTransitionEnd(boolean toAllApps)134 public void onAllAppsTransitionEnd(boolean toAllApps) { 135 mSearchSessionController.onAllAppsTransitionEnd(toAllApps); 136 if (toAllApps 137 && mShowKeyboard 138 && mAppsView.getSearchUiManager().getEditText() != null) { 139 mAppsView.getSearchUiManager().getEditText().requestFocus(); 140 } 141 if (toAllApps) { 142 InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS); 143 } 144 } 145 146 /** Check if search session can handle back. This check doesn't perform any action. */ canHandleSearchBackInvoked()147 boolean canHandleSearchBackInvoked() { 148 return mSearchSessionController.canHandleBackInvoked(); 149 } 150 151 /** Invoked on back press, returning {@code true} if the search session handled it. */ handleSearchBackInvoked()152 boolean handleSearchBackInvoked() { 153 return mSearchSessionController.handleBackInvoked(); 154 } 155 onAllAppsAnimationPending(PendingAnimation animation, boolean toAllApps)156 void onAllAppsAnimationPending(PendingAnimation animation, boolean toAllApps) { 157 mSearchSessionController.onAllAppsAnimationPending(animation, toAllApps, mShowKeyboard); 158 } 159 } 160 } 161