Bug 1261527 - Remove RemoteTabsExpandableListAdapter after extracting static methods. r=sebastian, a=lizzard
authorChenxia Liu <liuche@mozilla.com>
Wed, 27 Apr 2016 17:38:07 -0700
changeset 334726 fa7318ff115f45b9c9cabb51324981c6c624adec
parent 334725 7e7a0d76f09c4f1dcdf85c274bd8f04b90abd550
child 334727 bd4d5fe4e576aebca4b405f724286d23299d1ef5
push id1146
push userCallek@gmail.com
push dateMon, 25 Jul 2016 16:35:44 +0000
treeherdermozilla-release@a55778f9cd5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssebastian, lizzard
bugs1261527
milestone48.0a2
Bug 1261527 - Remove RemoteTabsExpandableListAdapter after extracting static methods. r=sebastian, a=lizzard MozReview-Commit-ID: Ae5oEbK2QYn
mobile/android/base/java/org/mozilla/gecko/RemoteTabsExpandableListAdapter.java
mobile/android/base/java/org/mozilla/gecko/db/RemoteTab.java
mobile/android/base/java/org/mozilla/gecko/home/ClientsAdapter.java
mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryItem.java
mobile/android/base/moz.build
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/RemoteTabsExpandableListAdapter.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/* 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/. */
-
-package org.mozilla.gecko;
-
-
-
-import android.support.v4.content.ContextCompat;
-import android.text.format.DateUtils;
-import org.mozilla.gecko.db.RemoteClient;
-import org.mozilla.gecko.db.RemoteTab;
-import org.mozilla.gecko.home.TwoLinePageRow;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-/**
- * An adapter that populates group and child views with remote client and tab
- * data maintained in a monolithic static array.
- * <p>
- * The group and child view resources are parameters to allow future
- * specialization to home fragment styles.
- */
-public class RemoteTabsExpandableListAdapter extends BaseExpandableListAdapter {
-    /**
-     * If a device claims to have synced before this date, we will assume it has never synced.
-     */
-    private static final Date EARLIEST_VALID_SYNCED_DATE;
-    static {
-        final Calendar c = GregorianCalendar.getInstance();
-        c.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
-        EARLIEST_VALID_SYNCED_DATE = c.getTime();
-    }
-    protected final ArrayList<RemoteClient> clients;
-    private final boolean showGroupIndicator;
-    protected int groupLayoutId;
-    protected int childLayoutId;
-
-    public static class GroupViewHolder {
-        final TextView nameView;
-        final TextView lastModifiedView;
-        final ImageView deviceTypeView;
-        final ImageView deviceExpandedView;
-
-        public GroupViewHolder(View view) {
-            nameView = (TextView) view.findViewById(R.id.client);
-            lastModifiedView = (TextView) view.findViewById(R.id.last_synced);
-            deviceTypeView = (ImageView) view.findViewById(R.id.device_type);
-            deviceExpandedView = (ImageView) view.findViewById(R.id.device_expanded);
-        }
-    }
-
-    /**
-     * Construct a new adapter.
-     * <p>
-     * It's fine to create with clients to be null, and then to use
-     * {@link RemoteTabsExpandableListAdapter#replaceClients(List)} to
-     * update this list of clients.
-     *
-     * @param groupLayoutId
-     * @param childLayoutId
-     * @param clients
-     *            initial list of clients; can be null.
-     * @param showGroupIndicator
-     */
-    public RemoteTabsExpandableListAdapter(int groupLayoutId, int childLayoutId, List<RemoteClient> clients, boolean showGroupIndicator) {
-        this.groupLayoutId = groupLayoutId;
-        this.childLayoutId = childLayoutId;
-        this.clients = new ArrayList<>();
-        if (clients != null) {
-            this.clients.addAll(clients);
-        }
-        this.showGroupIndicator = showGroupIndicator;
-    }
-
-    public void replaceClients(List<RemoteClient> clients) {
-        this.clients.clear();
-        if (clients != null) {
-            this.clients.addAll(clients);
-            this.notifyDataSetChanged();
-        } else {
-            this.notifyDataSetInvalidated();
-        }
-    }
-
-    @Override
-    public boolean hasStableIds() {
-        return false; // Client GUIDs are stable, but tab hashes are not.
-    }
-
-    @Override
-    public long getGroupId(int groupPosition) {
-        return clients.get(groupPosition).guid.hashCode();
-    }
-
-    @Override
-    public int getGroupCount() {
-        return clients.size();
-    }
-
-    @Override
-    public Object getGroup(int groupPosition) {
-        return clients.get(groupPosition);
-    }
-
-    @Override
-    public int getChildrenCount(int groupPosition) {
-        return clients.get(groupPosition).tabs.size();
-    }
-
-    @Override
-    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
-        final Context context = parent.getContext();
-        final View view;
-        if (convertView != null) {
-            view = convertView;
-        } else {
-            final LayoutInflater inflater = LayoutInflater.from(context);
-            view = inflater.inflate(groupLayoutId, parent, false);
-            final GroupViewHolder holder = new GroupViewHolder(view);
-            view.setTag(holder);
-        }
-
-        final RemoteClient client = clients.get(groupPosition);
-        updateClientsItemView(isExpanded, context, view, client);
-
-        return view;
-    }
-
-    public void updateClientsItemView(final boolean isExpanded, final Context context, final View view, final RemoteClient client) {
-        final GroupViewHolder holder = (GroupViewHolder) view.getTag();
-
-        // UI elements whose state depends on isExpanded, roughly from left to
-        // right: device type icon; client name text color; expanded state
-        // indicator.
-        final int deviceTypeResId;
-        final int textColorResId;
-        final int deviceExpandedResId;
-
-        if (isExpanded && !client.tabs.isEmpty()) {
-            deviceTypeResId = "desktop".equals(client.deviceType) ? R.drawable.sync_desktop : R.drawable.sync_mobile;
-            textColorResId = R.color.placeholder_active_grey;
-            deviceExpandedResId = showGroupIndicator ? R.drawable.arrow_down : R.drawable.home_group_collapsed;
-        } else {
-            deviceTypeResId = "desktop".equals(client.deviceType) ? R.drawable.sync_desktop_inactive : R.drawable.sync_mobile_inactive;
-            textColorResId = R.color.tabs_tray_icon_grey;
-            deviceExpandedResId = showGroupIndicator ? R.drawable.home_group_collapsed : 0;
-        }
-
-        // Now update the UI.
-        holder.nameView.setText(client.name);
-        holder.nameView.setTextColor(ContextCompat.getColor(context, textColorResId));
-
-        final long now = System.currentTimeMillis();
-
-        // It's OK to access the DB on the main thread here, as we're just
-        // getting a string.
-        final GeckoProfile profile = GeckoProfile.get(context);
-        holder.lastModifiedView.setText(getLastSyncedString(context, now, client.lastModified));
-
-        // These views exists only in some of our group views: they are present
-        // for the home panel groups and not for the tabs panel groups.
-        // Therefore, we must handle null.
-        if (holder.deviceTypeView != null) {
-            holder.deviceTypeView.setImageResource(deviceTypeResId);
-        }
-
-        if (holder.deviceExpandedView != null) {
-            // If there are no tabs to display, don't show an indicator at all.
-            holder.deviceExpandedView.setImageResource(client.tabs.isEmpty() ? 0 : deviceExpandedResId);
-        }
-    }
-
-    @Override
-    public boolean isChildSelectable(int groupPosition, int childPosition) {
-        return true;
-    }
-
-    @Override
-    public Object getChild(int groupPosition, int childPosition) {
-        return clients.get(groupPosition).tabs.get(childPosition);
-    }
-
-    @Override
-    public long getChildId(int groupPosition, int childPosition) {
-        return clients.get(groupPosition).tabs.get(childPosition).hashCode();
-    }
-
-    @Override
-    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
-        final Context context = parent.getContext();
-        final View view;
-        if (convertView != null) {
-            view = convertView;
-        } else {
-            final LayoutInflater inflater = LayoutInflater.from(context);
-            view = inflater.inflate(childLayoutId, parent, false);
-        }
-
-        final RemoteClient client = clients.get(groupPosition);
-        final RemoteTab tab = client.tabs.get(childPosition);
-
-        // The view is a TwoLinePageRow only for some of our child views: it's
-        // present for the home panel children and not for the tabs panel
-        // children. Therefore, we must handle one case manually.
-        if (view instanceof TwoLinePageRow) {
-            ((TwoLinePageRow) view).update(tab.title, tab.url);
-        } else {
-            final TextView titleView = (TextView) view.findViewById(R.id.title);
-            titleView.setText(TextUtils.isEmpty(tab.title) ? tab.url : tab.title);
-
-            final TextView urlView = (TextView) view.findViewById(R.id.url);
-            urlView.setText(tab.url);
-        }
-
-        return view;
-    }
-
-    /**
-     * Return a relative "Last synced" time span for the given tab record.
-     *
-     * @param now local time.
-     * @param time to format string for.
-     * @return string describing time span
-     */
-    public static String getLastSyncedString(Context context, long now, long time) {
-        if (new Date(time).before(EARLIEST_VALID_SYNCED_DATE)) {
-            return context.getString(R.string.remote_tabs_never_synced);
-        }
-        final CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
-        return context.getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
-    }
-}
--- a/mobile/android/base/java/org/mozilla/gecko/db/RemoteTab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/RemoteTab.java
@@ -1,25 +1,21 @@
 /* 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/. */
 
 package org.mozilla.gecko.db;
 
