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