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

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

Issue 2396523002: Unify NewTabPageItem and ItemGroup into a single tree-structured interface. (Closed)
Patch Set: review Created 4 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index 87ab56f13772ae39f7f88eaeebd8b99d009b29be..e539ac4b047515d9afe00d29f7ef082453401b03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -21,7 +21,6 @@ import org.chromium.chrome.browser.ntp.UiConfig;
import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
import org.chromium.chrome.browser.ntp.snippets.CategoryStatus;
import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnum;
-import org.chromium.chrome.browser.ntp.snippets.SectionHeader;
import org.chromium.chrome.browser.ntp.snippets.SectionHeaderViewHolder;
import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder;
@@ -41,8 +40,8 @@ import java.util.Map;
* the above-the-fold view (containing the logo, search box, and most visited tiles) and subsequent
* elements will be the cards shown to the user
*/
-public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
- implements SuggestionsSource.Observer, ItemGroup.Observer {
+public class NewTabPageAdapter
+ extends Adapter<NewTabPageViewHolder> implements SuggestionsSource.Observer, NodeParent {
private static final String TAG = "Ntp";
private final NewTabPageManager mNewTabPageManager;
@@ -55,12 +54,13 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
* List of all item groups (which can themselves contain multiple items. When flattened, this
* will be a list of all items the adapter exposes.
*/
- private final List<ItemGroup> mGroups = new ArrayList<>();
+ private final List<TreeNode> mGroups = new ArrayList<>();
private final AboveTheFoldItem mAboveTheFold = new AboveTheFoldItem();
- private final SignInPromo mSigninPromo = new SignInPromo();
+ private final SignInPromo mSigninPromo;
private final AllDismissedItem mAllDismissed = new AllDismissedItem();
private final Footer mFooter = new Footer();
private final SpacingItem mBottomSpacer = new SpacingItem();
+ private final InnerNode mRoot;
/** Maps suggestion categories to sections, with stable iteration ordering. */
private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap<>();
@@ -134,7 +134,14 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
mNewTabPageManager = manager;
mAboveTheFoldView = aboveTheFoldView;
mUiConfig = uiConfig;
- mSigninPromo.setObserver(this);
+ mRoot = new InnerNode(this) {
+ @Override
+ protected List<TreeNode> getChildren() {
+ return mGroups;
+ }
+ };
+
+ mSigninPromo = new SignInPromo(mRoot);
resetSections(/*alwaysAllowEmptySections=*/false);
mNewTabPageManager.getSuggestionsSource().setObserver(this);
@@ -205,7 +212,7 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
// Create the section if needed.
SuggestionsSection section = mSections.get(category);
if (section == null) {
- section = new SuggestionsSection(info, this);
+ section = new SuggestionsSection(mRoot, info);
mSections.put(category, section);
}
@@ -285,66 +292,59 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
}
@Override
- @NewTabPageItem.ViewType
+ @ItemViewType
public int getItemViewType(int position) {
- return getItems().get(position).getType();
+ return mRoot.getItemViewType(position);
}
@Override
public NewTabPageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
assert parent == mRecyclerView;
- if (viewType == NewTabPageItem.VIEW_TYPE_ABOVE_THE_FOLD) {
- return new NewTabPageViewHolder(mAboveTheFoldView);
- }
+ switch (viewType) {
+ case ItemViewType.ABOVE_THE_FOLD:
+ return new NewTabPageViewHolder(mAboveTheFoldView);
- if (viewType == NewTabPageItem.VIEW_TYPE_HEADER) {
- return new SectionHeaderViewHolder(mRecyclerView, mUiConfig);
- }
+ case ItemViewType.HEADER:
+ return new SectionHeaderViewHolder(mRecyclerView, mUiConfig);
- if (viewType == NewTabPageItem.VIEW_TYPE_SNIPPET) {
- return new SnippetArticleViewHolder(mRecyclerView, mNewTabPageManager, mUiConfig);
- }
+ case ItemViewType.SNIPPET:
+ return new SnippetArticleViewHolder(mRecyclerView, mNewTabPageManager, mUiConfig);
- if (viewType == NewTabPageItem.VIEW_TYPE_SPACING) {
- return new NewTabPageViewHolder(SpacingItem.createView(parent));
- }
+ case ItemViewType.SPACING:
+ return new NewTabPageViewHolder(SpacingItem.createView(parent));
- if (viewType == NewTabPageItem.VIEW_TYPE_STATUS) {
- return new StatusCardViewHolder(mRecyclerView, mUiConfig);
- }
+ case ItemViewType.STATUS:
+ return new StatusCardViewHolder(mRecyclerView, mUiConfig);
- if (viewType == NewTabPageItem.VIEW_TYPE_PROGRESS) {
- return new ProgressViewHolder(mRecyclerView);
- }
+ case ItemViewType.PROGRESS:
+ return new ProgressViewHolder(mRecyclerView);
- if (viewType == NewTabPageItem.VIEW_TYPE_ACTION) {
- return new ActionItem.ViewHolder(mRecyclerView, mNewTabPageManager, mUiConfig);
- }
+ case ItemViewType.ACTION:
+ return new ActionItem.ViewHolder(mRecyclerView, mNewTabPageManager, mUiConfig);
- if (viewType == NewTabPageItem.VIEW_TYPE_PROMO) {
- return new SignInPromo.ViewHolder(mRecyclerView, mUiConfig);
- }
+ case ItemViewType.PROMO:
+ return new SignInPromo.ViewHolder(mRecyclerView, mUiConfig);
- if (viewType == NewTabPageItem.VIEW_TYPE_FOOTER) {
- return new Footer.ViewHolder(mRecyclerView, mNewTabPageManager);
- }
+ case ItemViewType.FOOTER:
+ return new Footer.ViewHolder(mRecyclerView, mNewTabPageManager);
- if (viewType == NewTabPageItem.VIEW_TYPE_ALL_DISMISSED) {
- return new AllDismissedItem.ViewHolder(mRecyclerView, mNewTabPageManager, this);
+ case ItemViewType.ALL_DISMISSED:
+ return new AllDismissedItem.ViewHolder(mRecyclerView, mNewTabPageManager, this);
}
+ assert false : viewType;
return null;
}
@Override
public void onBindViewHolder(NewTabPageViewHolder holder, final int position) {
- getItems().get(position).onBindViewHolder(holder);
+ mRoot.onBindViewHolder(holder, position);
}
@Override
public int getItemCount() {
- return getItems().size();
+ return mRoot.getItemCount();
}
public int getAboveTheFoldPosition() {
@@ -352,9 +352,9 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
}
public int getFirstHeaderPosition() {
- List<NewTabPageItem> items = getItems();
- for (int i = 0; i < items.size(); i++) {
- if (items.get(i) instanceof SectionHeader) return i;
+ int count = getItemCount();
+ for (int i = 0; i < count; i++) {
+ if (getItemViewType(i) == ItemViewType.HEADER) return i;
}
return RecyclerView.NO_POSITION;
}
@@ -379,10 +379,9 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
}
public int getSuggestionPosition(SnippetArticle article) {
- List<NewTabPageItem> items = getItems();
- for (int i = 0; i < items.size(); i++) {
- NewTabPageItem item = items.get(i);
- if (article.equals(item)) return i;
+ for (int i = 0; i < mRoot.getItemCount(); i++) {
+ SnippetArticle articleToCheck = mRoot.getSuggestionAt(i);
+ if (articleToCheck != null && articleToCheck.equals(article)) return i;
}
return RecyclerView.NO_POSITION;
}
@@ -425,7 +424,7 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
mSections.remove(section.getCategory());
int startPos = getGroupPositionOffset(section);
mGroups.remove(section);
- notifyItemRangeRemoved(startPos, section.getItems().size());
+ notifyItemRangeRemoved(startPos, section.getItemCount());
if (hasAllBeenDismissed()) {
int footerPosition = getFooterPosition();
@@ -437,23 +436,26 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
}
@Override
- public void onItemRangeChanged(ItemGroup group, int itemPosition, int itemCount) {
+ public void onItemRangeChanged(TreeNode child, int itemPosition, int itemCount) {
+ assert child == mRoot;
if (mGroups.isEmpty()) return; // The sections have not been initialised yet.
- notifyItemRangeChanged(getGroupPositionOffset(group) + itemPosition, itemCount);
+ notifyItemRangeChanged(itemPosition, itemCount);
}
@Override
- public void onItemRangeInserted(ItemGroup group, int itemPosition, int itemCount) {
+ public void onItemRangeInserted(TreeNode child, int itemPosition, int itemCount) {
+ assert child == mRoot;
if (mGroups.isEmpty()) return; // The sections have not been initialised yet.
- notifyItemRangeInserted(getGroupPositionOffset(group) + itemPosition, itemCount);
- notifyItemChanged(getItems().size() - 1); // Refresh the spacer too.
+ notifyItemRangeInserted(itemPosition, itemCount);
+ notifyItemChanged(getItemCount() - 1); // Refresh the spacer too.
}
@Override
- public void onItemRangeRemoved(ItemGroup group, int itemPosition, int itemCount) {
+ public void onItemRangeRemoved(TreeNode child, int itemPosition, int itemCount) {
+ assert child == mRoot;
if (mGroups.isEmpty()) return; // The sections have not been initialised yet.
- notifyItemRangeRemoved(getGroupPositionOffset(group) + itemPosition, itemCount);
- notifyItemChanged(getItems().size() - 1); // Refresh the spacer too.
+ notifyItemRangeRemoved(itemPosition, itemCount);
+ notifyItemChanged(getItemCount() - 1); // Refresh the spacer too.
}
@Override
@@ -481,16 +483,16 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
// TODO(dgn): Polymorphism is supposed to allow to avoid that kind of stuff.
switch (itemViewType) {
- case NewTabPageItem.VIEW_TYPE_STATUS:
- case NewTabPageItem.VIEW_TYPE_ACTION:
- dismissSection((SuggestionsSection) getGroup(position));
+ case ItemViewType.STATUS:
+ case ItemViewType.ACTION:
+ dismissSection(getSuggestionsSection(position));
return;
- case NewTabPageItem.VIEW_TYPE_SNIPPET:
+ case ItemViewType.SNIPPET:
dismissSuggestion(position);
return;
- case NewTabPageItem.VIEW_TYPE_PROMO:
+ case ItemViewType.PROMO:
dismissPromo();
return;
@@ -506,8 +508,7 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
}
private void dismissSuggestion(int position) {
- SnippetArticle suggestion = (SnippetArticle) getItems().get(position);
-
+ SnippetArticle suggestion = mRoot.getSuggestionAt(position);
SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsSource();
if (suggestionsSource == null) {
// It is possible for this method to be called after the NewTabPage has had destroy()
@@ -520,7 +521,7 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
announceItemRemoved(suggestion.mTitle);
suggestionsSource.dismissSuggestion(suggestion);
- SuggestionsSection section = (SuggestionsSection) getGroup(position);
+ SuggestionsSection section = getSuggestionsSection(position);
section.removeSuggestion(suggestion);
}
@@ -536,27 +537,15 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
}
/**
- * Returns an unmodifiable list containing all items in the adapter.
- */
- private List<NewTabPageItem> getItems() {
- List<NewTabPageItem> items = new ArrayList<>();
- for (ItemGroup group : mGroups) {
- items.addAll(group.getItems());
- }
- return Collections.unmodifiableList(items);
- }
-
- /**
* Returns another view holder that should be dismissed at the same time as the provided one.
*/
public ViewHolder getDismissSibling(ViewHolder viewHolder) {
int swipePos = viewHolder.getAdapterPosition();
- ItemGroup group = getGroup(swipePos);
-
- if (!(group instanceof SuggestionsSection)) return null;
+ SuggestionsSection section = getSuggestionsSection(swipePos);
+ if (section == null) return null;
- SuggestionsSection section = (SuggestionsSection) group;
- int siblingPosDelta = section.getDismissSiblingPosDelta(getItems().get(swipePos));
+ int siblingPosDelta =
+ section.getDismissSiblingPosDelta(swipePos - getGroupPositionOffset(section));
if (siblingPosDelta == 0) return null;
return mRecyclerView.findViewHolderForAdapterPosition(siblingPosDelta + swipePos);
@@ -566,36 +555,31 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder>
return mSections.isEmpty() && !mSigninPromo.isShown();
}
+ /**
+ * @param itemPosition The position of an item in the adapter.
+ * @return Returns the {@link SuggestionsSection} that contains the item at
+ * {@code itemPosition}, or null if the item is not part of one.
+ */
@VisibleForTesting
- ItemGroup getGroup(int itemPosition) {
- int itemsSkipped = 0;
- for (ItemGroup group : mGroups) {
- List<NewTabPageItem> items = group.getItems();
- itemsSkipped += items.size();
- if (itemPosition < itemsSkipped) return group;
- }
- return null;
+ SuggestionsSection getSuggestionsSection(int itemPosition) {
+ TreeNode child = mGroups.get(mRoot.getChildIndexForPosition(itemPosition));
+ if (!(child instanceof SuggestionsSection)) return null;
+ return (SuggestionsSection) child;
}
@VisibleForTesting
- List<ItemGroup> getGroups() {
+ List<TreeNode> getGroups() {
return Collections.unmodifiableList(mGroups);
}
@VisibleForTesting
- int getGroupPositionOffset(ItemGroup group) {
- int positionOffset = 0;
- for (ItemGroup candidateGroup : mGroups) {
- if (candidateGroup == group) return positionOffset;
- positionOffset += candidateGroup.getItems().size();
- }
- Log.d(TAG, "Group not found: %s", group);
- return RecyclerView.NO_POSITION;
+ int getGroupPositionOffset(TreeNode group) {
+ return mRoot.getStartingOffsetForChild(group);
}
@VisibleForTesting
SnippetArticle getSuggestionAt(int position) {
- return (SnippetArticle) getItems().get(position);
+ return mRoot.getSuggestionAt(position);
}
private void announceItemRemoved(String suggestionTitle) {

Powered by Google App Engine
This is Rietveld 408576698