-import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
-
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
  * A thin representation of a remote tab.
  * <p>
- * We use the hash of the tab as the ID in
- * {@link RemoteTabsExpandableListAdapter#getClientId(int)}, and therefore we
- * must implement equality as well. These are generated functions.
+ * These are generated functions.
  */
 public class RemoteTab implements Parcelable {
     public final String title;
     public final String url;
     public final long lastUsed;
 
     public RemoteTab(String title, String url, long lastUsed) {
         this.title = title;
--- a/mobile/android/base/java/org/mozilla/gecko/home/ClientsAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/ClientsAdapter.java
@@ -4,36 +4,50 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.home;
 
 import android.content.Context;
 import android.support.annotation.UiThread;
 import android.support.v4.util.Pair;
 import android.support.v7.widget.RecyclerView;
+import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.RemoteClient;
 import org.mozilla.gecko.db.RemoteTab;
 
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
 import static org.mozilla.gecko.home.CombinedHistoryItem.ItemType.*;
 
 public class ClientsAdapter extends RecyclerView.Adapter<CombinedHistoryItem> implements CombinedHistoryRecyclerView.AdapterContextMenuBuilder {
     public static final String LOGTAG = "GeckoClientsAdapter";
 
+    /**
+     * If a device claims to have synced before this date, we will assume it has never synced.
+     */
+    public static final Date EARLIEST_VALID_SYNCED_DATE;
+    static {
+        final Calendar c = GregorianCalendar.getInstance();
+        c.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
+        EARLIEST_VALID_SYNCED_DATE = c.getTime();
+    }
+
     List<Pair<String, Integer>> adapterList = new LinkedList<>();
 
     // List of hidden remote clients.
     // Only accessed from the UI thread.
     protected final List<RemoteClient> hiddenClients = new ArrayList<>();
     private Map<String, RemoteClient> visibleClients = new HashMap<>();
 
     // Maintain group collapsed and hidden state. Only accessed from the UI thread.
@@ -287,9 +301,23 @@ public class ClientsAdapter extends Recy
     }
 
     protected static HomeContextMenuInfo populateChildInfoFromTab(HomeContextMenuInfo info, RemoteTab tab) {
         info.url = tab.url;
         info.title = tab.title;
         return info;
     }
 
+    /**
+     * Return a relative "Last synced" time span for the given tab record.
+     *
+     * @param now local time.
+     * @param time to format string for.
+     * @return string describing time span
+     */
+    public static String getLastSyncedString(Context context, long now, long time) {
+        if (new Date(time).before(EARLIEST_VALID_SYNCED_DATE)) {
+            return context.getString(R.string.remote_tabs_never_synced);
+        }
+        final CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
+        return context.getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryItem.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryItem.java
@@ -8,17 +8,16 @@ import android.content.Context;
 import android.database.Cursor;
 import android.support.v4.content.ContextCompat;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 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 {
     private static final String LOGTAG = "CombinedHistoryItem";
 
     public CombinedHistoryItem(View view) {
         super(view);
@@ -98,17 +97,17 @@ public abstract class CombinedHistoryIte
             deviceTypeView = (ImageView) view.findViewById(R.id.device_type);
             lastModifiedView = (TextView) view.findViewById(R.id.last_synced);
             deviceExpanded = (ImageView) view.findViewById(R.id.device_expanded);
         }
 
         public void bind(Context context, RemoteClient client, boolean isCollapsed) {
             this.nameView.setText(client.name);
             final long now = System.currentTimeMillis();
-            this.lastModifiedView.setText(RemoteTabsExpandableListAdapter.getLastSyncedString(context, now, client.lastModified));
+            this.lastModifiedView.setText(ClientsAdapter.getLastSyncedString(context, now, client.lastModified));
 
             if (client.isDesktop()) {
                 deviceTypeView.setImageResource(isCollapsed ? R.drawable.sync_desktop_inactive : R.drawable.sync_desktop);
             } else {
                 deviceTypeView.setImageResource(isCollapsed ? R.drawable.sync_mobile_inactive : R.drawable.sync_mobile);
             }
 
             nameView.setTextColor(ContextCompat.getColor(context, isCollapsed ? R.color.tabs_tray_icon_grey : R.color.placeholder_active_grey));
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -518,17 +518,16 @@ gbjar.sources += ['java/org/mozilla/geck
     'prompts/PromptListAdapter.java',
     'prompts/PromptListItem.java',
     'prompts/PromptService.java',
     'prompts/TabInput.java',
     'reader/ReaderModeUtils.java',
     'reader/ReadingListHelper.java',
     'reader/SavedReaderViewHelper.java',
     'RemoteClientsDialogFragment.java',
-    'RemoteTabsExpandableListAdapter.java',
     'Restarter.java',
     'restrictions/DefaultConfiguration.java',
     'restrictions/GuestProfileConfiguration.java',
     'restrictions/Restrictable.java',
     'restrictions/RestrictedProfileConfiguration.java',
     'restrictions/RestrictionCache.java',
     'restrictions/RestrictionConfiguration.java',
     'restrictions/RestrictionProvider.java',