зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1057637 - Extract a re-usable ExpandableListAdapter out of RemoteTabsList. r=mcomella
This patch does a few other small things as well: * It exposes the client device type. This will be used later, as part of the visual refresh. * Aligns the field names in remote_tabs_child with the names used by TwoLinePageRow. This will be used later, when we finally use said standard view class. --HG-- extra : rebase_source : 291f69a5f9b68801dd9154c5d291c6795d218ff6
This commit is contained in:
Родитель
45478db795
Коммит
3f1715f746
|
@ -0,0 +1,149 @@
|
|||
/* 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.mozilla.gecko.TabsAccessor.RemoteClient;
|
||||
import org.mozilla.gecko.TabsAccessor.RemoteTab;
|
||||
|
||||
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.TextView;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
protected final ArrayList<RemoteClient> clients;
|
||||
protected int groupLayoutId;
|
||||
protected int childLayoutId;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public RemoteTabsExpandableListAdapter(int groupLayoutId, int childLayoutId, List<RemoteClient> clients) {
|
||||
this.groupLayoutId = groupLayoutId;
|
||||
this.childLayoutId = childLayoutId;
|
||||
this.clients = new ArrayList<TabsAccessor.RemoteClient>();
|
||||
if (clients != null) {
|
||||
this.clients.addAll(clients);
|
||||
}
|
||||
}
|
||||
|
||||
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 RemoteClient client = clients.get(groupPosition);
|
||||
|
||||
final TextView nameView = (TextView) view.findViewById(R.id.client);
|
||||
nameView.setText(client.name);
|
||||
|
||||
final TextView lastModifiedView = (TextView) view.findViewById(R.id.last_synced);
|
||||
final long now = System.currentTimeMillis();
|
||||
lastModifiedView.setText(TabsAccessor.getLastSyncedString(context, now, client.lastModified));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -4,127 +4,241 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UIAsyncTask;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class TabsAccessor {
|
||||
private static final String LOGTAG = "GeckoTabsAccessor";
|
||||
|
||||
private static final String[] CLIENTS_AVAILABILITY_PROJECTION = new String[] {
|
||||
BrowserContract.Clients.GUID
|
||||
};
|
||||
|
||||
private static final String[] TABS_PROJECTION_COLUMNS = new String[] {
|
||||
public static final String[] TABS_PROJECTION_COLUMNS = new String[] {
|
||||
BrowserContract.Tabs.TITLE,
|
||||
BrowserContract.Tabs.URL,
|
||||
BrowserContract.Clients.GUID,
|
||||
BrowserContract.Clients.NAME,
|
||||
BrowserContract.Clients.LAST_MODIFIED,
|
||||
BrowserContract.Clients.DEVICE_TYPE,
|
||||
};
|
||||
|
||||
// Projection column numbers
|
||||
public static enum TABS_COLUMN {
|
||||
TITLE,
|
||||
URL,
|
||||
GUID,
|
||||
NAME,
|
||||
LAST_MODIFIED,
|
||||
};
|
||||
private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL";
|
||||
private static final String REMOTE_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NOT NULL";
|
||||
|
||||
private static final String CLIENTS_SELECTION = BrowserContract.Clients.GUID + " IS NOT NULL";
|
||||
private static final String TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NOT NULL";
|
||||
private static final String REMOTE_TABS_SORT_ORDER =
|
||||
// Most recently synced clients first.
|
||||
BrowserContract.Clients.LAST_MODIFIED + " DESC, " +
|
||||
// If two clients somehow had the same last modified time, this will
|
||||
// group them (arbitrarily).
|
||||
BrowserContract.Clients.GUID + " DESC, " +
|
||||
// Within a single client, most recently used tabs first.
|
||||
BrowserContract.Tabs.LAST_USED + " DESC";
|
||||
|
||||
private static final String LOCAL_CLIENT_SELECTION = BrowserContract.Clients.GUID + " IS NULL";
|
||||
private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL";
|
||||
|
||||
private static final Pattern FILTERED_URL_PATTERN = Pattern.compile("^(about|chrome|wyciwyg|file):");
|
||||
|
||||
/**
|
||||
* A thin representation of a remote client.
|
||||
* <p>
|
||||
* We use the hash of the client's GUID as the ID in
|
||||
* {@link RemoteTabsExpandableListAdapter#getGroupId(int)}.
|
||||
*/
|
||||
public static class RemoteClient {
|
||||
public final String guid;
|
||||
public final String name;
|
||||
public final long lastModified;
|
||||
public final String deviceType;
|
||||
public final ArrayList<RemoteTab> tabs;
|
||||
|
||||
public RemoteClient(String guid, String name, long lastModified, String deviceType) {
|
||||
this.guid = guid;
|
||||
this.name = name;
|
||||
this.lastModified = lastModified;
|
||||
this.deviceType = deviceType;
|
||||
this.tabs = new ArrayList<RemoteTab>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static class RemoteTab {
|
||||
public String title;
|
||||
public String url;
|
||||
public String guid;
|
||||
public String name;
|
||||
/**
|
||||
* This is the last time the remote client uploaded a tabs record; that
|
||||
* is, it is not per tab, but per remote client.
|
||||
*/
|
||||
public long lastModified;
|
||||
public final String title;
|
||||
public final String url;
|
||||
|
||||
public RemoteTab(String title, String url) {
|
||||
this.title = title;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
||||
result = prime * result + ((url == null) ? 0 : url.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
RemoteTab other = (RemoteTab) obj;
|
||||
if (title == null) {
|
||||
if (other.title != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!title.equals(other.title)) {
|
||||
return false;
|
||||
}
|
||||
if (url == null) {
|
||||
if (other.url != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!url.equals(other.url)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract client and tab records from a cursor.
|
||||
* <p>
|
||||
* The position of the cursor is moved to before the first record before
|
||||
* reading. The cursor is advanced until there are no more records to be
|
||||
* read. The position of the cursor is restored before returning.
|
||||
*
|
||||
* @param cursor
|
||||
* to extract records from. The records should already be grouped
|
||||
* by client GUID.
|
||||
* @return list of clients, each containing list of tabs.
|
||||
*/
|
||||
public static List<RemoteClient> getClientsFromCursor(final Cursor cursor) {
|
||||
final ArrayList<RemoteClient> clients = new ArrayList<TabsAccessor.RemoteClient>();
|
||||
|
||||
final int originalPosition = cursor.getPosition();
|
||||
try {
|
||||
if (!cursor.moveToFirst()) {
|
||||
return clients;
|
||||
}
|
||||
|
||||
final int tabTitleIndex = cursor.getColumnIndex(BrowserContract.Tabs.TITLE);
|
||||
final int tabUrlIndex = cursor.getColumnIndex(BrowserContract.Tabs.URL);
|
||||
final int clientGuidIndex = cursor.getColumnIndex(BrowserContract.Clients.GUID);
|
||||
final int clientNameIndex = cursor.getColumnIndex(BrowserContract.Clients.NAME);
|
||||
final int clientLastModifiedIndex = cursor.getColumnIndex(BrowserContract.Clients.LAST_MODIFIED);
|
||||
final int clientDeviceTypeIndex = cursor.getColumnIndex(BrowserContract.Clients.DEVICE_TYPE);
|
||||
|
||||
// A walking partition, chunking by client GUID. We assume the
|
||||
// cursor records are already grouped by client GUID; see the query
|
||||
// sort order.
|
||||
RemoteClient lastClient = null;
|
||||
while (!cursor.isAfterLast()) {
|
||||
final String clientGuid = cursor.getString(clientGuidIndex);
|
||||
if (lastClient == null || !TextUtils.equals(lastClient.guid, clientGuid)) {
|
||||
final String clientName = cursor.getString(clientNameIndex);
|
||||
final long lastModified = cursor.getLong(clientLastModifiedIndex);
|
||||
final String deviceType = cursor.getString(clientDeviceTypeIndex);
|
||||
lastClient = new RemoteClient(clientGuid, clientName, lastModified, deviceType);
|
||||
clients.add(lastClient);
|
||||
}
|
||||
|
||||
final String tabTitle = cursor.getString(tabTitleIndex);
|
||||
final String tabUrl = cursor.getString(tabUrlIndex);
|
||||
lastClient.tabs.add(new RemoteTab(tabTitle, tabUrl));
|
||||
|
||||
cursor.moveToNext();
|
||||
}
|
||||
} finally {
|
||||
cursor.moveToPosition(originalPosition);
|
||||
}
|
||||
|
||||
return clients;
|
||||
}
|
||||
|
||||
public static Cursor getRemoteTabsCursor(Context context) {
|
||||
return getRemoteTabsCursor(context, -1);
|
||||
}
|
||||
|
||||
public static Cursor getRemoteTabsCursor(Context context, int limit) {
|
||||
Uri uri = BrowserContract.Tabs.CONTENT_URI;
|
||||
|
||||
if (limit > 0) {
|
||||
uri = uri.buildUpon()
|
||||
.appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit))
|
||||
.build();
|
||||
}
|
||||
|
||||
final Cursor cursor = context.getContentResolver().query(uri,
|
||||
TABS_PROJECTION_COLUMNS,
|
||||
REMOTE_TABS_SELECTION,
|
||||
null,
|
||||
REMOTE_TABS_SORT_ORDER);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public interface OnQueryTabsCompleteListener {
|
||||
public void onQueryTabsComplete(List<RemoteTab> tabs);
|
||||
public void onQueryTabsComplete(List<RemoteClient> clients);
|
||||
}
|
||||
|
||||
// This method returns all tabs from all remote clients,
|
||||
// ordered by most recent client first, most recent tab first
|
||||
// This method returns all tabs from all remote clients,
|
||||
// ordered by most recent client first, most recent tab first
|
||||
public static void getTabs(final Context context, final OnQueryTabsCompleteListener listener) {
|
||||
getTabs(context, 0, listener);
|
||||
}
|
||||
|
||||
// This method returns limited number of tabs from all remote clients,
|
||||
// ordered by most recent client first, most recent tab first
|
||||
// This method returns limited number of tabs from all remote clients,
|
||||
// ordered by most recent client first, most recent tab first
|
||||
public static void getTabs(final Context context, final int limit, final OnQueryTabsCompleteListener listener) {
|
||||
// If there is no listener, no point in doing work.
|
||||
if (listener == null)
|
||||
return;
|
||||
|
||||
(new UIAsyncTask.WithoutParams<List<RemoteTab>>(ThreadUtils.getBackgroundHandler()) {
|
||||
(new UIAsyncTask.WithoutParams<List<RemoteClient>>(ThreadUtils.getBackgroundHandler()) {
|
||||
@Override
|
||||
protected List<RemoteTab> doInBackground() {
|
||||
Uri uri = BrowserContract.Tabs.CONTENT_URI;
|
||||
|
||||
if (limit > 0) {
|
||||
uri = uri.buildUpon()
|
||||
.appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit))
|
||||
.build();
|
||||
}
|
||||
|
||||
Cursor cursor = context.getContentResolver().query(uri,
|
||||
TABS_PROJECTION_COLUMNS,
|
||||
TABS_SELECTION,
|
||||
null,
|
||||
null);
|
||||
|
||||
protected List<RemoteClient> doInBackground() {
|
||||
final Cursor cursor = getRemoteTabsCursor(context, limit);
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
RemoteTab tab;
|
||||
final ArrayList<RemoteTab> tabs = new ArrayList<RemoteTab> ();
|
||||
try {
|
||||
while (cursor.moveToNext()) {
|
||||
tab = new RemoteTab();
|
||||
tab.title = cursor.getString(TABS_COLUMN.TITLE.ordinal());
|
||||
tab.url = cursor.getString(TABS_COLUMN.URL.ordinal());
|
||||
tab.guid = cursor.getString(TABS_COLUMN.GUID.ordinal());
|
||||
tab.name = cursor.getString(TABS_COLUMN.NAME.ordinal());
|
||||
tab.lastModified = cursor.getLong(TABS_COLUMN.LAST_MODIFIED.ordinal());
|
||||
|
||||
tabs.add(tab);
|
||||
}
|
||||
try {
|
||||
return Collections.unmodifiableList(getClientsFromCursor(cursor));
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(tabs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<RemoteTab> tabs) {
|
||||
listener.onQueryTabsComplete(tabs);
|
||||
protected void onPostExecute(List<RemoteClient> clients) {
|
||||
listener.onQueryTabsComplete(clients);
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
@ -210,4 +324,16 @@ public final class TabsAccessor {
|
|||
private static boolean isFilteredURL(String url) {
|
||||
return FILTERED_URL_PATTERN.matcher(url).lookingAt();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
final CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
|
||||
return context.getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -368,6 +368,7 @@ gbjar.sources += [
|
|||
'prompts/PromptService.java',
|
||||
'prompts/TabInput.java',
|
||||
'ReaderModeUtils.java',
|
||||
'RemoteTabsExpandableListAdapter.java',
|
||||
'Restarter.java',
|
||||
'ScrollAnimator.java',
|
||||
'ServiceNotificationClient.java',
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp">
|
||||
|
||||
<TextView android:id="@+id/tab"
|
||||
<TextView android:id="@+id/title"
|
||||
style="@style/TabRowTextAppearance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -5,42 +5,32 @@
|
|||
package org.mozilla.gecko.tabs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.RemoteTabsExpandableListAdapter;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.TabsAccessor;
|
||||
import org.mozilla.gecko.TabsAccessor.RemoteClient;
|
||||
import org.mozilla.gecko.TabsAccessor.RemoteTab;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.SimpleExpandableListAdapter;
|
||||
|
||||
/**
|
||||
* The actual list of synced tabs. This serves as the only child view of {@link RemoteTabsContainerPanel}
|
||||
* so it can be refreshed using a swipe-to-refresh gesture.
|
||||
*/
|
||||
class RemoteTabsList extends ExpandableListView
|
||||
implements ExpandableListView.OnGroupClickListener,
|
||||
ExpandableListView.OnChildClickListener,
|
||||
TabsAccessor.OnQueryTabsCompleteListener {
|
||||
private static final String[] CLIENT_KEY = new String[] { "name", "last_synced" };
|
||||
private static final String[] TAB_KEY = new String[] { "title", "url" };
|
||||
private static final int[] CLIENT_RESOURCE = new int[] { R.id.client, R.id.last_synced };
|
||||
private static final int[] TAB_RESOURCE = new int[] { R.id.tab, R.id.url };
|
||||
|
||||
private final Context context;
|
||||
public class RemoteTabsList extends ExpandableListView
|
||||
implements ExpandableListView.OnGroupClickListener,
|
||||
ExpandableListView.OnChildClickListener,
|
||||
TabsAccessor.OnQueryTabsCompleteListener {
|
||||
private TabsPanel tabsPanel;
|
||||
|
||||
private ArrayList <HashMap <String, String>> clients;
|
||||
private ArrayList <ArrayList <HashMap <String, String>>> tabsList;
|
||||
|
||||
// A list of the clients that are currently expanded.
|
||||
private List<String> expandedClientList;
|
||||
|
||||
|
@ -49,10 +39,10 @@ class RemoteTabsList extends ExpandableListView
|
|||
|
||||
public RemoteTabsList(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this.context = context;
|
||||
|
||||
setOnGroupClickListener(this);
|
||||
setOnChildClickListener(this);
|
||||
setAdapter(new RemoteTabsExpandableListAdapter(R.layout.remote_tabs_group, R.layout.remote_tabs_child, null));
|
||||
}
|
||||
|
||||
public void setTabsPanel(TabsPanel panel) {
|
||||
|
@ -65,7 +55,8 @@ class RemoteTabsList extends ExpandableListView
|
|||
|
||||
@Override
|
||||
public boolean onGroupClick(ExpandableListView parent, View view, int groupPosition, long id) {
|
||||
final String clientGuid = clients.get(groupPosition).get("guid");
|
||||
final RemoteClient client = (RemoteClient) parent.getExpandableListAdapter().getGroup(groupPosition);
|
||||
final String clientGuid = client.guid;
|
||||
|
||||
if (isGroupExpanded(groupPosition)) {
|
||||
collapseGroup(groupPosition);
|
||||
|
@ -81,7 +72,7 @@ class RemoteTabsList extends ExpandableListView
|
|||
|
||||
@Override
|
||||
public boolean onChildClick(ExpandableListView parent, View view, int groupPosition, int childPosition, long id) {
|
||||
HashMap <String, String> tab = tabsList.get(groupPosition).get(childPosition);
|
||||
final RemoteTab tab = (RemoteTab) parent.getExpandableListAdapter().getChild(groupPosition, childPosition);
|
||||
if (tab == null) {
|
||||
autoHidePanel();
|
||||
return true;
|
||||
|
@ -89,64 +80,23 @@ class RemoteTabsList extends ExpandableListView
|
|||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.LIST_ITEM, "remote");
|
||||
|
||||
Tabs.getInstance().loadUrl(tab.get("url"), Tabs.LOADURL_NEW_TAB);
|
||||
Tabs.getInstance().loadUrl(tab.url, Tabs.LOADURL_NEW_TAB);
|
||||
autoHidePanel();
|
||||
|
||||
clientScrollPosition = clients.get(groupPosition).get("guid");
|
||||
final RemoteClient client = (RemoteClient) parent.getExpandableListAdapter().getGroup(groupPosition);
|
||||
clientScrollPosition = client.guid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQueryTabsComplete(List<TabsAccessor.RemoteTab> remoteTabsList) {
|
||||
ArrayList<TabsAccessor.RemoteTab> remoteTabs = new ArrayList<TabsAccessor.RemoteTab> (remoteTabsList);
|
||||
if (remoteTabs == null || remoteTabs.size() == 0)
|
||||
return;
|
||||
|
||||
clients = new ArrayList <HashMap <String, String>>();
|
||||
tabsList = new ArrayList <ArrayList <HashMap <String, String>>>();
|
||||
|
||||
String oldGuid = null;
|
||||
ArrayList <HashMap <String, String>> tabsForClient = null;
|
||||
HashMap <String, String> client;
|
||||
HashMap <String, String> tab;
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
|
||||
for (TabsAccessor.RemoteTab remoteTab : remoteTabs) {
|
||||
final String clientGuid = remoteTab.guid;
|
||||
if (oldGuid == null || !TextUtils.equals(oldGuid, clientGuid)) {
|
||||
client = new HashMap <String, String>();
|
||||
client.put("name", remoteTab.name);
|
||||
client.put("last_synced", getLastSyncedString(now, remoteTab.lastModified));
|
||||
client.put("guid", clientGuid);
|
||||
clients.add(client);
|
||||
|
||||
tabsForClient = new ArrayList <HashMap <String, String>>();
|
||||
tabsList.add(tabsForClient);
|
||||
|
||||
oldGuid = new String(clientGuid);
|
||||
}
|
||||
|
||||
tab = new HashMap<String, String>();
|
||||
tab.put("title", TextUtils.isEmpty(remoteTab.title) ? remoteTab.url : remoteTab.title);
|
||||
tab.put("url", remoteTab.url);
|
||||
tabsForClient.add(tab);
|
||||
}
|
||||
|
||||
setAdapter(new SimpleExpandableListAdapter(context,
|
||||
clients,
|
||||
R.layout.remote_tabs_group,
|
||||
CLIENT_KEY,
|
||||
CLIENT_RESOURCE,
|
||||
tabsList,
|
||||
R.layout.remote_tabs_child,
|
||||
TAB_KEY,
|
||||
TAB_RESOURCE));
|
||||
public void onQueryTabsComplete(List<RemoteClient> clients) {
|
||||
((RemoteTabsExpandableListAdapter) getExpandableListAdapter()).replaceClients(clients);
|
||||
|
||||
// Either set the initial UI state, or restore it.
|
||||
List<String> newExpandedClientList = new ArrayList<String>();
|
||||
for (int i = 0; i < clients.size(); i++) {
|
||||
final String clientGuid = clients.get(i).get("guid");
|
||||
final String clientGuid = clients.get(i).guid;
|
||||
|
||||
if (expandedClientList == null) {
|
||||
// On initial entry we expand all clients by default.
|
||||
|
@ -167,16 +117,4 @@ class RemoteTabsList extends ExpandableListView
|
|||
}
|
||||
expandedClientList = newExpandedClientList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected String getLastSyncedString(long now, long time) {
|
||||
CharSequence relativeTimeSpanString = DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
|
||||
return getResources().getString(R.string.remote_tabs_last_synced, relativeTimeSpanString);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче