Bug 1406338 - Part 2: Show favicons in tabs tray page. r?nechen draft
authorJing-wei Wu <topwu.tw@gmail.com>
Mon, 09 Oct 2017 11:02:52 +0800
changeset 676598 10352df8f7180858682e8525dafd6138d447bcef
parent 676597 5b6ca7b000ecc0921f00597e50f3a6e740c8e3fc
child 676622 fcef77e81b969fcc07d523509422cb7589a2eec2
push id83540
push userbmo:topwu.tw@gmail.com
push dateMon, 09 Oct 2017 03:04:13 +0000
reviewersnechen
bugs1406338
milestone58.0a1
Bug 1406338 - Part 2: Show favicons in tabs tray page. r?nechen MozReview-Commit-ID: BXOFuxwI0sl
mobile/android/app/src/main/res/layout-large/tabs_layout_item_view.xml
mobile/android/app/src/main/res/layout/tabs_layout_item_view.xml
mobile/android/app/src/main/res/layout/tabs_list_item_view.xml
mobile/android/app/src/photon/res/values-v17/styles.xml
mobile/android/app/src/photon/res/values/dimens.xml
mobile/android/app/src/photon/res/values/styles.xml
mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
--- a/mobile/android/app/src/main/res/layout-large/tabs_layout_item_view.xml
+++ b/mobile/android/app/src/main/res/layout-large/tabs_layout_item_view.xml
@@ -15,45 +15,57 @@
     <LinearLayout android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal"
                   android:duplicateParentState="true"
                   android:paddingLeft="@dimen/tab_highlight_stroke_width"
                   android:paddingRight="@dimen/tab_highlight_stroke_width"
                   android:paddingBottom="@dimen/tab_highlight_stroke_width">
 
-       <org.mozilla.gecko.widget.FadedSingleColorTextView
-               android:id="@+id/title"
-               android:layout_width="0dip"
-               android:layout_height="wrap_content"
-               android:layout_weight="1.0"
-               style="@style/TabLayoutItemTextAppearance"
-               android:textSize="14sp"
-               android:textColor="@color/tab_item_title"
-               android:singleLine="true"
-               android:duplicateParentState="true"
-               gecko:fadeWidth="15dp"
-               android:paddingRight="5dp"
-               android:paddingEnd="5dp"
-               android:paddingLeft="0dp"
-               android:paddingStart="0dp"
-               android:drawablePadding="6dp"/>
+        <org.mozilla.gecko.widget.FaviconView
+            android:id="@+id/favicon"
+            style="@style/TabsLayoutItemFavicon"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_gravity="center_vertical"
+            android:scaleType="centerInside"
+            gecko:dominantBorderEnabled="false"
+            gecko:overrideScaleType="false"/>
+
+        <org.mozilla.gecko.widget.FadedSingleColorTextView
+            android:id="@+id/title"
+            style="@style/TabLayoutItemTextAppearance"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1.0"
+            android:layout_gravity="center_vertical"
+            android:drawablePadding="6dp"
+            android:duplicateParentState="true"
+            android:paddingEnd="5dp"
+            android:paddingLeft="0dp"
+            android:paddingRight="5dp"
+            android:paddingStart="0dp"
+            android:singleLine="true"
+            android:textColor="@color/tab_item_title"
+            android:textSize="14sp"
+            gecko:fadeWidth="15dp"/>
 
         <!-- Use of baselineAlignBottom only supported from API 11+ - if this needs to work on lower API versions
              we'll need to override getBaseLine() and return image height, but we assume this won't happen -->
-        <ImageView android:id="@+id/close"
-                     style="@style/TabsItemClose"
-                     android:layout_width="wrap_content"
-                     android:layout_height="wrap_content"
-                     android:scaleType="center"
-                     android:baselineAlignBottom="true"
-                     android:background="@android:color/transparent"
-                     android:contentDescription="@string/close_tab"
-                     android:src="@drawable/tab_item_close_button"
-                     android:duplicateParentState="true"/>
+        <ImageView
+            android:id="@+id/close"
+            style="@style/TabsItemClose"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:contentDescription="@string/close_tab"
+            android:duplicateParentState="true"
+            android:scaleType="center"
+            android:src="@drawable/tab_item_close_button"/>
 
     </LinearLayout>
 
     <!-- We set state_private on this View dynamically in TabsGridLayout. -->
     <org.mozilla.gecko.widget.TabThumbnailWrapper
             android:id="@+id/wrapper"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
--- a/mobile/android/app/src/main/res/layout/tabs_layout_item_view.xml
+++ b/mobile/android/app/src/main/res/layout/tabs_layout_item_view.xml
@@ -15,45 +15,55 @@
     <LinearLayout android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:orientation="horizontal"
                   android:duplicateParentState="true"
                   android:paddingLeft="@dimen/tab_highlight_stroke_width"
                   android:paddingRight="@dimen/tab_highlight_stroke_width"
                   android:paddingBottom="@dimen/tab_highlight_stroke_width">
 
