• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.launcher3.hybridhotseat;
17 
18 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_ACCEPT;
19 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_DENY;
20 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_EDU_SEEN;
21 
22 import android.content.Context;
23 import android.content.res.Configuration;
24 import android.graphics.Rect;
25 import android.util.AttributeSet;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.widget.Button;
29 import android.widget.LinearLayout;
30 import android.widget.TextView;
31 
32 import com.android.launcher3.AbstractFloatingView;
33 import com.android.launcher3.CellLayout;
34 import com.android.launcher3.DeviceProfile;
35 import com.android.launcher3.Insettable;
36 import com.android.launcher3.InvariantDeviceProfile;
37 import com.android.launcher3.Launcher;
38 import com.android.launcher3.R;
39 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
40 import com.android.launcher3.model.data.WorkspaceItemInfo;
41 import com.android.launcher3.uioverrides.PredictedAppIcon;
42 import com.android.launcher3.views.AbstractSlideInView;
43 
44 import java.util.List;
45 
46 /**
47  * User education dialog for hybrid hotseat. Allows user to migrate hotseat items to a new page in
48  * the workspace and shows predictions on the whole hotseat
49  */
50 public class HotseatEduDialog extends AbstractSlideInView<Launcher> implements Insettable {
51 
52     private static final int DEFAULT_CLOSE_DURATION = 200;
53     protected static final int FINAL_SCRIM_BG_COLOR = 0x88000000;
54 
55     // we use this value to keep track of migration logs as we experiment with different migrations
56     private static final int MIGRATION_EXPERIMENT_IDENTIFIER = 1;
57 
58     private final Rect mInsets = new Rect();
59     private View mHotseatWrapper;
60     private CellLayout mSampleHotseat;
61     private Button mDismissBtn;
62 
setHotseatEduController(HotseatEduController hotseatEduController)63     public void setHotseatEduController(HotseatEduController hotseatEduController) {
64         mHotseatEduController = hotseatEduController;
65     }
66 
67     private HotseatEduController mHotseatEduController;
68 
HotseatEduDialog(Context context, AttributeSet attr)69     public HotseatEduDialog(Context context, AttributeSet attr) {
70         this(context, attr, 0);
71     }
72 
HotseatEduDialog(Context context, AttributeSet attrs, int defStyleAttr)73     public HotseatEduDialog(Context context, AttributeSet attrs,
74             int defStyleAttr) {
75         super(context, attrs, defStyleAttr);
76         mContent = this;
77     }
78 
79     @Override
onLayout(boolean changed, int l, int t, int r, int b)80     protected void onLayout(boolean changed, int l, int t, int r, int b) {
81         super.onLayout(changed, l, t, r, b);
82         setTranslationShift(TRANSLATION_SHIFT_CLOSED);
83     }
84 
85     @Override
onFinishInflate()86     protected void onFinishInflate() {
87         super.onFinishInflate();
88         mHotseatWrapper = findViewById(R.id.hotseat_wrapper);
89         mSampleHotseat = findViewById(R.id.sample_prediction);
90 
91         Context context = getContext();
92         DeviceProfile grid = mActivityContext.getDeviceProfile();
93         Rect padding = grid.getHotseatLayoutPadding(context);
94 
95         mSampleHotseat.getLayoutParams().height = grid.cellHeightPx;
96         mSampleHotseat.setGridSize(grid.numShownHotseatIcons, 1);
97         mSampleHotseat.setPadding(padding.left, 0, padding.right, 0);
98 
99         Button turnOnBtn = findViewById(R.id.turn_predictions_on);
100         turnOnBtn.setOnClickListener(this::onAccept);
101 
102         mDismissBtn = findViewById(R.id.no_thanks);
103         mDismissBtn.setOnClickListener(this::onDismiss);
104 
105         LinearLayout buttonContainer = findViewById(R.id.button_container);
106         int adjustedMarginEnd = grid.hotseatBarEndOffset - buttonContainer.getPaddingEnd();
107         if (InvariantDeviceProfile.INSTANCE.get(context)
108                 .getDeviceProfile(context).isTaskbarPresent && adjustedMarginEnd > 0) {
109             ((LinearLayout.LayoutParams) buttonContainer.getLayoutParams()).setMarginEnd(
110                     adjustedMarginEnd);
111         }
112     }
113 
onAccept(View v)114     private void onAccept(View v) {
115         mHotseatEduController.migrate();
116         handleClose(true);
117 
118         mHotseatEduController.moveHotseatItems();
119         mHotseatEduController.finishOnboarding();
120         mActivityContext.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_ACCEPT);
121     }
122 
onDismiss(View v)123     private void onDismiss(View v) {
124         mHotseatEduController.showDimissTip();
125         mHotseatEduController.finishOnboarding();
126         mActivityContext.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_DENY);
127         handleClose(true);
128     }
129 
130     @Override
isOfType(int type)131     protected boolean isOfType(int type) {
132         return (type & TYPE_ON_BOARD_POPUP) != 0;
133     }
134 
135     @Override
setInsets(Rect insets)136     public void setInsets(Rect insets) {
137         int leftInset = insets.left - mInsets.left;
138         int rightInset = insets.right - mInsets.right;
139         int bottomInset = insets.bottom - mInsets.bottom;
140         mInsets.set(insets);
141         if (mActivityContext.getOrientation() == Configuration.ORIENTATION_PORTRAIT) {
142             setPadding(leftInset, getPaddingTop(), rightInset, 0);
143             mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
144                     mHotseatWrapper.getPaddingRight(), bottomInset);
145             mHotseatWrapper.getLayoutParams().height =
146                     mActivityContext.getDeviceProfile().hotseatBarSizePx + insets.bottom;
147 
148         } else {
149             setPadding(0, getPaddingTop(), 0, 0);
150             mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
151                     mHotseatWrapper.getPaddingRight(),
152                     (int) getResources().getDimension(R.dimen.bottom_sheet_edu_padding));
153             ((TextView) findViewById(R.id.hotseat_edu_heading)).setText(
154                     R.string.hotseat_edu_title_migrate_landscape);
155             ((TextView) findViewById(R.id.hotseat_edu_content)).setText(
156                     R.string.hotseat_edu_message_migrate_landscape);
157         }
158     }
159 
animateOpen()160     private void animateOpen() {
161         if (mIsOpen || mOpenCloseAnimation.getAnimationPlayer().isRunning()) {
162             return;
163         }
164         mIsOpen = true;
165         setUpDefaultOpenAnimation().start();
166     }
167 
168     @Override
handleClose(boolean animate)169     protected void handleClose(boolean animate) {
170         handleClose(true, DEFAULT_CLOSE_DURATION);
171     }
172 
173     @Override
onConfigurationChanged(Configuration newConfig)174     protected void onConfigurationChanged(Configuration newConfig) {
175         super.onConfigurationChanged(newConfig);
176         handleClose(false);
177     }
178 
179     @Override
getScrimColor(Context context)180     protected int getScrimColor(Context context) {
181         return FINAL_SCRIM_BG_COLOR;
182     }
183 
populatePreview(List<WorkspaceItemInfo> predictions)184     private void populatePreview(List<WorkspaceItemInfo> predictions) {
185         for (int i = 0; i < mActivityContext.getDeviceProfile().numShownHotseatIcons; i++) {
186             WorkspaceItemInfo info = predictions.get(i);
187             PredictedAppIcon icon = PredictedAppIcon.createIcon(mSampleHotseat, info);
188             icon.setEnabled(false);
189             icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
190             icon.verifyHighRes();
191             CellLayoutLayoutParams lp = new CellLayoutLayoutParams(i, 0, 1, 1);
192             mSampleHotseat.addViewToCellLayout(icon, i, info.getViewId(), lp, true);
193         }
194     }
195 
196     /**
197      * Opens User education dialog with a list of suggested apps
198      */
show(List<WorkspaceItemInfo> predictions)199     public void show(List<WorkspaceItemInfo> predictions) {
200         if (getParent() != null
201                 || predictions.size() < mActivityContext.getDeviceProfile().numShownHotseatIcons
202                 || mHotseatEduController == null) {
203             return;
204         }
205         AbstractFloatingView.closeAllOpenViews(mActivityContext);
206         attachToContainer();
207         animateOpen();
208         populatePreview(predictions);
209         mActivityContext.getStatsLogManager().logger().log(LAUNCHER_HOTSEAT_EDU_SEEN);
210     }
211 
212     /**
213      * Factory method for HotseatPredictionUserEdu dialog
214      */
getDialog(Launcher launcher)215     public static HotseatEduDialog getDialog(Launcher launcher) {
216         LayoutInflater layoutInflater = LayoutInflater.from(launcher);
217         return (HotseatEduDialog) layoutInflater.inflate(
218                 R.layout.predicted_hotseat_edu, launcher.getDragLayer(),
219                 false);
220 
221     }
222 }
223