Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 org.chromium.base.Callback; | 7 import org.chromium.base.Callback; |
| 8 import org.chromium.base.Log; | 8 import org.chromium.base.Log; |
| 9 import org.chromium.base.VisibleForTesting; | 9 import org.chromium.base.VisibleForTesting; |
| 10 import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; | 10 import org.chromium.chrome.browser.ntp.NewTabPage.DestructionObserver; |
| 11 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; | 11 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; |
| 12 import org.chromium.chrome.browser.ntp.cards.SectionList.SuggestionRanker; | |
| 12 import org.chromium.chrome.browser.ntp.snippets.CategoryInt; | 13 import org.chromium.chrome.browser.ntp.snippets.CategoryInt; |
| 13 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m; | 14 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m; |
| 14 import org.chromium.chrome.browser.ntp.snippets.SectionHeader; | 15 import org.chromium.chrome.browser.ntp.snippets.SectionHeader; |
| 15 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; | 16 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; |
| 16 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder; | 17 import org.chromium.chrome.browser.ntp.snippets.SnippetArticleViewHolder; |
| 17 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; | 18 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; |
| 18 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; | 19 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; |
| 19 import org.chromium.chrome.browser.offlinepages.ClientId; | 20 import org.chromium.chrome.browser.offlinepages.ClientId; |
| 20 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; | 21 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; |
| 21 import org.chromium.chrome.browser.offlinepages.OfflinePageItem; | 22 import org.chromium.chrome.browser.offlinepages.OfflinePageItem; |
| 22 | 23 |
| 23 import java.util.ArrayList; | 24 import java.util.ArrayList; |
| 24 import java.util.Iterator; | 25 import java.util.Iterator; |
| 25 import java.util.List; | 26 import java.util.List; |
| 26 | 27 |
| 27 /** | 28 /** |
| 28 * A group of suggestions, with a header, a status card, and a progress indicato r. This is | 29 * A group of suggestions, with a header, a status card, and a progress indicato r. This is |
| 29 * responsible for tracking whether its suggestions have been saved offline. | 30 * responsible for tracking whether its suggestions have been saved offline. |
| 30 */ | 31 */ |
| 31 public class SuggestionsSection extends InnerNode { | 32 public class SuggestionsSection extends InnerNode { |
| 32 private static final String TAG = "NtpCards"; | 33 private static final String TAG = "NtpCards"; |
| 33 | 34 |
| 34 private final Delegate mDelegate; | 35 private final Delegate mDelegate; |
| 35 private final SuggestionsCategoryInfo mCategoryInfo; | 36 private final SuggestionsCategoryInfo mCategoryInfo; |
| 36 private final OfflinePageBridge mOfflinePageBridge; | 37 private final OfflinePageBridge mOfflinePageBridge; |
| 38 private final SuggestionRanker mSuggestionRanker; | |
| 37 | 39 |
| 38 // Children | 40 // Children |
| 39 private final SectionHeader mHeader; | 41 private final SectionHeader mHeader; |
| 40 private final SuggestionsList mSuggestionsList; | 42 private final SuggestionsList mSuggestionsList; |
| 41 private final StatusItem mStatus; | 43 private final StatusItem mStatus; |
| 42 private final ActionItem mMoreButton; | 44 private final ActionItem mMoreButton; |
| 43 private final ProgressItem mProgressIndicator; | 45 private final ProgressItem mProgressIndicator; |
| 44 | 46 |
| 45 private boolean mIsNtpDestroyed; | 47 private boolean mIsNtpDestroyed; |
| 46 | 48 |
| 47 // Keep track of impressions of the suggestions so that we replace only sugg estions that | 49 // Keep track of impressions of the suggestions so that we replace only sugg estions that |
| 48 // have not been impressed, yet. We keep track of the first suggestion separ ately as the | 50 // have not been impressed, yet. We keep track of the first suggestion separ ately as the |
| 49 // first is often impressed in the form of a peeking card and we still want to be able to | 51 // first is often impressed in the form of a peeking card and we still want to be able to |
| 50 // replace something in this case. | 52 // replace something in this case. |
| 51 private boolean mFirstSuggestionSeen; | 53 private boolean mFirstSuggestionSeen; |
| 52 private boolean mSubsequentSuggestionsSeen; | 54 private boolean mSubsequentSuggestionsSeen; |
| 53 | 55 |
| 54 /** | 56 /** |
| 55 * Delegate interface that allows dismissing this section without introducin g | 57 * Delegate interface that allows dismissing this section without introducin g |
| 56 * a circular dependency. | 58 * a circular dependency. |
| 57 */ | 59 */ |
| 58 public interface Delegate { | 60 public interface Delegate { |
| 59 void dismissSection(SuggestionsSection section); | 61 void dismissSection(SuggestionsSection section); |
| 60 } | 62 } |
| 61 | 63 |
| 62 public SuggestionsSection(Delegate delegate, NewTabPageManager manager, | 64 public SuggestionsSection(Delegate delegate, NewTabPageManager manager, Sugg estionRanker ranker, |
| 63 OfflinePageBridge offlinePageBridge, SuggestionsCategoryInfo info) { | 65 OfflinePageBridge offlinePageBridge, SuggestionsCategoryInfo info) { |
| 64 mDelegate = delegate; | 66 mDelegate = delegate; |
| 65 mCategoryInfo = info; | 67 mCategoryInfo = info; |
| 66 mOfflinePageBridge = offlinePageBridge; | 68 mOfflinePageBridge = offlinePageBridge; |
| 69 mSuggestionRanker = ranker; | |
| 67 | 70 |
| 68 mHeader = new SectionHeader(info.getTitle()); | 71 mHeader = new SectionHeader(info.getTitle()); |
| 69 mSuggestionsList = new SuggestionsList(manager, info); | 72 mSuggestionsList = new SuggestionsList(manager, info); |
| 70 mStatus = StatusItem.createNoSuggestionsItem(info); | 73 mStatus = StatusItem.createNoSuggestionsItem(info); |
| 71 mMoreButton = new ActionItem(this); | 74 mMoreButton = new ActionItem(this); |
| 72 mProgressIndicator = new ProgressItem(); | 75 mProgressIndicator = new ProgressItem(); |
| 73 addChildren(mHeader, mSuggestionsList, mStatus, mMoreButton, mProgressIn dicator); | 76 addChildren(mHeader, mSuggestionsList, mStatus, mMoreButton, mProgressIn dicator); |
| 74 | 77 |
| 75 setupOfflinePageBridgeObserver(manager); | 78 setupOfflinePageBridgeObserver(manager); |
| 76 refreshChildrenVisibility(); | 79 refreshChildrenVisibility(); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 241 } | 244 } |
| 242 | 245 |
| 243 @Override | 246 @Override |
| 244 public void onItemRangeRemoved(TreeNode child, int index, int count) { | 247 public void onItemRangeRemoved(TreeNode child, int index, int count) { |
| 245 super.onItemRangeRemoved(child, index, count); | 248 super.onItemRangeRemoved(child, index, count); |
| 246 if (child == mSuggestionsList) refreshChildrenVisibility(); | 249 if (child == mSuggestionsList) refreshChildrenVisibility(); |
| 247 } | 250 } |
| 248 | 251 |
| 249 @Override | 252 @Override |
| 250 public void onBindViewHolder(NewTabPageViewHolder holder, int position, List <Object> payloads) { | 253 public void onBindViewHolder(NewTabPageViewHolder holder, int position, List <Object> payloads) { |
| 254 @ItemViewType | |
| 255 int viewType = getItemViewType(position); | |
| 256 if (viewType == ItemViewType.SNIPPET) { | |
| 257 childSeen(position); | |
| 258 } else if (viewType == ItemViewType.ACTION) { | |
| 259 mSuggestionRanker.rankItem((ActionItem) getChildForPosition(position ), this); | |
|
Bernhard Bauer
2017/01/17 17:42:31
Could we have the ActionItem itself call this?
dgn
2017/01/17 18:46:24
Done.
| |
| 260 } | |
| 251 super.onBindViewHolder(holder, position, payloads); | 261 super.onBindViewHolder(holder, position, payloads); |
| 252 childSeen(position); | |
| 253 } | 262 } |
| 254 | 263 |
| 255 /** | 264 /** |
| 256 * Sets the child at position {@code position} as being seen by the user. | 265 * Sets the child at position {@code position} as being seen by the user. |
| 257 * @param position Position in the list being shown (the first suggestion be ing at index 1, | 266 * @param position Position in the list being shown (the first suggestion be ing at index 1, |
| 258 * as at index 0, there is a non-suggestion). | 267 * as at index 0, there is a non-suggestion). |
| 259 */ | 268 */ |
| 260 @VisibleForTesting | 269 @VisibleForTesting |
| 261 public void childSeen(int position) { | 270 public void childSeen(int position) { |
|
Bernhard Bauer
2017/01/17 17:42:31
If this is only called for suggestions now, rename
dgn
2017/01/17 18:46:24
Reverted since actionItem calls its ranker itself.
| |
| 262 Log.d(TAG, "childSeen: position %d in category %d", position, mCategoryI nfo.getCategory()); | 271 Log.d(TAG, "childSeen: position %d in category %d", position, mCategoryI nfo.getCategory()); |
| 263 assert getStartingOffsetForChild(mSuggestionsList) == 1; | 272 assert getStartingOffsetForChild(mSuggestionsList) == 1; |
| 264 if (getItemViewType(position) == ItemViewType.SNIPPET) { | 273 assert getItemViewType(position) == ItemViewType.SNIPPET; |
| 265 // We assume all non-snippet cards come after all cards of type SNIP PET. | 274 |
| 266 int positionAmongSuggestions = position - 1; | 275 // We assume all non-snippet cards come after all cards of type SNIPPET. |
| 267 if (positionAmongSuggestions == 0) { | 276 int positionAmongSuggestions = position - 1; |
| 268 mFirstSuggestionSeen = true; | 277 if (positionAmongSuggestions == 0) { |
| 269 } else if (positionAmongSuggestions > 0) { | 278 mFirstSuggestionSeen = true; |
| 270 mSubsequentSuggestionsSeen = true; | 279 } else if (positionAmongSuggestions > 0) { |
| 271 } | 280 mSubsequentSuggestionsSeen = true; |
| 272 } | 281 } |
| 273 } | 282 } |
| 274 | 283 |
| 275 /** | 284 /** |
| 276 * Removes a suggestion. Does nothing if the ID is unknown. | 285 * Removes a suggestion. Does nothing if the ID is unknown. |
| 277 * @param idWithinCategory The ID of the suggestion to remove. | 286 * @param idWithinCategory The ID of the suggestion to remove. |
| 278 */ | 287 */ |
| 279 public void removeSuggestionById(String idWithinCategory) { | 288 public void removeSuggestionById(String idWithinCategory) { |
| 280 int i = 0; | 289 int i = 0; |
| 281 for (SnippetArticle suggestion : mSuggestionsList) { | 290 for (SnippetArticle suggestion : mSuggestionsList) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 Log.d(TAG, "setSuggestions: removing all suggestions"); | 351 Log.d(TAG, "setSuggestions: removing all suggestions"); |
| 343 mSuggestionsList.clear(); | 352 mSuggestionsList.clear(); |
| 344 } | 353 } |
| 345 } | 354 } |
| 346 | 355 |
| 347 mProgressIndicator.setVisible(SnippetsBridge.isCategoryLoading(status)); | 356 mProgressIndicator.setVisible(SnippetsBridge.isCategoryLoading(status)); |
| 348 | 357 |
| 349 mSuggestionsList.addAll(suggestions); | 358 mSuggestionsList.addAll(suggestions); |
| 350 | 359 |
| 351 for (SnippetArticle article : suggestions) { | 360 for (SnippetArticle article : suggestions) { |
| 361 mSuggestionRanker.rankItem(article); | |
| 352 if (!article.requiresExactOfflinePage()) { | 362 if (!article.requiresExactOfflinePage()) { |
| 353 updateSnippetOfflineAvailability(article); | 363 updateSnippetOfflineAvailability(article); |
| 354 } | 364 } |
| 355 } | 365 } |
| 356 | 366 |
| 357 refreshChildrenVisibility(); | 367 refreshChildrenVisibility(); |
| 358 } | 368 } |
| 359 | 369 |
| 360 private void updateSnippetOfflineAvailability(final SnippetArticle article) { | 370 private void updateSnippetOfflineAvailability(final SnippetArticle article) { |
| 361 // This method is not applicable to articles for which the exact offline id must specified. | 371 // This method is not applicable to articles for which the exact offline id must specified. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 @VisibleForTesting | 451 @VisibleForTesting |
| 442 ActionItem getActionItem() { | 452 ActionItem getActionItem() { |
| 443 return mMoreButton; | 453 return mMoreButton; |
| 444 } | 454 } |
| 445 | 455 |
| 446 @VisibleForTesting | 456 @VisibleForTesting |
| 447 StatusItem getStatusItem() { | 457 StatusItem getStatusItem() { |
| 448 return mStatus; | 458 return mStatus; |
| 449 } | 459 } |
| 450 } | 460 } |
| OLD | NEW |