-       <org.mozilla.gecko.widget.FadedSingleColorTextView
-               android:id="@+id/title"
-               android:layout_width="0dip"
-               android:layout_height="wrap_content"
-               android:layout_weight="1.0"
-               style="@style/TabLayoutItemTextAppearance"
-               android:textSize="14sp"
-               android:textColor="@color/tab_item_title"
-               android:singleLine="true"
-               android:duplicateParentState="true"
-               gecko:fadeWidth="15dp"
-               android:paddingRight="5dp"
-               android:paddingEnd="5dp"
-               android:paddingLeft="0dp"
-               android:paddingStart="0dp"
-               android:drawablePadding="6dp"/>
+        <org.mozilla.gecko.widget.FaviconView
+            android:id="@+id/favicon"
+            style="@style/TabsLayoutItemFavicon"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:layout_gravity="center_vertical"
+            android:scaleType="centerInside"
+            gecko:dominantBorderEnabled="false"
+            gecko:overrideScaleType="false"/>
 
-        <!-- Use of baselineAlignBottom only supported from API 11+ - if this needs to work on lower API versions
-             we'll need to override getBaseLine() and return image height, but we assume this won't happen -->
-        <ImageView android:id="@+id/close"
-                     style="@style/TabsItemClose"
-                     android:layout_width="wrap_content"
-                     android:layout_height="wrap_content"
-                     android:scaleType="center"
-                     android:baselineAlignBottom="true"
-                     android:background="@android:color/transparent"
-                     android:contentDescription="@string/close_tab"
-                     android:src="@drawable/tab_item_close_button"
-                     android:duplicateParentState="true"/>
+        <org.mozilla.gecko.widget.FadedSingleColorTextView
+            android:id="@+id/title"
+            style="@style/TabLayoutItemTextAppearance"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_weight="1.0"
+            android:drawablePadding="6dp"
+            android:duplicateParentState="true"
+            android:paddingEnd="5dp"
+            android:paddingLeft="0dp"
+            android:paddingRight="5dp"
+            android:paddingStart="0dp"
+            android:singleLine="true"
+            android:textColor="@color/tab_item_title"
+            android:textSize="14sp"
+            gecko:fadeWidth="15dp"/>
+
+        <ImageView
+            android:id="@+id/close"
+            style="@style/TabsItemClose"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:contentDescription="@string/close_tab"
+            android:duplicateParentState="true"
+            android:scaleType="center"
+            android:src="@drawable/tab_item_close_button"/>
 
     </LinearLayout>
 
     <!-- We set state_private on this View dynamically in TabsGridLayout. -->
     <org.mozilla.gecko.widget.TabThumbnailWrapper
             android:id="@+id/wrapper"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
--- a/mobile/android/app/src/main/res/layout/tabs_list_item_view.xml
+++ b/mobile/android/app/src/main/res/layout/tabs_list_item_view.xml
@@ -1,72 +1,69 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <org.mozilla.gecko.tabs.TabsLayoutItemView xmlns:android="http://schemas.android.com/apk/res/android"
+                                           xmlns:gecko="http://schemas.android.com/apk/res-auto"
                                            style="@style/TabsItem"
                                            android:focusable="true"
                                            android:id="@+id/info"
                                            android:layout_width="match_parent"
                                            android:layout_height="wrap_content"
                                            android:paddingLeft="12dip"
                                            android:paddingStart="12dip"
                                            android:paddingRight="0dip"
                                            android:paddingEnd="0dip"
                                            android:paddingTop="6dip"
                                            android:paddingBottom="6dip"
                                            android:background="@drawable/tab_row">
 
     <!-- We set state_private on this View dynamically in TabsListLayout. -->
     <org.mozilla.gecko.widget.TabThumbnailWrapper
-            android:id="@+id/wrapper"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:padding="4dip"
-            android:background="@drawable/tab_thumbnail"
-            android:duplicateParentState="true"
-            android:clipToPadding="false">
+        android:id="@+id/wrapper"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:padding="4dip"
+        android:background="@drawable/tab_thumbnail"
+        android:duplicateParentState="true"
+        android:clipToPadding="false">
 
         <org.mozilla.gecko.tabs.TabsPanelThumbnailView
             android:id="@+id/thumbnail"
             android:layout_width="137dp"
             android:layout_height="wrap_content"/>
 
     </org.mozilla.gecko.widget.TabThumbnailWrapper>
 
