Bug 1220928 - Add remote client children. r=sebastian
authorChenxia Liu <liuche@mozilla.com>
Tue, 15 Mar 2016 15:51:56 -0700
changeset 329133 1139e8f7b278942800183d18d10ba17b937b6642
parent 329132 df8b8021d41939f362f013a70239d827d505dffd
child 329134 fe241494b578e688550de433b8b6d838863af7f8
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssebastian
bugs1220928
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1220928 - Add remote client children. r=sebastian MozReview-Commit-ID: F5DYHrR5p99
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryItem.java
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryRecyclerView.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/resources/layout/bookmark_folder_row.xml
mobile/android/base/resources/layout/home_combined_back_item.xml
mobile/android/base/resources/values/styles.xml
mobile/android/base/strings.xml.in
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
@@ -9,109 +9,157 @@ import android.support.v7.widget.Recycle
 import android.content.Context;
 import android.database.Cursor;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.RemoteClient;
+import org.mozilla.gecko.db.RemoteTab;
 
 import java.util.Collections;
+import java.util.ArrayList;
 import java.util.List;
 
 public class CombinedHistoryAdapter extends RecyclerView.Adapter<CombinedHistoryItem> {
     private static final String LOGTAG = "GeckoCombinedHistAdapt";
 
     public enum ItemType {
-        CLIENT, HISTORY;
+        CLIENT, HISTORY, NAVIGATION_BACK, CHILD;
 
         public static ItemType viewTypeToItemType(int viewType) {
             if (viewType >= ItemType.values().length) {
                 Log.e(LOGTAG, "No corresponding ItemType!");
             }
             return ItemType.values()[viewType];
         }
 
         public static int itemTypeToViewType(ItemType itemType) {
             return itemType.ordinal();
         }
     }
 
     private List<RemoteClient> remoteClients = Collections.emptyList();
+    private List<RemoteTab> clientChildren;
     private Cursor historyCursor;
     private final Context context;
 
+    private boolean inChildView = false;
+
     public CombinedHistoryAdapter(Context context) {
         super();
         this.context = context;
     }
 
     public void setClients(List<RemoteClient> clients) {
         remoteClients = clients;
         notifyDataSetChanged();
     }
 
     public void setHistory(Cursor history) {
         historyCursor = history;
         notifyDataSetChanged();
     }
 
+    public void showChildView(int parentPosition) {
+        if (clientChildren == null) {
+            clientChildren = new ArrayList<>();
+        }
+        // Handle "back" view.
+        clientChildren.add(null);
+        clientChildren.addAll(remoteClients.get(transformPosition(ItemType.CLIENT, parentPosition)).tabs);
+        inChildView = true;
+        notifyDataSetChanged();
+    }
+
+    public void exitChildView() {
+        inChildView = false;
+        clientChildren.clear();
+        notifyDataSetChanged();
+    }
+
     private int transformPosition(ItemType type, int position) {
         if (type == ItemType.CLIENT) {
             return position;
+        } else if (type == ItemType.HISTORY){
+            return position - remoteClients.size();
         } else {
-            return position - remoteClients.size();
+            return position;
         }
     }
 
     @Override
     public CombinedHistoryItem onCreateViewHolder(ViewGroup viewGroup, int viewType) {
         final LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
         final View view;
 
         final ItemType itemType = ItemType.viewTypeToItemType(viewType);
 
         switch (itemType) {
             case CLIENT:
                 view = inflater.inflate(R.layout.home_remote_tabs_group, viewGroup, false);
                 return new CombinedHistoryItem.ClientItem(view);
+
+            case NAVIGATION_BACK:
+                view = inflater.inflate(R.layout.home_combined_back_item, viewGroup, false);
+                return new CombinedHistoryItem.HistoryItem(view);
+
+            case CHILD:
             case HISTORY:
                 view = inflater.inflate(R.layout.home_item_row, viewGroup, false);
                 return new CombinedHistoryItem.HistoryItem(view);
             default:
                 throw new IllegalArgumentException("Unexpected Home Panel item type");
         }
     }
 
     @Override
     public int getItemViewType(int position) {
-        final int numClients = remoteClients.size();
-        return (position < numClients) ? ItemType.itemTypeToViewType(ItemType.CLIENT) : ItemType.itemTypeToViewType(ItemType.HISTORY);
+        if (inChildView) {
+            if (position == 0) {
+                return ItemType.itemTypeToViewType(ItemType.NAVIGATION_BACK);
+            } else {
+                return ItemType.itemTypeToViewType(ItemType.CHILD);
+            }
+        } else {
+            final int numClients = remoteClients.size();
+            return (position < numClients) ? ItemType.itemTypeToViewType(ItemType.CLIENT) : ItemType.itemTypeToViewType(ItemType.HISTORY);
+        }
     }
 
     @Override
     public int getItemCount() {
-        final int remoteSize = remoteClients.size();
-        final int historySize = historyCursor == null ? 0 : historyCursor.getCount();
-        return remoteSize + historySize;
+
+        if (inChildView) {
+            return (clientChildren == null) ? 0 : clientChildren.size();
+        } else {
+            final int remoteSize = remoteClients.size();
+            final int historySize = historyCursor == null ? 0 : historyCursor.getCount();
+            return remoteSize + historySize;
+        }
     }
 
     @Override
     public void onBindViewHolder(CombinedHistoryItem viewHolder, int position) {
         final ItemType itemType = ItemType.viewTypeToItemType(getItemViewType(position));
         final int localPosition = transformPosition(itemType, position);
 
         switch (itemType) {
             case CLIENT:
                 final CombinedHistoryItem.ClientItem clientItem = (CombinedHistoryItem.ClientItem) viewHolder;
                 final RemoteClient client = remoteClients.get(localPosition);
                 clientItem.bind(client, context);
                 break;
 
+            case CHILD:
+                RemoteTab remoteTab = clientChildren.get(position);
+                ((CombinedHistoryItem.HistoryItem) viewHolder).bind(remoteTab);
+                break;
+
             case HISTORY:
                 if (historyCursor == null || !historyCursor.moveToPosition(localPosition)) {
                     throw new IllegalStateException("Couldn't move cursor to position " + localPosition);
                 }
                 ((CombinedHistoryItem.HistoryItem) viewHolder).bind(historyCursor);
                 break;
         }
     }
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryItem.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryItem.java
@@ -9,32 +9,39 @@ import android.database.Cursor;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.widget.RecyclerView;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
 import org.mozilla.gecko.db.RemoteClient;
+import org.mozilla.gecko.db.RemoteTab;
 
 public abstract class CombinedHistoryItem extends RecyclerView.ViewHolder {
     public CombinedHistoryItem(View view) {
         super(view);
     }
 
     public static class HistoryItem extends CombinedHistoryItem {
         public HistoryItem(View view) {
             super(view);
         }
 
         public void bind(Cursor historyCursor) {
             final TwoLinePageRow pageRow = (TwoLinePageRow) this.itemView;
             pageRow.setShowIcons(true);
             pageRow.updateFromCursor(historyCursor);
         }
+
+        public void bind(RemoteTab remoteTab) {
+            final TwoLinePageRow childPageRow = (TwoLinePageRow) this.itemView;
+            childPageRow.setShowIcons(true);
+            childPageRow.update(remoteTab.title, remoteTab.url);
+        }
     }
 
     public static class ClientItem extends CombinedHistoryItem {
         final TextView nameView;
         final ImageView deviceTypeView;
         final TextView lastModifiedView;
 
         public ClientItem(View view) {
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryRecyclerView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryRecyclerView.java
@@ -52,24 +52,29 @@ public class CombinedHistoryRecyclerView
 
     @Override
     public void onItemClicked(RecyclerView recyclerView, int position, View v) {
         final int viewType = getAdapter().getItemViewType(position);
         final CombinedHistoryAdapter.ItemType itemType = CombinedHistoryAdapter.ItemType.viewTypeToItemType(viewType);
 
         switch(itemType) {
             case CLIENT:
-                // TODO: open new panel with all the remote children, and hide all the other items
-                return;
+                ((CombinedHistoryAdapter) getAdapter()).showChildView(position);
+                break;
+            case NAVIGATION_BACK:
+                ((CombinedHistoryAdapter) getAdapter()).exitChildView();
+                break;
+            case CHILD:
             case HISTORY:
                 if (mOnUrlOpenListener != null) {
                     final TwoLinePageRow historyItem = (TwoLinePageRow) v;
                     Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "history");
                     mOnUrlOpenListener.onUrlOpen(historyItem.getUrl(), EnumSet.of(HomePager.OnUrlOpenListener.Flags.ALLOW_SWITCH_TO_TAB));
                 }
+                break;
         }
     }
 
     @Override
     public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) {
         // TODO: open context menu if not a date title
         return showContextMenuForChild(this);
     }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -518,16 +518,17 @@ size. -->
 <!-- Localization note (home_top_sites_add): This string is used as placeholder
      text underneath empty thumbnails in the Top Sites page on about:home. -->
 <!ENTITY home_top_sites_add "Add a site">
 
 <!-- Localization note (home_title): This string should be kept in sync
      with the page title defined in aboutHome.dtd -->
 <!ENTITY home_title "&brandShortName; Home">
 <!ENTITY home_history_title "History">
+<!ENTITY home_history_back_to "Go back to all history">
 <!ENTITY home_clear_history_button "Clear browsing history">
 <!ENTITY home_clear_history_confirm "Are you sure you want to clear your history?">
 <!ENTITY home_bookmarks_empty "Bookmarks you save show up here.">
 <!ENTITY home_closed_tabs_title "Recently closed tabs">
 <!ENTITY home_last_tabs_title "Tabs from last time">
 <!ENTITY home_last_tabs_empty "Your recent tabs show up here.">
 <!ENTITY home_open_all "Open all">
 <!ENTITY home_most_recent_empty "Websites you visited most recently show up here.">
--- a/mobile/android/base/resources/layout/bookmark_folder_row.xml
+++ b/mobile/android/base/resources/layout/bookmark_folder_row.xml
@@ -1,11 +1,10 @@
 <?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.home.BookmarkFolderView xmlns:android="http://schemas.android.com/apk/res/android"
-                                           style="@style/Widget.BookmarkFolderView"
+                                           style="@style/Widget.FolderView"
                                            android:layout_width="match_parent"
-                                           android:layout_height="@dimen/page_group_height"
-                                           android:minHeight="@dimen/page_group_height"
+                                           android:drawableLeft="@drawable/bookmark_folder"
                                            android:gravity="center_vertical"/>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/layout/home_combined_back_item.xml
@@ -0,0 +1,11 @@
+<?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/. -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          style="@style/Widget.FolderView"
+          android:layout_width="match_parent"
+          android:text="@string/home_history_back_to"
+          android:drawableLeft="@drawable/arrow_up"
+          android:gravity="center_vertical"/>
--- a/mobile/android/base/resources/values/styles.xml
+++ b/mobile/android/base/resources/values/styles.xml
@@ -158,23 +158,24 @@
     <style name="Widget.ReadingListRow.Description.Unread" parent="Widget.ReadingListRow.Description">
         <item name="android:textColor">@color/text_and_tabs_tray_grey</item>
     </style>
 
     <style name="Widget.ReadingListRow.ReadTime">
         <item name="android:textColor">@color/fennec_ui_orange</item>
     </style>
 
-    <style name="Widget.BookmarkFolderView" parent="Widget.TwoLinePageRow.Title">
+    <style name="Widget.FolderView" parent="Widget.TwoLinePageRow.Title">
+        <item name="android:layout_height">@dimen/page_group_height</item>
+        <item name="android:minHeight">@dimen/page_group_height</item>
         <item name="android:singleLine">true</item>
         <item name="android:ellipsize">none</item>
         <item name="android:background">@color/about_page_header_grey</item>
         <item name="android:paddingLeft">20dp</item>
         <item name="android:drawablePadding">20dp</item>
-        <item name="android:drawableLeft">@drawable/bookmark_folder</item>
     </style>
 
     <style name="Widget.PanelItemView" />
 
     <style name="Widget.PanelItemView.Title">
         <item name="android:textAppearance">@style/TextAppearance.Widget.Home.ItemTitle</item>
         <item name="android:maxLines">2</item>
         <item name="android:ellipsize">end</item>
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -420,16 +420,17 @@
   <string name="button_yes">&button_yes;</string>
   <string name="button_no">&button_no;</string>
   <string name="button_copy">&button_copy;</string>
 
   <string name="home_title">&home_title;</string>
   <string name="home_top_sites_title">&home_top_sites_title;</string>
   <string name="home_top_sites_add">&home_top_sites_add;</string>
   <string name="home_history_title">&home_history_title;</string>
+  <string name="home_history_back_to">&home_history_back_to;</string>
   <string name="home_clear_history_button">&home_clear_history_button;</string>
   <string name="home_clear_history_confirm">&home_clear_history_confirm;</string>
   <string name="home_bookmarks_empty">&home_bookmarks_empty;</string>
   <string name="home_closed_tabs_title">&home_closed_tabs_title;</string>
   <string name="home_last_tabs_title">&home_last_tabs_title;</string>
   <string name="home_last_tabs_empty">&home_last_tabs_empty;</string>
   <string name="home_open_all">&home_open_all;</string>
   <string name="home_most_recent_empty">&home_most_recent_empty;</string>