Bug 1220928 - Add remote client children. r=sebastian draft
authorChenxia Liu <liuche@mozilla.com>
Tue, 15 Mar 2016 15:51:56 -0700
changeset 346108 dee19234fb4bc6795cdbb06382181007e3e7f9b3
parent 346107 37023c0517882ce9d8f01a9c87b271c1cc01d4bc
child 346109 567394c3e728f6e85a20d0c989f78faf834f1c97
push id14243
push usercliu@mozilla.com
push dateWed, 30 Mar 2016 23:23:30 +0000
reviewerssebastian
bugs1220928
milestone48.0a1
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>