1 package com.android.systemui.qs;
2 
3 import static com.android.systemui.Prefs.Key.QS_TILE_SPECS_REVEALED;
4 
5 import android.content.Context;
6 import android.os.Handler;
7 import android.util.ArraySet;
8 
9 import com.android.systemui.Prefs;
10 import com.android.systemui.plugins.qs.QSTile;
11 import com.android.systemui.qs.customize.QSCustomizerController;
12 import com.android.systemui.qs.dagger.QSScope;
13 
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.Set;
17 
18 import javax.inject.Inject;
19 
20 /**
21  * Plays a animation to reveal newly added QS tiles.
22  *
23  * The aniumation is played when the user fully opens Quick Settings, and is only shown for
24  * <li> tiles added automatically (not through user customization)
25  * <li> tiles not have been revealed before (memoized via {@code QS_TILE_SPECS_REVEALED}
26  * preference)
27  */
28 public class QSTileRevealController {
29     private static final long QS_REVEAL_TILES_DELAY = 500L;
30 
31     private final Context mContext;
32     private final QSPanelController mQSPanelController;
33     private final PagedTileLayout mPagedTileLayout;
34     private final QSCustomizerController mQsCustomizerController;
35     private final ArraySet<String> mTilesToReveal = new ArraySet<>();
36     private final Handler mHandler = new Handler();
37 
38     private final Runnable mRevealQsTiles = new Runnable() {
39         @Override
40         public void run() {
41             mPagedTileLayout.startTileReveal(mTilesToReveal, () -> {
42                 if (mQSPanelController.isExpanded()) {
43                     addTileSpecsToRevealed(mTilesToReveal);
44                     mTilesToReveal.clear();
45                 }
46             });
47         }
48     };
49 
QSTileRevealController(Context context, QSPanelController qsPanelController, PagedTileLayout pagedTileLayout, QSCustomizerController qsCustomizerController)50     QSTileRevealController(Context context, QSPanelController qsPanelController,
51             PagedTileLayout pagedTileLayout, QSCustomizerController qsCustomizerController) {
52         mContext = context;
53         mQSPanelController = qsPanelController;
54         mPagedTileLayout = pagedTileLayout;
55         mQsCustomizerController = qsCustomizerController;
56     }
57 
setExpansion(float expansion)58     public void setExpansion(float expansion) {
59         if (expansion == 1f) {
60             mHandler.postDelayed(mRevealQsTiles, QS_REVEAL_TILES_DELAY);
61         } else {
62             mHandler.removeCallbacks(mRevealQsTiles);
63         }
64     }
65 
updateRevealedTiles(Collection<QSTile> tiles)66     public void updateRevealedTiles(Collection<QSTile> tiles) {
67         ArraySet<String> tileSpecs = new ArraySet<>();
68         for (QSTile tile : tiles) {
69             tileSpecs.add(tile.getTileSpec());
70         }
71 
72         final Set<String> revealedTiles = Prefs.getStringSet(
73                 mContext, QS_TILE_SPECS_REVEALED, Collections.EMPTY_SET);
74         if (revealedTiles.isEmpty() || mQsCustomizerController.isCustomizing()) {
75             // Do not reveal QS tiles the user has upon first load or those that they directly
76             // added through customization.
77             addTileSpecsToRevealed(tileSpecs);
78         } else {
79             // Animate all tiles that the user has not directly added themselves.
80             tileSpecs.removeAll(revealedTiles);
81             mTilesToReveal.addAll(tileSpecs);
82         }
83     }
84 
addTileSpecsToRevealed(ArraySet<String> specs)85     private void addTileSpecsToRevealed(ArraySet<String> specs) {
86         final ArraySet<String> revealedTiles = new ArraySet<>(
87                 Prefs.getStringSet(mContext, QS_TILE_SPECS_REVEALED, Collections.EMPTY_SET));
88         revealedTiles.addAll(specs);
89         Prefs.putStringSet(mContext, QS_TILE_SPECS_REVEALED, revealedTiles);
90     }
91 
92     /** TODO(b/168904199): Remove this once QSPanel has its rejection removed. */
93     @QSScope
94     static class Factory {
95         private final Context mContext;
96         private final QSCustomizerController mQsCustomizerController;
97 
98         @Inject
Factory(Context context, QSCustomizerController qsCustomizerController)99         Factory(Context context, QSCustomizerController qsCustomizerController) {
100             mContext = context;
101             mQsCustomizerController = qsCustomizerController;
102         }
103 
create(QSPanelController qsPanelController, PagedTileLayout pagedTileLayout)104         QSTileRevealController create(QSPanelController qsPanelController,
105                 PagedTileLayout pagedTileLayout) {
106             return new QSTileRevealController(mContext, qsPanelController, pagedTileLayout,
107                     mQsCustomizerController);
108         }
109     }
110 }
111