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

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

Issue 2274293002: 📰 Keep Suggestion sections in declaration order (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix render test Created 4 years, 3 months 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
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.ntp.cards; 5 package org.chromium.chrome.browser.ntp.cards;
6 6
7 import android.graphics.Canvas; 7 import android.graphics.Canvas;
8 import android.support.v4.view.ViewCompat; 8 import android.support.v4.view.ViewCompat;
9 import android.support.v7.widget.RecyclerView; 9 import android.support.v7.widget.RecyclerView;
10 import android.support.v7.widget.RecyclerView.Adapter; 10 import android.support.v7.widget.RecyclerView.Adapter;
(...skipping 14 matching lines...) Expand all
25 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m; 25 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m;
26 import org.chromium.chrome.browser.ntp.snippets.SectionHeader; 26 import org.chromium.chrome.browser.ntp.snippets.SectionHeader;
27 import org.chromium.chrome.browser.ntp.snippets.SectionHeaderViewHolder; 27 import org.chromium.chrome.browser.ntp.snippets.SectionHeaderViewHolder;
28 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; 28 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
29 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder; 29 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder;
30 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; 30 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
31 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; 31 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
32 32
33 import java.util.ArrayList; 33 import java.util.ArrayList;
34 import java.util.Collections; 34 import java.util.Collections;
35 import java.util.LinkedHashMap;
35 import java.util.List; 36 import java.util.List;
36 import java.util.Map; 37 import java.util.Map;
37 import java.util.TreeMap;
38 38
39 /** 39 /**
40 * A class that handles merging above the fold elements and below the fold cards into an adapter 40 * A class that handles merging above the fold elements and below the fold cards into an adapter
41 * that will be used to back the NTP RecyclerView. The first element in the adap ter should always be 41 * that will be used to back the NTP RecyclerView. The first element in the adap ter should always be
42 * the above-the-fold view (containing the logo, search box, and most visited ti les) and subsequent 42 * the above-the-fold view (containing the logo, search box, and most visited ti les) and subsequent
43 * elements will be the cards shown to the user 43 * elements will be the cards shown to the user
44 */ 44 */
45 public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> 45 public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
46 implements SuggestionsSource.Observer { 46 implements SuggestionsSource.Observer {
47 private static final String TAG = "Ntp"; 47 private static final String TAG = "Ntp";
48 48
49 private final NewTabPageManager mNewTabPageManager; 49 private final NewTabPageManager mNewTabPageManager;
50 private final View mAboveTheFoldView; 50 private final View mAboveTheFoldView;
51 private SuggestionsSource mSuggestionsSource; 51 private SuggestionsSource mSuggestionsSource;
52 private final UiConfig mUiConfig; 52 private final UiConfig mUiConfig;
53 private final ItemTouchCallbacks mItemTouchCallbacks = new ItemTouchCallback s(); 53 private final ItemTouchCallbacks mItemTouchCallbacks = new ItemTouchCallback s();
54 private NewTabPageRecyclerView mRecyclerView; 54 private NewTabPageRecyclerView mRecyclerView;
55 55
56 /** 56 /**
57 * List of all item groups (which can themselves contain multiple items. Whe n flattened, this 57 * List of all item groups (which can themselves contain multiple items. Whe n flattened, this
58 * will be a list of all items the adapter exposes. 58 * will be a list of all items the adapter exposes.
59 */ 59 */
60 private final List<ItemGroup> mGroups = new ArrayList<>(); 60 private final List<ItemGroup> mGroups = new ArrayList<>();
61 private final AboveTheFoldItem mAboveTheFold = new AboveTheFoldItem(); 61 private final AboveTheFoldItem mAboveTheFold = new AboveTheFoldItem();
62 private final SpacingItem mBottomSpacer = new SpacingItem(); 62 private final SpacingItem mBottomSpacer = new SpacingItem();
63 63
64 /** Maps suggestion categories to sections, with stable iteration ordering. */ 64 /** Maps suggestion categories to sections, with stable iteration ordering. */
65 private final Map<Integer, SuggestionsSection> mSections = new TreeMap<>(); 65 private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap <>();
66 66
67 private class ItemTouchCallbacks extends ItemTouchHelper.Callback { 67 private class ItemTouchCallbacks extends ItemTouchHelper.Callback {
68 @Override 68 @Override
69 public void onSwiped(ViewHolder viewHolder, int direction) { 69 public void onSwiped(ViewHolder viewHolder, int direction) {
70 mRecyclerView.onItemDismissStarted(viewHolder.itemView); 70 mRecyclerView.onItemDismissStarted(viewHolder.itemView);
71 71
72 NewTabPageAdapter.this.dismissItem(viewHolder); 72 NewTabPageAdapter.this.dismissItem(viewHolder);
73 } 73 }
74 74
75 @Override 75 @Override
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 for (int category : categories) { 138 for (int category : categories) {
139 int categoryStatus = suggestionsSource.getCategoryStatus(category); 139 int categoryStatus = suggestionsSource.getCategoryStatus(category);
140 assert categoryStatus != CategoryStatus.NOT_PROVIDED; 140 assert categoryStatus != CategoryStatus.NOT_PROVIDED;
141 if (categoryStatus == CategoryStatus.LOADING_ERROR 141 if (categoryStatus == CategoryStatus.LOADING_ERROR
142 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED) 142 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED)
143 continue; 143 continue;
144 144
145 List<SnippetArticle> suggestions = 145 List<SnippetArticle> suggestions =
146 suggestionsSource.getSuggestionsForCategory(category); 146 suggestionsSource.getSuggestionsForCategory(category);
147 suggestionsPerCategory[i++] = suggestions.size(); 147 suggestionsPerCategory[i++] = suggestions.size();
148
149 // Create the new section.
150 SuggestionsCategoryInfo info = mSuggestionsSource.getCategoryInfo(ca tegory);
151 if (suggestions.isEmpty() && !info.showIfEmpty()) continue;
152 mSections.put(category, new SuggestionsSection(category, info, this) );
153
154 // Add the new suggestions.
148 setSuggestions(category, suggestions, categoryStatus); 155 setSuggestions(category, suggestions, categoryStatus);
149 } 156 }
150 // |mNewTabPageManager| is null in some tests. 157 // |mNewTabPageManager| is null in some tests.
151 if (mNewTabPageManager != null) { 158 if (mNewTabPageManager != null) {
152 mNewTabPageManager.trackSnippetsPageImpression(categories, suggestio nsPerCategory); 159 mNewTabPageManager.trackSnippetsPageImpression(categories, suggestio nsPerCategory);
153 } 160 }
154 suggestionsSource.setObserver(this); 161 suggestionsSource.setObserver(this);
155 updateGroups(); 162 updateGroups();
156 } 163 }
157 164
158 /** Returns callbacks to configure the interactions with the RecyclerView's items. */ 165 /** Returns callbacks to configure the interactions with the RecyclerView's items. */
159 public ItemTouchHelper.Callback getItemTouchCallbacks() { 166 public ItemTouchHelper.Callback getItemTouchCallbacks() {
160 return mItemTouchCallbacks; 167 return mItemTouchCallbacks;
161 } 168 }
162 169
163 @Override 170 @Override
164 public void onNewSuggestions(@CategoryInt int category) { 171 public void onNewSuggestions(@CategoryInt int category) {
172 // We never want to add suggestions from unknown categories.
173 if (!mSections.containsKey(category)) return;
174
165 // We never want to refresh the suggestions if we already have some cont ent. 175 // We never want to refresh the suggestions if we already have some cont ent.
166 if (mSections.containsKey(category) && mSections.get(category).hasSugges tions()) return; 176 if (mSections.get(category).hasSuggestions()) return;
167 177
168 // The status may have changed while the suggestions were loading, perha ps they should not 178 // The status may have changed while the suggestions were loading, perha ps they should not
169 // be displayed any more. 179 // be displayed any more.
170 @CategoryStatusEnum 180 @CategoryStatusEnum
171 int status = mSuggestionsSource.getCategoryStatus(category); 181 int status = mSuggestionsSource.getCategoryStatus(category);
172 if (!SnippetsBridge.isCategoryEnabled(status)) { 182 if (!SnippetsBridge.isCategoryEnabled(status)) {
173 Log.w(TAG, "Received suggestions for a disabled category (id=%d, sta tus=%d)", category, 183 Log.w(TAG, "Received suggestions for a disabled category (id=%d, sta tus=%d)", category,
174 status); 184 status);
175 return; 185 return;
176 } 186 }
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 // Count the number of suggestions before this category. 319 // Count the number of suggestions before this category.
310 int globalPositionOffset = 0; 320 int globalPositionOffset = 0;
311 for (Map.Entry<Integer, SuggestionsSection> entry : mSections.entrySet() ) { 321 for (Map.Entry<Integer, SuggestionsSection> entry : mSections.entrySet() ) {
312 if (entry.getKey() == category) break; 322 if (entry.getKey() == category) break;
313 globalPositionOffset += entry.getValue().getSuggestionsCount(); 323 globalPositionOffset += entry.getValue().getSuggestionsCount();
314 } 324 }
315 // Assign global indices to the new suggestions. 325 // Assign global indices to the new suggestions.
316 for (SnippetArticle suggestion : suggestions) { 326 for (SnippetArticle suggestion : suggestions) {
317 suggestion.mGlobalPosition = globalPositionOffset + suggestion.mPosi tion; 327 suggestion.mGlobalPosition = globalPositionOffset + suggestion.mPosi tion;
318 } 328 }
319 // Add the new suggestions.
320 if (!mSections.containsKey(category)) {
321 SuggestionsCategoryInfo info = mSuggestionsSource.getCategoryInfo(ca tegory);
322 if (suggestions.isEmpty() && !info.showIfEmpty()) return;
323
324 mSections.put(category, new SuggestionsSection(category, info, this) );
325 }
326 329
327 mSections.get(category).setSuggestions(suggestions, status); 330 mSections.get(category).setSuggestions(suggestions, status);
328 } 331 }
329 332
330 private void updateGroups() { 333 private void updateGroups() {
331 mGroups.clear(); 334 mGroups.clear();
332 mGroups.add(mAboveTheFold); 335 mGroups.add(mAboveTheFold);
333 // TODO(treib,bauerb): Preserve the order of categories we got from getC ategories. 336 // TODO(treib,bauerb): Preserve the order of categories we got from getC ategories.
334 mGroups.addAll(mSections.values()); 337 mGroups.addAll(mSections.values());
335 if (!mSections.isEmpty()) { 338 if (!mSections.isEmpty()) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 ItemGroup getGroup(int itemPosition) { 404 ItemGroup getGroup(int itemPosition) {
402 int itemsSkipped = 0; 405 int itemsSkipped = 0;
403 for (ItemGroup group : mGroups) { 406 for (ItemGroup group : mGroups) {
404 List<NewTabPageItem> items = group.getItems(); 407 List<NewTabPageItem> items = group.getItems();
405 itemsSkipped += items.size(); 408 itemsSkipped += items.size();
406 if (itemPosition < itemsSkipped) return group; 409 if (itemPosition < itemsSkipped) return group;
407 } 410 }
408 return null; 411 return null;
409 } 412 }
410 413
414 @VisibleForTesting
415 List<ItemGroup> getGroups() {
416 return Collections.unmodifiableList(mGroups);
417 }
418
411 private int getGroupPositionOffset(ItemGroup group) { 419 private int getGroupPositionOffset(ItemGroup group) {
412 int positionOffset = 0; 420 int positionOffset = 0;
413 for (ItemGroup candidateGroup : mGroups) { 421 for (ItemGroup candidateGroup : mGroups) {
414 if (candidateGroup == group) return positionOffset; 422 if (candidateGroup == group) return positionOffset;
415 positionOffset += candidateGroup.getItems().size(); 423 positionOffset += candidateGroup.getItems().size();
416 } 424 }
417 return RecyclerView.NO_POSITION; 425 return RecyclerView.NO_POSITION;
418 } 426 }
419 } 427 }
OLDNEW
« no previous file with comments | « no previous file | chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698