Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java

Issue 2513453004: [Android NTP] Move suggestion sections into a separate node. (Closed)
Patch Set: fix Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.ntp.cards;
Michael van Ouwerkerk 2016/12/12 16:09:57 Fwiw, I'm not convinced having packages 'cards' an
Bernhard Bauer 2016/12/12 17:39:19 Yeah, I agree, the current split feels kind of arb
Michael van Ouwerkerk 2016/12/13 11:08:21 Yes I considered that split, but we have things li
6
7 import org.chromium.base.Log;
8 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
9 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
10 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus;
11 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m;
12 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
13 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
14 import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig;
15 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
16 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
17
18 import java.util.ArrayList;
19 import java.util.LinkedHashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 /**
24 * A node in the tree containing a list of all suggestions sections. It listens to changes in the
25 * suggestions source and updates the corresponding sections.
26 */
27 public class SectionList extends InnerNode implements SuggestionsSource.Observer {
Michael van Ouwerkerk 2016/12/12 16:09:57 It seems it would be nice to see a diff between th
Bernhard Bauer 2016/12/12 17:39:19 Done!
28 private static final String TAG = "Ntp";
29
30 /** Maps suggestion categories to sections, with stable iteration ordering. */
31 private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap <>();
32 private final List<TreeNode> mChildren = new ArrayList<>();
33 private final NewTabPageManager mNewTabPageManager;
34 private final OfflinePageBridge mOfflinePageBridge;
35
36 public SectionList(NodeParent parent, NewTabPageManager newTabPageManager,
37 OfflinePageBridge offlinePageBridge) {
38 super(parent);
39 mNewTabPageManager = newTabPageManager;
40 mNewTabPageManager.getSuggestionsSource().setObserver(this);
41 mOfflinePageBridge = offlinePageBridge;
42 }
43
44 @Override
45 public void init() {
46 super.init();
47 resetSections(/* alwaysAllowEmptySections = */ false);
48 }
49
50 @Override
51 protected List<TreeNode> getChildren() {
52 return mChildren;
53 }
54
55 /**
56 * Resets the sections, reloading the whole new tab page content.
57 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when
58 * they are empty, even when they are normally not.
59 */
60 public void resetSections(boolean alwaysAllowEmptySections) {
61 mSections.clear();
62 mChildren.clear();
63
64 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource();
65 int[] categories = suggestionsSource.getCategories();
66 int[] suggestionsPerCategory = new int[categories.length];
67 int i = 0;
68 for (int category : categories) {
69 int categoryStatus = suggestionsSource.getCategoryStatus(category);
70 if (categoryStatus == CategoryStatus.LOADING_ERROR
71 || categoryStatus == CategoryStatus.NOT_PROVIDED
72 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED)
73 continue;
74
75 suggestionsPerCategory[i++] =
76 resetSection(category, categoryStatus, alwaysAllowEmptySecti ons);
77 }
78
79 mNewTabPageManager.trackSnippetsPageImpression(categories, suggestionsPe rCategory);
80 }
81
82 /**
83 * Resets the section for {@code category}. Removes the section if there are no suggestions for
84 * it and it is not allowed to be empty. Otherwise, creates the section if i t is not present
85 * yet. Sets the available suggestions on the section.
86 * @param category The category for which the section must be reset.
87 * @param categoryStatus The category status.
88 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when
89 * they are empty, even when they are normally not.
90 * @return The number of suggestions for the section.
91 */
92 private int resetSection(@CategoryInt int category, @CategoryStatusEnum int categoryStatus,
93 boolean alwaysAllowEmptySections) {
94 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource();
95 List<SnippetArticle> suggestions = suggestionsSource.getSuggestionsForCa tegory(category);
96 SuggestionsCategoryInfo info = suggestionsSource.getCategoryInfo(categor y);
97
98 SuggestionsSection section = mSections.get(category);
99
100 // Do not show an empty section if not allowed.
101 if (suggestions.isEmpty() && !info.showIfEmpty() && !alwaysAllowEmptySec tions) {
102 if (section != null) removeSection(section);
103 return 0;
104 }
105
106 // Create the section if needed.
107 if (section == null) {
108 section = new SuggestionsSection(this, mNewTabPageManager, mOfflineP ageBridge, info);
109 mSections.put(category, section);
110 mChildren.add(section);
111 didAddChild(section);
112 }
113
114 // Add the new suggestions.
115 setSuggestions(category, suggestions, categoryStatus);
116
117 return suggestions.size();
118 }
119
120 @Override
121 public void onNewSuggestions(@CategoryInt int category) {
122 @CategoryStatusEnum
123 int status = mNewTabPageManager.getSuggestionsSource().getCategoryStatus (category);
124
125 if (!canLoadSuggestions(category, status)) return;
126
127 // We never want to refresh the suggestions if we already have some cont ent.
128 if (mSections.get(category).hasSuggestions()) return;
129
130 List<SnippetArticle> suggestions =
131 mNewTabPageManager.getSuggestionsSource().getSuggestionsForCateg ory(category);
132
133 Log.d(TAG, "Received %d new suggestions for category %d.", suggestions.s ize(), category);
134
135 // At first, there might be no suggestions available, we wait until they have been fetched.
136 if (suggestions.isEmpty()) return;
137
138 setSuggestions(category, suggestions, status);
139 }
140
141 @Override
142 public void onMoreSuggestions(@CategoryInt int category, List<SnippetArticle > suggestions) {
143 @CategoryStatusEnum
144 int status = mNewTabPageManager.getSuggestionsSource().getCategoryStatus (category);
145 if (!canLoadSuggestions(category, status)) return;
146
147 setSuggestions(category, suggestions, status);
148 }
149
150 @Override
151 public void onCategoryStatusChanged(@CategoryInt int category, @CategoryStat usEnum int status) {
152 // Observers should not be registered for this state.
153 assert status != CategoryStatus.ALL_SUGGESTIONS_EXPLICITLY_DISABLED;
154
155 // If there is no section for this category there is nothing to do.
156 if (!mSections.containsKey(category)) return;
157
158 switch (status) {
159 case CategoryStatus.NOT_PROVIDED:
160 // The section provider has gone away. Keep open UIs as they are .
161 return;
162
163 case CategoryStatus.CATEGORY_EXPLICITLY_DISABLED:
164 case CategoryStatus.LOADING_ERROR:
165 // Need to remove the entire section from the UI immediately.
166 removeSection(mSections.get(category));
167 return;
168
169 case CategoryStatus.SIGNED_OUT:
170 resetSection(category, status, /* alwaysAllowEmptySections = */ false);
171 return;
172
173 default:
174 mSections.get(category).setStatus(status);
175 return;
176 }
177 }
178
179 @Override
180 public void onSuggestionInvalidated(@CategoryInt int category, String idWith inCategory) {
181 if (!mSections.containsKey(category)) return;
182 mSections.get(category).removeSuggestionById(idWithinCategory);
183 }
184
185 @Override
186 public void onFullRefreshRequired() {
187 resetSections(/* alwaysAllowEmptySections = */false);
188 }
189
190 private void setSuggestions(@CategoryInt int category, List<SnippetArticle> suggestions,
191 @CategoryStatusEnum int status) {
192 // Count the number of suggestions before this category.
193 int globalPositionOffset = 0;
194 for (Map.Entry<Integer, SuggestionsSection> entry : mSections.entrySet() ) {
195 if (entry.getKey() == category) break;
196 globalPositionOffset += entry.getValue().getSuggestionsCount();
197 }
198 // Assign global indices to the new suggestions.
199 for (SnippetArticle suggestion : suggestions) {
200 suggestion.mGlobalPosition = globalPositionOffset + suggestion.mPosi tion;
201 }
202
203 mSections.get(category).addSuggestions(suggestions, status);
204 }
205
206 private boolean canLoadSuggestions(@CategoryInt int category, @CategoryStatu sEnum int status) {
207 // We never want to add suggestions from unknown categories.
208 if (!mSections.containsKey(category)) return false;
209
210 // The status may have changed while the suggestions were loading, perha ps they should not
211 // be displayed any more.
212 if (!SnippetsBridge.isCategoryEnabled(status)) {
213 Log.w(TAG, "Received suggestions for a disabled category (id=%d, sta tus=%d)", category,
214 status);
215 return false;
216 }
217
218 return true;
219 }
220
221 /**
222 * Dismisses a section.
223 * @param section The section to be dismissed.
224 */
225 public void dismissSection(SuggestionsSection section) {
226 assert SnippetsConfig.isSectionDismissalEnabled();
227
228 mNewTabPageManager.getSuggestionsSource().dismissCategory(section.getCat egory());
229 removeSection(section);
230 }
231
232 private void removeSection(SuggestionsSection section) {
233 mSections.remove(section.getCategory());
234 willRemoveChild(section);
235 mChildren.remove(section);
236 }
237
238 /**
239 * Restores any sections that have been dismissed and triggers a new fetch.
240 */
241 public void restoreDismissedSections() {
242 mNewTabPageManager.getSuggestionsSource().restoreDismissedCategories();
243 resetSections(/* allowEmptySections = */ true);
244 mNewTabPageManager.getSuggestionsSource().fetchRemoteSuggestions();
245 }
246
247 /**
248 * @return Whether the list of sections is empty.
249 */
250 public boolean isEmpty() {
251 return mSections.isEmpty();
252 }
253
254 SuggestionsSection getSectionForTesting(@CategoryInt int categoryId) {
255 return mSections.get(categoryId);
256 }
257 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698