-    <LinearLayout android:layout_width="0dip"
-                  android:layout_height="match_parent"
-                  android:orientation="vertical"
-                  android:layout_weight="1.0"
-                  android:paddingTop="4dip"
-                  android:paddingLeft="10dp"
-                  android:paddingStart="10dp"
-                  android:paddingRight="2dp"
-                  android:paddingEnd="4dip"
-                  android:duplicateParentState="true">
+    <org.mozilla.gecko.widget.FaviconView
+        android:id="@+id/favicon"
+        style="@style/TabsListItemFavicon"
+        android:layout_width="16dp"
+        android:layout_height="16dp"
+        android:layout_gravity="center_vertical"
+        android:scaleType="centerInside"
+        gecko:dominantBorderEnabled="false"
+        gecko:overrideScaleType="false"/>
 
-        <TextView android:id="@+id/title"
-                  android:layout_width="match_parent"
-                  android:layout_height="0dip"
-                  android:layout_weight="1.0"
-                  style="@style/TabLayoutItemTextAppearance"
-                  android:textColor="@color/tab_item_title"
-                  android:textSize="14sp"
-                  android:gravity="center_vertical"
-                  android:singleLine="false"
-                  android:maxLines="4"
-                  android:drawablePadding="6dp"
-                  android:duplicateParentState="true"/>
-
-    </LinearLayout>
+    <TextView android:id="@+id/title"
+              android:layout_width="0dp"
+              android:layout_height="wrap_content"
+              android:layout_weight="1"
+              style="@style/TabLayoutItemTextAppearance"
+              android:textColor="@color/tab_item_title"
+              android:textSize="14sp"
+              android:layout_gravity="center_vertical"
+              android:singleLine="false"
+              android:maxLines="4"
+              android:duplicateParentState="true"/>
 
     <ImageView android:id="@+id/close"
-                 style="@style/TabsItemClose"
-                 android:layout_width="34dip"
-                 android:layout_height="match_parent"
-                 android:scaleType="center"
-                 android:contentDescription="@string/close_tab"
-                 android:src="@drawable/tab_item_close_button"
-                 android:duplicateParentState="true"/>
+               style="@style/TabsItemClose"
+               android:layout_width="34dip"
+               android:layout_height="match_parent"
+               android:contentDescription="@string/close_tab"
+               android:duplicateParentState="true"
+               android:scaleType="center"
+               android:src="@drawable/tab_item_close_button"/>
 
 </org.mozilla.gecko.tabs.TabsLayoutItemView>
\ No newline at end of file
--- a/mobile/android/app/src/photon/res/values-v17/styles.xml
+++ b/mobile/android/app/src/photon/res/values-v17/styles.xml
@@ -76,16 +76,25 @@
         <item name="android:layout_alignEnd">@id/url_bar_entry</item>
     </style>
 
     <style name="UrlBar.QRCode" parent="UrlBar.V17.QRCode"/>
     <style name="UrlBar.V17.QRCode" parent="UrlBar.ImageButton">
         <item name="android:layout_marginRight">-3dp</item>
     </style>
 
+    <style name="TabsLayoutItemFavicon">
+        <item name="android:layout_marginEnd">4dp</item>
+    </style>
+
+    <style name="TabsListItemFavicon">
+        <item name="android:layout_marginStart">10dp</item>
+        <item name="android:layout_marginEnd">6dp</item>
+    </style>
+
     <style name="TabsTray.AddTab" parent="TabsTray.V17.AddTab" />
     <style name="TabsTray.V17.AddTab" parent="TabsTray.Base.AddTab">
         <item name="android:layout_marginEnd">-3dp</item>
     </style>
 
     <style name="TabsTray.Menu" parent="TabsTray.V17.Menu" />
     <style name="TabsTray.V17.Menu" parent="TabsTray.Base.Menu"/>
 
--- a/mobile/android/app/src/photon/res/values/dimens.xml
+++ b/mobile/android/app/src/photon/res/values/dimens.xml
@@ -170,16 +170,18 @@
     <!-- CompactTabsGridLayout -->
     <dimen name="tab_panel_grid_hpadding_compact">15dp</dimen>
     <dimen name="tab_panel_grid_vpadding_compact">7dp</dimen>
     <dimen name="tab_panel_grid_item_hpadding_compact">10dp</dimen>
     <dimen name="tab_panel_grid_item_vpadding_compact">6dp</dimen>
 
     <!-- TabsListLayout -->
     <dimen name="tab_highlight_stroke_width">5dp</dimen>
+    <dimen name="tab_favicon_size">16dp</dimen>
+    <dimen name="tab_favicon_text_size">12sp</dimen>
 
     <!-- PageActionButtons dimensions -->
     <dimen name="page_action_button_width">@dimen/browser_toolbar_image_button_width</dimen>
 
     <!-- Banner -->
     <dimen name="home_banner_height">72dp</dimen>
     <dimen name="home_banner_close_width">42dp</dimen>
     <dimen name="home_banner_icon_height">48dip</dimen>
