Chromium Code Reviews| 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 5a6bcef7a1d21fa39737df1b42d9a8a69ae7d939..e13d6c94361f49e2a14d709d4ff7b57fb8ee2acc 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 |
| @@ -12,18 +12,22 @@ import android.graphics.drawable.Drawable; |
| import android.graphics.drawable.TransitionDrawable; |
| import android.media.ThumbnailUtils; |
| import android.os.AsyncTask; |
| +import android.text.TextUtils; |
| import android.text.format.DateUtils; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| +import android.view.View.MeasureSpec; |
| import android.view.ViewGroup; |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| +import org.chromium.base.ApiCompatibilityUtils; |
| import org.chromium.base.Log; |
| import org.chromium.base.StreamUtil; |
| import org.chromium.base.metrics.RecordHistogram; |
| import org.chromium.base.metrics.RecordUserAction; |
| import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback; |
| import org.chromium.chrome.browser.ntp.NewTabPageUma; |
| import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; |
| import org.chromium.chrome.browser.ntp.cards.NewTabPageListItem; |
| @@ -31,6 +35,7 @@ import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder; |
| import java.io.IOException; |
| import java.io.InputStream; |
| +import java.net.MalformedURLException; |
| import java.net.URL; |
| /** |
| @@ -38,6 +43,7 @@ import java.net.URL; |
| */ |
| public class SnippetArticleViewHolder extends NewTabPageViewHolder implements View.OnClickListener { |
| private static final String TAG = "NtpSnippets"; |
| + private static final String PUBLISHER_FORMAT_STRING = "%s - %s"; |
| private static final int FADE_IN_ANIMATION_TIME_MS = 300; |
| private final NewTabPageManager mNewTabPageManager; |
| @@ -102,14 +108,16 @@ public class SnippetArticleViewHolder extends NewTabPageViewHolder implements Vi |
| SnippetArticle item = (SnippetArticle) article; |
| mHeadlineTextView.setText(item.mTitle); |
| - mPublisherTextView.setText( |
| + mPublisherTextView.setText(String.format(PUBLISHER_FORMAT_STRING, item.mPublisher, |
| DateUtils.getRelativeTimeSpanString(item.mTimestamp, System.currentTimeMillis(), |
| - DateUtils.MINUTE_IN_MILLIS)); |
| + DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE))); |
| + |
| mArticleSnippetTextView.setText(item.mPreviewText); |
| mUrl = item.mUrl; |
| mPosition = item.mPosition; |
| updateThumbnail(item); |
| + upadateFavicon(item); |
| } |
| private void updateThumbnail(final SnippetArticle snippet) { |
| @@ -177,6 +185,78 @@ public class SnippetArticleViewHolder extends NewTabPageViewHolder implements Vi |
| transitionDrawable.startTransition(FADE_IN_ANIMATION_TIME_MS); |
| } |
| + private void upadateFavicon(final SnippetArticle snippet) { |
|
Bernhard Bauer
2016/04/27 13:22:05
Nit: updateFavicon :)
Also, the final is unnecess
May
2016/04/27 16:45:08
Done.
|
| + // The favicon size should match the textview height |
| + int widthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); |
| + int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); |
| + mPublisherTextView.measure(widthSpec, heightSpec); |
| + fetchFavicon(snippet, mPublisherTextView.getHeight()); |
| + } |
| + |
| + // Fetch the favicon using the article's url first. If that fails, try to fetch the |
| + // favicon for the hostname |
| + private void fetchFavicon(final SnippetArticle snippet, final int faviconSizePx) { |
| + mNewTabPageManager.getLocalFaviconImageForURL( |
| + snippet.mUrl, faviconSizePx, new FaviconImageCallback() { |
| + @Override |
| + public void onFaviconAvailable(Bitmap image, String iconUrl) { |
| + if (image == null) { |
| + fetchFaviconForHostname(snippet.mUrl, faviconSizePx); |
| + } else { |
| + Drawable siteFavicon = new BitmapDrawable( |
| + mPublisherTextView.getContext().getResources(), image); |
| + siteFavicon.setBounds(0, 0, faviconSizePx, faviconSizePx); |
| + ApiCompatibilityUtils.setCompoundDrawablesRelative( |
| + mPublisherTextView, siteFavicon, null, null, null); |
| + mPublisherTextView.setVisibility(View.VISIBLE); |
| + } |
| + } |
| + }); |
| + } |
| + |
| + private void fetchFaviconForHostname(String urlStr, final int sizePx) { |
| + URL url = null; |
|
Bernhard Bauer
2016/04/27 13:22:05
I think it's more common to use java.net.URI when
May
2016/04/27 16:45:08
Done.
|
| + try { |
| + url = new URL(urlStr); |
| + } catch (MalformedURLException e) { |
| + drawDefaultFavicon(sizePx); |
| + return; |
| + } |
| + |
| + String origin = null; |
|
Bernhard Bauer
2016/04/27 13:22:05
I wouldn't call this origin if it's just protocol
May
2016/04/27 16:45:08
Not sure I understand the second part. We first tr
Bernhard Bauer
2016/04/28 14:19:20
What I meant was extracting the part that removes
May
2016/04/28 18:01:52
True, I removed the checks and now there's just on
|
| + if (url != null) origin = String.format("%s://%s", url.getProtocol(), url.getHost()); |
| + |
| + if (!TextUtils.isEmpty(origin)) { |
| + mNewTabPageManager.getLocalFaviconImageForURL( |
| + origin, sizePx, new FaviconImageCallback() { |
| + @Override |
| + public void onFaviconAvailable(Bitmap image, String iconUrl) { |
| + if (image == null) { |
| + drawDefaultFavicon(sizePx); |
| + } else { |
| + Drawable domainFavicon = new BitmapDrawable( |
|
Bernhard Bauer
2016/04/27 13:22:05
I think you could extract this into a shared metho
May
2016/04/27 16:45:07
Done.
|
| + mPublisherTextView.getContext().getResources(), image); |
| + domainFavicon.setBounds(0, 0, sizePx, sizePx); |
| + ApiCompatibilityUtils.setCompoundDrawablesRelative( |
| + mPublisherTextView, domainFavicon, null, null, null); |
| + mPublisherTextView.setVisibility(View.VISIBLE); |
| + } |
| + } |
| + }); |
| + } else { |
| + drawDefaultFavicon(sizePx); |
| + } |
| + } |
| + |
| + private void drawDefaultFavicon(int faviconSizePx) { |
| + Drawable newIcon = ApiCompatibilityUtils.getDrawable( |
| + mPublisherTextView.getContext().getResources(), R.drawable.default_favicon); |
| + newIcon.setBounds(0, 0, faviconSizePx, faviconSizePx); |
| + ApiCompatibilityUtils.setCompoundDrawablesRelative( |
| + mPublisherTextView, newIcon, null, null, null); |
| + mPublisherTextView.setVisibility(View.VISIBLE); |
| + } |
| + |
| @Override |
| public boolean isDismissable() { |
| return true; |