-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
MostVisitedTilesCoordinator.java
177 lines (156 loc) · 8.54 KB
/
MostVisitedTilesCoordinator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.suggestions.tile;
import android.app.Activity;
import android.content.res.Configuration;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.feed.FeedFeatures;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
import org.chromium.chrome.browser.native_page.ContextMenuManager;
import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.suggestions.SuggestionsConfig;
import org.chromium.chrome.browser.suggestions.SuggestionsDependencyFactory;
import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
import org.chromium.chrome.browser.ui.native_page.TouchEnabledDelegate;
import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
/**
* Coordinator for displaying a list of {@link SuggestionsTileView} in a {@link ViewGroup}.
*/
public class MostVisitedTilesCoordinator implements ConfigurationChangedObserver {
private static final int TITLE_LINES = 1;
public static final String CONTEXT_MENU_USER_ACTION_PREFIX = "Suggestions";
/**
* The maximum number of tiles to try and fit in a row. On smaller screens, there may not be
* enough space to fit all of them.
*/
@VisibleForTesting
public static final int MAX_TILE_COLUMNS_FOR_GRID = 4;
private final Activity mActivity;
private final ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
private final MostVisitedTilesMediator mMediator;
private final WindowAndroid mWindowAndroid;
private final UiConfig mUiConfig;
private final PropertyModelChangeProcessor mModelChangeProcessor;
private TileRenderer mRenderer;
private ContextMenuManager mContextMenuManager;
private OfflinePageBridge mOfflinePageBridge;
/**
* @param activity The app activity.
* @param activityLifecycleDispatcher Dispatcher for activity lifecycle events,
* e.g.configuration changes. We need this to adjust the
* paddings and margins of the tile views.
* @param mvTilesContainerLayout The container view of most visited tiles layout.
* @param windowAndroid The current {@link WindowAndroid}
* @param shouldShowSkeletonUIPreNative Whether to show the background icon for pre-native
* surface.
* @param isScrollableMVTEnabled Whether scrollable MVT is enabled. If true {@link
* MostVisitedTilesCarouselLayout} is used; if false {@link
* MostVisitedTilesGridLayout} is used.
* @param maxRows The maximum number of rows to display. This will only be used for {@link
* MostVisitedTilesGridLayout}.
* @param snapshotTileGridChangedRunnable The runnable called when the snapshot tile grid is
* changed.
* @param tileCountChangedRunnable The runnable called when the tile count is changed.
*/
public MostVisitedTilesCoordinator(Activity activity,
ActivityLifecycleDispatcher activityLifecycleDispatcher, View mvTilesContainerLayout,
WindowAndroid windowAndroid, boolean shouldShowSkeletonUIPreNative,
boolean isScrollableMVTEnabled, int maxRows,
@Nullable Runnable snapshotTileGridChangedRunnable,
@Nullable Runnable tileCountChangedRunnable) {
mActivity = activity;
mActivityLifecycleDispatcher = activityLifecycleDispatcher;
mWindowAndroid = windowAndroid;
((ViewStub) mvTilesContainerLayout.findViewById(
isScrollableMVTEnabled ? R.id.mv_tiles_carousel_stub : R.id.mv_tiles_grid_stub))
.inflate();
ViewGroup tilesLayout = mvTilesContainerLayout.findViewById(R.id.mv_tiles_layout);
if (!isScrollableMVTEnabled) {
assert maxRows != Integer.MAX_VALUE;
((MostVisitedTilesGridLayout) tilesLayout).setMaxColumns(MAX_TILE_COLUMNS_FOR_GRID);
((MostVisitedTilesGridLayout) tilesLayout).setMaxRows(maxRows);
}
mUiConfig = new UiConfig(tilesLayout);
PropertyModel propertyModel = new PropertyModel(MostVisitedTilesProperties.ALL_KEYS);
mModelChangeProcessor = PropertyModelChangeProcessor.create(propertyModel,
new MostVisitedTilesViewBinder.ViewHolder(mvTilesContainerLayout, tilesLayout),
MostVisitedTilesViewBinder::bind);
mRenderer = new TileRenderer(
mActivity, SuggestionsConfig.getTileStyle(mUiConfig), TITLE_LINES, null);
boolean isTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity);
mMediator = new MostVisitedTilesMediator(activity.getResources(), mUiConfig, tilesLayout,
mvTilesContainerLayout.findViewById(R.id.tile_grid_placeholder_stub), mRenderer,
propertyModel, shouldShowSkeletonUIPreNative, isScrollableMVTEnabled, isTablet,
snapshotTileGridChangedRunnable, tileCountChangedRunnable,
StartSurfaceConfiguration.isNtpAsHomeSurfaceEnabled(isTablet)
&& FeedFeatures.isMultiColumnFeedEnabled(activity));
}
/**
* Called before the TasksSurface is showing to initialize MV tiles.
* {@link MostVisitedTilesCoordinator#destroyMvtiles()} is called after the TasksSurface hides.
*
* @param suggestionsUiDelegate The UI delegate of suggestion surface.
* @param tileGroupDelegate The delegate of tile group.
* @param touchEnabledDelegate The {@link TouchEnabledDelegate} for handling whether touch
* events are allowed.
*/
public void initWithNative(SuggestionsUiDelegate suggestionsUiDelegate,
TileGroup.Delegate tileGroupDelegate, TouchEnabledDelegate touchEnabledDelegate) {
mActivityLifecycleDispatcher.register(this);
Profile profile = Profile.getLastUsedRegularProfile();
if (mRenderer == null) {
mRenderer = new TileRenderer(mActivity, SuggestionsConfig.getTileStyle(mUiConfig), 1,
suggestionsUiDelegate.getImageFetcher());
} else {
mRenderer.setImageFetcher(suggestionsUiDelegate.getImageFetcher());
}
mRenderer.onNativeInitializationReady();
mContextMenuManager = new ContextMenuManager(suggestionsUiDelegate.getNavigationDelegate(),
touchEnabledDelegate, mActivity::closeContextMenu, CONTEXT_MENU_USER_ACTION_PREFIX);
mWindowAndroid.addContextMenuCloseListener(mContextMenuManager);
mOfflinePageBridge =
SuggestionsDependencyFactory.getInstance().getOfflinePageBridge(profile);
mMediator.initWithNative(suggestionsUiDelegate, mContextMenuManager, tileGroupDelegate,
mOfflinePageBridge, mRenderer);
}
/** Called when the TasksSurface is hidden or NewTabPageLayout is destroyed. */
public void destroyMvtiles() {
mActivityLifecycleDispatcher.unregister(this);
if (mOfflinePageBridge != null) mOfflinePageBridge = null;
if (mRenderer != null) mRenderer = null;
if (mWindowAndroid != null) {
mWindowAndroid.removeContextMenuCloseListener(mContextMenuManager);
mContextMenuManager = null;
}
if (mMediator != null) mMediator.destroy();
}
public boolean isMVTilesCleanedUp() {
return mMediator.isMVTilesCleanedUp();
}
public void onSwitchToForeground() {
if (!isMVTilesCleanedUp()) mMediator.onSwitchToForeground();
}
/* ConfigurationChangedObserver implementation. */
@Override
public void onConfigurationChanged(Configuration newConfig) {
mMediator.onConfigurationChanged();
mUiConfig.updateDisplayStyle();
}
@VisibleForTesting
public void onTemplateURLServiceChangedForTesting() {
mMediator.onTemplateURLServiceChanged();
}
}