blob: 00e72b1e47ad1d1693ce009f4d5c31b750dc3edb [file] [log] [blame]
Samuel Fufaaed008d2019-12-19 10:57:40 -08001/*
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 */
16package com.android.launcher3.hybridhotseat;
17
Samuel Fufab641ac22020-02-10 17:58:11 -080018import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
19import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.HYBRID_HOTSEAT_CANCELED;
20
Samuel Fufaaed008d2019-12-19 10:57:40 -080021import android.animation.PropertyValuesHolder;
22import android.content.Context;
23import android.content.res.Configuration;
24import android.graphics.Rect;
25import android.util.AttributeSet;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.widget.Button;
29import android.widget.Toast;
30
31import com.android.launcher3.CellLayout;
32import com.android.launcher3.DeviceProfile;
33import com.android.launcher3.Insettable;
34import com.android.launcher3.Launcher;
35import com.android.launcher3.R;
36import com.android.launcher3.WorkspaceItemInfo;
37import com.android.launcher3.anim.Interpolators;
Samuel Fufab641ac22020-02-10 17:58:11 -080038import com.android.launcher3.logging.UserEventDispatcher;
Samuel Fufaaed008d2019-12-19 10:57:40 -080039import com.android.launcher3.uioverrides.PredictedAppIcon;
40import com.android.launcher3.userevent.nano.LauncherLogProto;
41import com.android.launcher3.views.AbstractSlideInView;
42
43import java.util.List;
44
45/**
46 * User education dialog for hybrid hotseat. Allows user to migrate hotseat items to a new page in
47 * the workspace and shows predictions on the whole hotseat
48 */
49public class HotseatEduDialog extends AbstractSlideInView implements Insettable {
50
51 private static final int DEFAULT_CLOSE_DURATION = 200;
52
53 public static boolean shown = false;
54
55 private final Rect mInsets = new Rect();
56 private View mHotseatWrapper;
57 private CellLayout mSampleHotseat;
58
59 public void setHotseatEduController(HotseatEduController hotseatEduController) {
60 mHotseatEduController = hotseatEduController;
61 }
62
63 private HotseatEduController mHotseatEduController;
64
65 public HotseatEduDialog(Context context, AttributeSet attr) {
66 this(context, attr, 0);
67 }
68
69 public HotseatEduDialog(Context context, AttributeSet attrs,
70 int defStyleAttr) {
71 super(context, attrs, defStyleAttr);
72 mContent = this;
73 }
74
75
76 @Override
77 protected void onFinishInflate() {
78 super.onFinishInflate();
79 mHotseatWrapper = findViewById(R.id.hotseat_wrapper);
80 mSampleHotseat = findViewById(R.id.sample_prediction);
81
82 DeviceProfile grid = mLauncher.getDeviceProfile();
83 Rect padding = grid.getHotseatLayoutPadding();
84
85 mSampleHotseat.getLayoutParams().height = grid.cellHeightPx;
86 mSampleHotseat.setGridSize(grid.inv.numHotseatIcons, 1);
87 mSampleHotseat.setPadding(padding.left, 0, padding.right, 0);
88
89 Button turnOnBtn = findViewById(R.id.turn_predictions_on);
90 turnOnBtn.setOnClickListener(this::onMigrate);
91
92 Button learnMoreBtn = findViewById(R.id.no_thanks);
93 learnMoreBtn.setOnClickListener(this::onKeepDefault);
94
95 }
96
97 private void onMigrate(View v) {
98 if (mHotseatEduController == null) return;
99 handleClose(true);
100 mHotseatEduController.migrate();
101 mHotseatEduController.finishOnboarding();
Samuel Fufab641ac22020-02-10 17:58:11 -0800102 logUserAction(true);
Samuel Fufaaed008d2019-12-19 10:57:40 -0800103 Toast.makeText(mLauncher, R.string.hotseat_items_migrated, Toast.LENGTH_LONG).show();
104 }
105
106 private void onKeepDefault(View v) {
107 if (mHotseatEduController == null) return;
108 Toast.makeText(getContext(), R.string.hotseat_no_migration, Toast.LENGTH_LONG).show();
109 mHotseatEduController.finishOnboarding();
Samuel Fufab641ac22020-02-10 17:58:11 -0800110 logUserAction(false);
Samuel Fufaaed008d2019-12-19 10:57:40 -0800111 handleClose(true);
112 }
113
114 @Override
115 public void logActionCommand(int command) {
116 // Since this is on-boarding popup, it is not a user controlled action.
117 }
118
119 @Override
120 public int getLogContainerType() {
121 return LauncherLogProto.ContainerType.TIP;
122 }
123
124 @Override
125 protected boolean isOfType(int type) {
126 return (type & TYPE_ON_BOARD_POPUP) != 0;
127 }
128
129 @Override
130 public void setInsets(Rect insets) {
131 int leftInset = insets.left - mInsets.left;
132 int rightInset = insets.right - mInsets.right;
133 int bottomInset = insets.bottom - mInsets.bottom;
134 mInsets.set(insets);
135 setPadding(leftInset, getPaddingTop(), rightInset, 0);
136 mHotseatWrapper.setPadding(mHotseatWrapper.getPaddingLeft(), getPaddingTop(),
137 mHotseatWrapper.getPaddingRight(), bottomInset);
138 mHotseatWrapper.getLayoutParams().height =
139 mLauncher.getDeviceProfile().hotseatBarSizePx + insets.bottom;
140 }
141
Samuel Fufab641ac22020-02-10 17:58:11 -0800142 private void logUserAction(boolean migrated) {
143 LauncherLogProto.Action action = new LauncherLogProto.Action();
144 LauncherLogProto.Target target = new LauncherLogProto.Target();
145 action.type = LauncherLogProto.Action.Type.TOUCH;
146 action.touch = LauncherLogProto.Action.Touch.TAP;
147 target.containerType = LauncherLogProto.ContainerType.TIP;
148 target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
149 target.controlType = migrated ? LauncherLogProto.ControlType.HYBRID_HOTSEAT_ACCEPTED
150 : HYBRID_HOTSEAT_CANCELED;
151 LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
152 UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
153 }
Samuel Fufaaed008d2019-12-19 10:57:40 -0800154
Samuel Fufab641ac22020-02-10 17:58:11 -0800155 private void logOnBoardingSeen() {
156 LauncherLogProto.Action action = new LauncherLogProto.Action();
157 LauncherLogProto.Target target = new LauncherLogProto.Target();
158 action.type = LauncherLogProto.Action.Type.TIP;
159 target.containerType = LauncherLogProto.ContainerType.TIP;
160 target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
161 LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
162 UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
163 }
Samuel Fufaaed008d2019-12-19 10:57:40 -0800164 private void animateOpen() {
165 if (mIsOpen || mOpenCloseAnimator.isRunning()) {
166 return;
167 }
168 mIsOpen = true;
169 mOpenCloseAnimator.setValues(
170 PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
171 mOpenCloseAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
172 mOpenCloseAnimator.start();
173 }
174
175 @Override
176 protected void handleClose(boolean animate) {
177 handleClose(true, DEFAULT_CLOSE_DURATION);
178 }
179
180 @Override
181 protected void onConfigurationChanged(Configuration newConfig) {
182 super.onConfigurationChanged(newConfig);
183 handleClose(false);
184 }
185
186 /**
187 * Opens User education dialog with a list of suggested apps
188 */
189 public void show(List<WorkspaceItemInfo> predictions) {
190 if (getParent() != null
191 || predictions.size() < mLauncher.getDeviceProfile().inv.numHotseatIcons) {
192 return;
193 }
194 mLauncher.getDragLayer().addView(this);
Samuel Fufab641ac22020-02-10 17:58:11 -0800195 logOnBoardingSeen();
Samuel Fufaaed008d2019-12-19 10:57:40 -0800196 animateOpen();
197 for (int i = 0; i < mLauncher.getDeviceProfile().inv.numHotseatIcons; i++) {
198 WorkspaceItemInfo info = predictions.get(i);
199 PredictedAppIcon icon = PredictedAppIcon.createIcon(mSampleHotseat, info);
200 icon.setEnabled(false);
201 icon.verifyHighRes();
202 CellLayout.LayoutParams lp = new CellLayout.LayoutParams(i, 0, 1, 1);
203 mSampleHotseat.addViewToCellLayout(icon, i, info.getViewId(), lp, true);
204 }
205 }
206
207 /**
208 * Factory method for HotseatPredictionUserEdu dialog
209 */
210 public static HotseatEduDialog getDialog(Launcher launcher) {
211 LayoutInflater layoutInflater = LayoutInflater.from(launcher);
212 return (HotseatEduDialog) layoutInflater.inflate(
213 R.layout.predicted_hotseat_edu, launcher.getDragLayer(),
214 false);
215
216 }
217}