Bug 1220928 - Handle configuration changes. r=sebastian
MozReview-Commit-ID: E5MoWlcMCdj
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryAdapter.java
@@ -42,45 +42,45 @@ public class CombinedHistoryAdapter exte
public static int itemTypeToViewType(ItemType itemType) {
return itemType.ordinal();
}
}
private List<RemoteClient> remoteClients = Collections.emptyList();
private List<RemoteTab> clientChildren;
+ private int remoteClientIndexOfParent = -1;
private Cursor historyCursor;
// Maintain group collapsed and hidden state. Only accessed from the UI thread.
protected static RemoteTabsExpandableListState sState;
// List of hidden remote clients.
// Only accessed from the UI thread.
protected final List<RemoteClient> hiddenClients = new ArrayList<>();
// We use a sparse array to store each section header's position in the panel [more cheaply than a HashMap].
private final SparseArray<CombinedHistoryPanel.SectionHeader> sectionHeaders;
private final Context context;
- private boolean inChildView = false;
-
- public CombinedHistoryAdapter(Context context) {
+ public CombinedHistoryAdapter(Context context, int savedParentIndex) {
super();
this.context = context;
sectionHeaders = new SparseArray<>();
// This races when multiple Fragments are created. That's okay: one
// will win, and thereafter, all will be okay. If we create and then
// drop an instance the shared SharedPreferences backing all the
// instances will maintain the state for us. Since everything happens on
// the UI thread, this doesn't even need to be volatile.
if (sState == null) {
sState = new RemoteTabsExpandableListState(GeckoSharedPrefs.forProfile(context));
}
+ remoteClientIndexOfParent = savedParentIndex;
}
public void setClients(List<RemoteClient> clients) {
hiddenClients.clear();
remoteClients.clear();
final Iterator<RemoteClient> it = clients.iterator();
while (it.hasNext()) {
@@ -179,32 +179,40 @@ public class CombinedHistoryAdapter exte
for (int i = 1; i < clientChildren.size(); i++) {
urls.put(clientChildren.get(i).url);
}
return urls;
}
return null;
}
+ public int getParentIndex() {
+ return remoteClientIndexOfParent;
+ }
+
+ private boolean isInChildView() {
+ return remoteClientIndexOfParent != -1;
+ }
+
public void showChildView(int parentPosition) {
if (clientChildren == null) {
clientChildren = new ArrayList<>();
}
// Handle "back" view.
clientChildren.add(null);
- clientChildren.addAll(remoteClients.get(transformAdapterPositionForDataStructure(ItemType.CLIENT, parentPosition)).tabs);
- inChildView = true;
+ remoteClientIndexOfParent = transformAdapterPositionForDataStructure(ItemType.CLIENT, parentPosition);
+ clientChildren.addAll(remoteClients.get(remoteClientIndexOfParent).tabs);
notifyDataSetChanged();
}
public boolean exitChildView() {
- if (!inChildView) {
+ if (!isInChildView()) {
return false;
}
- inChildView = false;
+ remoteClientIndexOfParent = -1;
clientChildren.clear();
notifyDataSetChanged();
return true;
}
private ItemType getItemTypeForPosition(int position) {
return ItemType.viewTypeToItemType(getItemViewType(position));
}
@@ -280,17 +288,17 @@ public class CombinedHistoryAdapter exte
return new CombinedHistoryItem.HistoryItem(view);
default:
throw new IllegalArgumentException("Unexpected Home Panel item type");
}
}
@Override
public int getItemViewType(int position) {
- if (inChildView) {
+ if (isInChildView()) {
if (position == 0) {
return ItemType.itemTypeToViewType(ItemType.NAVIGATION_BACK);
}
return ItemType.itemTypeToViewType(ItemType.CHILD);
} else {
final int numClients = remoteClients.size();
if (position < numClients) {
if (!hiddenClients.isEmpty() && position == numClients - 1) {
@@ -305,18 +313,23 @@ public class CombinedHistoryAdapter exte
}
return ItemType.itemTypeToViewType(ItemType.HISTORY);
}
}
@Override
public int getItemCount() {
- if (inChildView) {
- return (clientChildren == null) ? 0 : clientChildren.size();
+ if (isInChildView()) {
+ if (clientChildren == null) {
+ clientChildren = new ArrayList<>();
+ clientChildren.add(null);
+ clientChildren.addAll(remoteClients.get(remoteClientIndexOfParent).tabs);
+ }
+ return clientChildren.size();
} else {
final int historySize = historyCursor == null ? 0 : historyCursor.getCount();
return remoteClients.size() + historySize + sectionHeaders.size();
}
}
/**
* Add only the SectionHeaders that have history items within their range to a SparseArray, where the
--- a/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/CombinedHistoryPanel.java
@@ -4,16 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.res.Configuration;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.widget.DefaultItemAnimator;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
@@ -77,16 +78,17 @@ public class CombinedHistoryPanel extend
// String placeholders to mark formatting.
private final static String FORMAT_S1 = "%1$s";
private final static String FORMAT_S2 = "%2$s";
private CombinedHistoryRecyclerView mRecyclerView;
private CombinedHistoryAdapter mAdapter;
private CursorLoaderCallbacks mCursorLoaderCallbacks;
+ private int mSavedParentIndex = -1;
private OnPanelLevelChangeListener.PanelLevel mPanelLevel = OnPanelLevelChangeListener.PanelLevel.PARENT;
private Button mPanelFooterButton;
// Reference to the View to display when there are no results.
private View mEmptyView;
public interface OnPanelLevelChangeListener {
enum PanelLevel {
@@ -101,17 +103,17 @@ public class CombinedHistoryPanel extend
return inflater.inflate(R.layout.home_combined_history_panel, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView = (CombinedHistoryRecyclerView) view.findViewById(R.id.combined_recycler_view);
- mAdapter = new CombinedHistoryAdapter(getContext());
+ mAdapter = new CombinedHistoryAdapter(getContext(), mSavedParentIndex);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext()));
mRecyclerView.setOnHistoryClickedListener(mUrlOpenListener);
mRecyclerView.setOnPanelLevelChangeListener(new OnLevelChangeListener());
mRecyclerView.setHiddenClientsDialogBuilder(new HiddenClientsHelper());
registerForContextMenu(mRecyclerView);
@@ -121,16 +123,27 @@ public class CombinedHistoryPanel extend
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mCursorLoaderCallbacks = new CursorLoaderCallbacks();
}
@Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ if (isVisible()) {
+ // The parent stack is saved just so that the folder state can be
+ // restored on rotation.
+ mSavedParentIndex = mAdapter.getParentIndex();
+ }
+ }
+
+ @Override
protected void load() {
getLoaderManager().initLoader(LOADER_ID_HISTORY, null, mCursorLoaderCallbacks);
getLoaderManager().initLoader(LOADER_ID_REMOTE, null, mCursorLoaderCallbacks);
}
private static class RemoteTabsCursorLoader extends SimpleCursorLoader {
private final GeckoProfile mProfile;
@@ -280,17 +293,17 @@ public class CombinedHistoryPanel extend
Telemetry.sendUIEvent(TelemetryContract.Event.SANITIZE, TelemetryContract.Method.BUTTON, "history");
}
});
dialogBuilder.show();
break;
case CHILD:
- final JSONArray tabUrls = ((CombinedHistoryAdapter) mRecyclerView.getAdapter()).getCurrentChildTabs();
+ final JSONArray tabUrls = mAdapter.getCurrentChildTabs();
if (tabUrls != null) {
final JSONObject message = new JSONObject();
try {
message.put("urls", tabUrls);
message.put("shouldNotifyTabsOpenedToJava", false);
GeckoAppShell.notifyObservers("Tabs:OpenMultiple", message.toString());
} catch (JSONException e) {
Log.e(LOGTAG, "Error making JSON message to open tabs");
@@ -420,17 +433,17 @@ public class CombinedHistoryPanel extend
if (!(menuInfo instanceof RemoteTabsClientContextMenuInfo)) {
return false;
}
final RemoteTabsClientContextMenuInfo info = (RemoteTabsClientContextMenuInfo) menuInfo;
final int itemId = item.getItemId();
if (itemId == R.id.home_remote_tabs_hide_client) {
- ((CombinedHistoryAdapter) mRecyclerView.getAdapter()).removeItem(info.position);
+ mAdapter.removeItem(info.position);
return true;
}
return false;
}
interface DialogBuilder<E> {
void createAndShowDialog(List<E> items);
@@ -447,17 +460,17 @@ public class CombinedHistoryPanel extend
dialog.show(getActivity().getSupportFragmentManager(), "show-clients");
}
}
@Override
public void onClients(List<RemoteClient> clients) {
- ((CombinedHistoryAdapter) mRecyclerView.getAdapter()).unhideClients(clients);
+ mAdapter.unhideClients(clients);
}
/**
* Stores information regarding the creation of the context menu for a remote client.
*/
protected static class RemoteTabsClientContextMenuInfo extends HomeContextMenuInfo {
protected final RemoteClient client;