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

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java

Issue 2688383005: [NTP::Downloads] Show thumbnails for Download suggestions. (Closed)
Patch Set: clean rebase + dfalcantara@ comment + isRecycled() check in DownloadItemView Created 3 years, 10 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/snippets/SnippetArticleViewHolder.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
index aeb54cc9520624a47da71ff387df5f4d48746d72..d809a34af399f5c05583e3241ab53b2d79c4b9ec 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.ntp.snippets;
import android.annotation.SuppressLint;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
@@ -14,6 +15,7 @@ import android.media.ThumbnailUtils;
import android.os.StrictMode;
import android.os.SystemClock;
import android.support.v4.text.BidiFormatter;
+import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -25,6 +27,10 @@ import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.Callback;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.download.DownloadUtils;
+import org.chromium.chrome.browser.download.ui.DownloadFilter;
+import org.chromium.chrome.browser.download.ui.ThumbnailProvider;
+import org.chromium.chrome.browser.download.ui.ThumbnailProviderImpl;
import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback;
import org.chromium.chrome.browser.favicon.FaviconHelper.IconAvailabilityCallback;
import org.chromium.chrome.browser.ntp.ContextMenuManager;
@@ -36,6 +42,7 @@ import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo;
import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
+import org.chromium.chrome.browser.widget.TintedImageView;
import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver;
import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserverAdapter;
import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle;
@@ -68,21 +75,25 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
private final TextView mHeadlineTextView;
private final TextView mPublisherTextView;
private final TextView mArticleSnippetTextView;
- private final ImageView mThumbnailView;
+ private final TintedImageView mThumbnailView;
private final ImageView mOfflineBadge;
private final View mPublisherBar;
+ private final boolean mUseFaviconService;
+ private final UiConfig mUiConfig;
+
+ private final ColorStateList mIconForegroundColorList;
+ private final int mIconBackgroundColor;
+ private final ThumbnailProvider mThumbnailProvider;
+
private FetchImageCallback mImageCallback;
private SnippetArticle mArticle;
private SuggestionsCategoryInfo mCategoryInfo;
private int mPublisherFaviconSizePx;
- private final boolean mUseFaviconService;
- private final UiConfig mUiConfig;
-
/**
* Constructs a {@link SnippetArticleViewHolder} item used to display snippets.
- * @param parent The NewTabPageRecyclerView that is going to contain the newly created view.
+ * @param parent The NewTabPageRecyclerView that is going to contain the newly created view.
* @param contextMenuManager The manager responsible for the context menu.
* @param uiDelegate The delegate object used to open an article, fetch thumbnails, etc.
* @param uiConfig The NTP UI configuration object used to adjust the article UI.
@@ -93,7 +104,7 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
super(R.layout.new_tab_page_snippets_card, parent, uiConfig, contextMenuManager);
mUiDelegate = uiDelegate;
- mThumbnailView = (ImageView) itemView.findViewById(R.id.article_thumbnail);
+ mThumbnailView = (TintedImageView) itemView.findViewById(R.id.article_thumbnail);
mHeadlineTextView = (TextView) itemView.findViewById(R.id.article_headline);
mPublisherTextView = (TextView) itemView.findViewById(R.id.article_publisher);
mArticleSnippetTextView = (TextView) itemView.findViewById(R.id.article_snippet);
@@ -111,6 +122,11 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
});
mUseFaviconService = CardsVariationParameters.isFaviconServiceEnabled();
+
+ mIconBackgroundColor = DownloadUtils.getIconBackgroundColor(parent.getContext());
+ mIconForegroundColorList = DownloadUtils.getIconForegroundColorList(parent.getContext());
+ mThumbnailProvider = new ThumbnailProviderImpl(
+ Math.min(mThumbnailView.getMaxWidth(), mThumbnailView.getMaxHeight()));
}
@Override
@@ -153,6 +169,44 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
}
/**
+ * Updates ViewHolder with data.
+ * @param article The snippet to take the data from.
+ * @param categoryInfo The info of the category which the snippet belongs to.
+ */
+ public void onBindViewHolder(SnippetArticle article, SuggestionsCategoryInfo categoryInfo) {
+ super.onBindViewHolder();
+
+ mArticle = article;
+ mCategoryInfo = categoryInfo;
+ updateLayout();
+
+ mHeadlineTextView.setText(mArticle.mTitle);
+ mPublisherTextView.setText(getAttributionString(mArticle));
+
+ // The favicon of the publisher should match the TextView height.
+ int widthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ mPublisherTextView.measure(widthSpec, heightSpec);
+ mPublisherFaviconSizePx = mPublisherTextView.getMeasuredHeight();
+
+ mArticleSnippetTextView.setText(mArticle.mPreviewText);
+
+ setThumbnail();
+
+ // Set the favicon of the publisher.
+ try {
+ fetchFaviconFromLocalCache(new URI(mArticle.mUrl), true);
+ } catch (URISyntaxException e) {
+ setDefaultFaviconOnView();
+ }
+
+ mOfflineBadge.setVisibility(View.GONE);
+ refreshOfflineBadgeVisibility();
+
+ mRecyclerView.onSnippetBound(itemView);
+ }
+
+ /**
* Updates the layout taking into account screen dimensions and the type of snippet displayed.
*/
private void updateLayout() {
@@ -237,87 +291,84 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
BidiFormatter.getInstance().unicodeWrap(article.mPublisher), relativeTimeSpan);
}
- public void onBindViewHolder(SnippetArticle article, SuggestionsCategoryInfo categoryInfo) {
- super.onBindViewHolder();
+ private void setThumbnailFromBitmap(Bitmap thumbnail) {
+ assert thumbnail != null && !thumbnail.isRecycled();
+ mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ mThumbnailView.setBackground(null);
+ mThumbnailView.setImageBitmap(thumbnail);
+ mThumbnailView.setTint(null);
+ }
- mArticle = article;
- mCategoryInfo = categoryInfo;
- updateLayout();
+ private void setThumbnailFromFileType(int fileType) {
+ mThumbnailView.setScaleType(ImageView.ScaleType.CENTER);
+ mThumbnailView.setBackgroundColor(mIconBackgroundColor);
+ mThumbnailView.setImageResource(DownloadUtils.getIconResId(fileType));
+ mThumbnailView.setTint(mIconForegroundColorList);
+ }
- mHeadlineTextView.setText(mArticle.mTitle);
- mPublisherTextView.setText(getAttributionString(mArticle));
+ private void setDownloadThumbnail() {
+ assert mArticle.isDownload();
+ if (mArticle.isAssetDownload()) {
+ int fileType = DownloadFilter.fromMimeType(mArticle.getAssetDownloadMimeType());
+ setThumbnailFromFileType(fileType);
- // The favicon of the publisher should match the TextView height.
- int widthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- mPublisherTextView.measure(widthSpec, heightSpec);
- mPublisherFaviconSizePx = mPublisherTextView.getMeasuredHeight();
+ if (fileType != DownloadFilter.FILTER_IMAGE) return;
+ if (mImageCallback != null) {
+ mThumbnailProvider.cancelRetrieval(mImageCallback);
+ mImageCallback = null;
+ }
+ mImageCallback = new FetchImageCallback(this, mArticle);
+ mArticle.setThumbnailBitmap(null);
+ Bitmap thumbnail = mThumbnailProvider.getThumbnail(mImageCallback);
+ if (thumbnail == null || thumbnail.isRecycled()) return;
+ mArticle.setThumbnailBitmap(thumbnail);
+ setThumbnailFromBitmap(thumbnail);
+
+ return;
+ }
- mArticleSnippetTextView.setText(mArticle.mPreviewText);
+ setThumbnailFromFileType(DownloadFilter.FILTER_PAGE);
+ }
+ private void setThumbnail() {
// If there's still a pending thumbnail fetch, cancel it.
cancelImageFetch();
- // If the article has a thumbnail already, reuse it. Otherwise start a fetch.
// mThumbnailView's visibility is modified in updateLayout().
- if (mThumbnailView.getVisibility() == View.VISIBLE) {
- if (mArticle.getThumbnailBitmap() != null) {
- mThumbnailView.setImageBitmap(mArticle.getThumbnailBitmap());
- } else {
- mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder);
- mImageCallback = new FetchImageCallback(this, mArticle);
- mUiDelegate.getSuggestionsSource().fetchSuggestionImage(mArticle, mImageCallback);
- }
+ if (mThumbnailView.getVisibility() != View.VISIBLE) return;
+ if (mArticle.getThumbnailBitmap() != null && !mArticle.getThumbnailBitmap().isRecycled()) {
+ setThumbnailFromBitmap(mArticle.getThumbnailBitmap());
+ return;
}
- // Set the favicon of the publisher.
- try {
- fetchFaviconFromLocalCache(new URI(mArticle.mUrl), true);
- } catch (URISyntaxException e) {
- setDefaultFaviconOnView();
+ if (mArticle.isDownload()) {
+ setDownloadThumbnail();
+ return;
}
- mOfflineBadge.setVisibility(View.GONE);
- refreshOfflineBadgeVisibility();
-
- mRecyclerView.onSnippetBound(itemView);
+ // Temporarily set placeholder and then fetch the thumbnail from a provider.
+ mThumbnailView.setBackground(null);
+ mThumbnailView.setImageResource(R.drawable.ic_snippet_thumbnail_placeholder);
+ mThumbnailView.setTint(null);
+ mImageCallback = new FetchImageCallback(this, mArticle);
+ mUiDelegate.getSuggestionsSource().fetchSuggestionImage(mArticle, mImageCallback);
}
/** Updates the visibility of the card's offline badge by checking the bound article's info. */
private void refreshOfflineBadgeVisibility() {
if (!SnippetsConfig.isOfflineBadgeEnabled()) return;
- boolean visible = mArticle.getOfflinePageOfflineId() != null || mArticle.mIsAssetDownload;
+ boolean visible = mArticle.getOfflinePageOfflineId() != null || mArticle.isAssetDownload();
if (visible == (mOfflineBadge.getVisibility() == View.VISIBLE)) return;
mOfflineBadge.setVisibility(visible ? View.VISIBLE : View.GONE);
}
- private static class FetchImageCallback extends Callback<Bitmap> {
- private SnippetArticleViewHolder mViewHolder;
- private final SnippetArticle mSnippet;
-
- public FetchImageCallback(
- SnippetArticleViewHolder viewHolder, SnippetArticle snippet) {
- mViewHolder = viewHolder;
- mSnippet = snippet;
- }
-
- @Override
- public void onResult(Bitmap image) {
- if (mViewHolder == null) return;
- mViewHolder.fadeThumbnailIn(mSnippet, image);
- }
-
- public void cancel() {
- // TODO(treib): Pass the "cancel" on to the actual image fetcher.
- mViewHolder = null;
- }
- }
-
private void cancelImageFetch() {
- if (mImageCallback != null) {
- mImageCallback.cancel();
- mImageCallback = null;
+ if (mImageCallback == null) return;
+ mImageCallback.cancel();
+ if (mArticle.isAssetDownload()) {
+ mThumbnailProvider.cancelRetrieval(mImageCallback);
}
+ mImageCallback = null;
}
private void fadeThumbnailIn(SnippetArticle snippet, Bitmap thumbnail) {
@@ -340,7 +391,10 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
Drawable[] layers = {mThumbnailView.getDrawable(),
new BitmapDrawable(mThumbnailView.getResources(), scaledThumbnail)};
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
+ mThumbnailView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ mThumbnailView.setBackground(null);
mThumbnailView.setImageDrawable(transitionDrawable);
+ mThumbnailView.setTint(null);
transitionDrawable.setCrossFadeEnabled(true);
transitionDrawable.startTransition(FADE_IN_ANIMATION_TIME_MS);
}
@@ -415,6 +469,41 @@ public class SnippetArticleViewHolder extends CardViewHolder implements Impressi
mPublisherTextView.setVisibility(View.VISIBLE);
}
+ private static class FetchImageCallback
+ extends Callback<Bitmap> implements ThumbnailProvider.ThumbnailRequest {
+ private SnippetArticleViewHolder mViewHolder;
+ private final SnippetArticle mSnippet;
+
+ public FetchImageCallback(SnippetArticleViewHolder viewHolder, SnippetArticle snippet) {
+ mViewHolder = viewHolder;
+ mSnippet = snippet;
+ }
+
+ @Override
+ public void onResult(Bitmap image) {
+ if (mViewHolder == null) return;
+ mViewHolder.fadeThumbnailIn(mSnippet, image);
+ }
+
+ @Override
+ public String getFilePath() {
+ return mSnippet == null ? null : mSnippet.getAssetDownloadFile().getAbsolutePath();
+ }
+
+ @Override
+ public void onThumbnailRetrieved(String filePath, Bitmap thumbnail) {
+ if (TextUtils.equals(getFilePath(), filePath) && thumbnail != null
+ && thumbnail.getWidth() > 0 && thumbnail.getHeight() > 0) {
+ onResult(thumbnail);
+ }
+ }
+
+ public void cancel() {
+ // TODO(treib): Pass the "cancel" on to the actual image fetcher.
+ mViewHolder = null;
+ }
+ }
+
/**
* Callback to refresh the offline badge visibility.
*/

Powered by Google App Engine
This is Rietveld 408576698