--- a/mobile/android/app/src/photon/res/values/styles.xml
+++ b/mobile/android/app/src/photon/res/values/styles.xml
@@ -513,16 +513,25 @@
     <style name="TabsItem">
          <item name="android:nextFocusRight">@+id/close</item>
     </style>
 
     <style name="TabsItemClose">
          <item name="android:nextFocusLeft">@+id/info</item>
     </style>
 
+    <style name="TabsLayoutItemFavicon">
+        <item name="android:layout_marginRight">4dp</item>
+    </style>
+
+    <style name="TabsListItemFavicon">
+        <item name="android:layout_marginLeft">10dp</item>
+        <item name="android:layout_marginRight">6dp</item>
+    </style>
+
     <style name="Widget.RemoteTabsItemView" parent="Widget.TwoLinePageRow"/>
 
     <style name="Widget.RemoteTabsClientView" parent="Widget.TwoLinePageRow">
         <item name="android:background">@color/about_page_header_grey</item>
     </style>
 
     <style name="Widget.RemoteTabsListView" parent="Widget.HomeListView">
         <item name="android:childDivider">@color/toolbar_divider_grey</item>
--- a/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabs/TabsLayoutItemView.java
@@ -2,48 +2,56 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabs;
 
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.icons.IconResponse;
+import org.mozilla.gecko.icons.Icons;
+import org.mozilla.gecko.widget.FaviconView;
 import org.mozilla.gecko.widget.HoverDelegateWithReset;
 import org.mozilla.gecko.widget.TabThumbnailWrapper;
 import org.mozilla.gecko.widget.TouchDelegateWithReset;
 import org.mozilla.gecko.widget.themed.ThemedRelativeLayout;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.support.v4.widget.TextViewCompat;
 import android.support.v7.widget.ViewUtils;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import java.util.concurrent.Future;
+
 public class TabsLayoutItemView extends LinearLayout
                                 implements Checkable {
     private static final String LOGTAG = "Gecko" + TabsLayoutItemView.class.getSimpleName();
     private static final int[] STATE_CHECKED = { android.R.attr.state_checked };
     private boolean mChecked;
 
     private int mTabId;
     private TextView mTitle;
     private TabsPanelThumbnailView mThumbnail;
     private ImageView mCloseButton;
     private TabThumbnailWrapper mThumbnailWrapper;
     private HoverDelegateWithReset mHoverDelegate;
 
+    private FaviconView mFaviconView;
+    private Future<IconResponse> mOngoingIconLoad;
+
     public TabsLayoutItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     @Override
     public int[] onCreateDrawableState(int extraSpace) {
         final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
 
@@ -93,16 +101,17 @@ public class TabsLayoutItemView extends 
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTitle = (TextView) findViewById(R.id.title);
         mThumbnail = (TabsPanelThumbnailView) findViewById(R.id.thumbnail);
         mCloseButton = (ImageView) findViewById(R.id.close);
         mThumbnailWrapper = (TabThumbnailWrapper) findViewById(R.id.wrapper);
+        mFaviconView = (FaviconView) findViewById(R.id.favicon);
 
         growCloseButtonHitArea();
     }
 
     private void growCloseButtonHitArea() {
         addOnLayoutChangeListener(new OnLayoutChangeListener() {
             @Override
             public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
@@ -164,22 +173,37 @@ public class TabsLayoutItemView extends 
             mThumbnailWrapper.setRecording(tab.isRecording());
         }
 
         final String tabTitle = tab.getDisplayTitle();
         mTitle.setText(tabTitle);
         mCloseButton.setTag(this);
 
         if (tab.isAudioPlaying()) {
-            TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(mTitle, R.drawable.tab_audio_playing, 0, 0, 0);
+            mFaviconView.setImageResource(R.drawable.tab_audio_playing);
             final String tabTitleWithAudio =
                     getResources().getString(R.string.tab_title_prefix_is_playing_audio, tabTitle);
             mTitle.setContentDescription(tabTitleWithAudio);
         } else {
-            TextViewCompat.setCompoundDrawablesRelative(mTitle, null, null, null, null);
+            if (mOngoingIconLoad != null) {
+                mOngoingIconLoad.cancel(true);
+            }
+
+            final Resources resources = getResources();
+            final int iconSize = resources.getDimensionPixelSize(R.dimen.tab_favicon_size);
+            final float textSize = resources.getDimensionPixelSize(R.dimen.tab_favicon_text_size);
+
+            mOngoingIconLoad = Icons.with(getContext())
+                                       .pageUrl(tab.getURL())
+                                       .skipNetwork()
+                                       .targetSize(iconSize)
+                                       .textSize(textSize)
+                                       .build()
+                                       .execute(mFaviconView.createIconCallback());
+
             mTitle.setContentDescription(tabTitle);
         }
     }
 
     public int getTabId() {
         return mTabId;
     }