Automatically open roots pane if default dir is empty.
Move drawer fiddling out of DirectoryFragment into respective
FragmentTuner instance.
Bug: 27084308
Change-Id: Ia13fc2be1442e1a7164c2d67ea6ce4bcfda68bcc
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 3c21a21..67a5b25 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -216,7 +216,9 @@
return state;
}
- void onStackRestored(boolean restored, boolean external) {}
+ public void setRootsDrawerOpen(boolean open) {
+ mNavigator.revealRootsDrawer(open);
+ }
void onRootPicked(RootInfo root) {
// Skip refreshing if root didn't change
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 3485fe4..80bdfda 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -32,7 +32,6 @@
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -141,8 +140,7 @@
}
}
- @Override
- void onStackRestored(boolean restored, boolean external) {
+ private void onStackRestored(boolean restored, boolean external) {
// Show drawer when no stack restored, but only when requesting
// non-visual content. However, if we last used an external app,
// drawer is always shown.
@@ -329,10 +327,6 @@
mNavigator.revealRootsDrawer(false);
}
- public void setRootsDrawerOpen(boolean open) {
- mNavigator.revealRootsDrawer(open);
- }
-
@Override
public void onDocumentPicked(DocumentInfo doc, SiblingProvider siblings) {
final FragmentManager fm = getFragmentManager();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index d141de6..bd90eef 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -16,10 +16,13 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
+
import android.annotation.IntDef;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Log;
import android.util.SparseArray;
import com.android.documentsui.model.DocumentInfo;
@@ -35,6 +38,8 @@
public class State implements android.os.Parcelable {
+ private static final String TAG = "State";
+
public static final int ACTION_OPEN = 1;
public static final int ACTION_CREATE = 2;
public static final int ACTION_GET_CONTENT = 3;
@@ -85,6 +90,8 @@
/** Current user navigation stack; empty implies recents. */
public DocumentStack stack = new DocumentStack();
private boolean mStackTouched;
+ private boolean mInitialRootChanged;
+ private boolean mInitialDocChanged;
/** Currently active search, overriding any stack. */
public String currentSearch;
@@ -108,22 +115,32 @@
}
public void onRootChanged(RootInfo root) {
+ if (DEBUG) Log.d(TAG, "Root changed to: " + root);
+ if (!mInitialRootChanged && stack.root != null && !root.equals(stack.root)) {
+ mInitialRootChanged = true;
+ }
stack.root = root;
stack.clear();
mStackTouched = true;
}
public void pushDocument(DocumentInfo info) {
+ if (DEBUG) Log.d(TAG, "Adding doc to stack: " + info);
+ if (!mInitialDocChanged && stack.size() > 0 && !info.equals(stack.peek())) {
+ mInitialDocChanged = true;
+ }
stack.push(info);
mStackTouched = true;
}
public void popDocument() {
+ if (DEBUG) Log.d(TAG, "Popping doc off stack.");
stack.pop();
mStackTouched = true;
}
public void setStack(DocumentStack stack) {
+ if (DEBUG) Log.d(TAG, "Setting the whole darn stack to: " + stack);
this.stack = stack;
mStackTouched = true;
}
@@ -132,6 +149,10 @@
return mStackTouched;
}
+ public boolean initialiLocationHasChanged() {
+ return mInitialRootChanged || mInitialDocChanged;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -156,6 +177,8 @@
out.writeList(excludedAuthorities);
out.writeInt(openableOnly ? 1 : 0);
out.writeInt(mStackTouched ? 1 : 0);
+ out.writeInt(mInitialRootChanged ? 1 : 0);
+ out.writeInt(mInitialDocChanged ? 1 : 0);
}
public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() {
@@ -184,6 +207,8 @@
in.readList(state.excludedAuthorities, loader);
state.openableOnly = in.readInt() != 0;
state.mStackTouched = in.readInt() != 0;
+ state.mInitialRootChanged = in.readInt() != 0;
+ state.mInitialDocChanged = in.readInt() != 0;
return state;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index d21b157..ce9fd1b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -27,6 +27,7 @@
import static com.android.internal.util.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkArgument;
+import android.annotation.IntDef;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.ActivityManager;
@@ -100,8 +101,11 @@
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperations;
+
import com.google.common.collect.Lists;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -111,6 +115,13 @@
*/
public class DirectoryFragment extends Fragment implements DocumentsAdapter.Environment {
+ @IntDef(flag = true, value = {
+ TYPE_NORMAL,
+ TYPE_SEARCH,
+ TYPE_RECENT_OPEN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ResultType {}
public static final int TYPE_NORMAL = 1;
public static final int TYPE_SEARCH = 2;
public static final int TYPE_RECENT_OPEN = 3;
@@ -147,7 +158,7 @@
private RecyclerView mRecView;
private ListeningGestureDetector mGestureDetector;
- private int mType = TYPE_NORMAL;
+ private @ResultType int mType = TYPE_NORMAL;
private String mStateKey;
private int mLastSortOrder = SORT_ORDER_UNKNOWN;
@@ -262,7 +273,7 @@
mType = getArguments().getInt(EXTRA_TYPE);
mStateKey = buildStateKey(root, doc);
- mTuner = FragmentTuner.pick(state);
+ mTuner = FragmentTuner.pick(getContext(), state);
mClipper = new DocumentClipper(context);
boolean hideGridTitles;
@@ -320,12 +331,6 @@
updateDisplayState();
- // When launched into empty recents, show drawer
- if (mType == TYPE_RECENT_OPEN && mModel.isEmpty() && !state.hasLocationChanged() &&
- context instanceof DocumentsActivity) {
- ((DocumentsActivity) context).setRootsDrawerOpen(true);
- }
-
// Restore any previous instance state
final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) {
@@ -338,6 +343,8 @@
}
mLastSortOrder = state.derivedSortOrder;
+
+ mTuner.onModelLoaded(mModel, mType);
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index a295ab2..3f51e538 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -16,6 +16,7 @@
package com.android.documentsui.dirlist;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.State.ACTION_BROWSE;
import static com.android.documentsui.State.ACTION_CREATE;
import static com.android.documentsui.State.ACTION_GET_CONTENT;
@@ -24,15 +25,20 @@
import static com.android.documentsui.State.ACTION_OPEN_TREE;
import static com.android.internal.util.Preconditions.checkArgument;
+import android.content.Context;
+import android.os.SystemProperties;
+import android.provider.DocumentsContract.Document;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.documentsui.DocumentsActivity;
+import com.android.documentsui.FilesActivity;
import com.android.documentsui.Menus;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
import com.android.documentsui.State;
-
-import android.os.SystemProperties;
-import android.provider.DocumentsContract.Document;
-import android.view.Menu;
-import android.view.MenuItem;
+import com.android.documentsui.dirlist.DirectoryFragment.ResultType;
/**
* Providers support for specializing the DirectoryFragment to the "host" Activity.
@@ -40,20 +46,22 @@
*/
public abstract class FragmentTuner {
+ final Context mContext;
final State mState;
- public FragmentTuner(State state) {
+ public FragmentTuner(Context context, State state) {
+ mContext = context;
mState = state;
}
- public static FragmentTuner pick(State state) {
+ public static FragmentTuner pick(Context context, State state) {
switch (state.action) {
case ACTION_BROWSE:
- return new FilesTuner(state);
+ return new FilesTuner(context, state);
case ACTION_MANAGE:
- return new DownloadsTuner(state);
+ return new DownloadsTuner(context, state);
default:
- return new DocumentsTuner(state);
+ return new DocumentsTuner(context, state);
}
}
@@ -76,13 +84,15 @@
return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
}
+ abstract void onModelLoaded(Model model, @ResultType int resultType);
+
/**
* Provides support for Platform specific specializations of DirectoryFragment.
*/
private static final class DocumentsTuner extends FragmentTuner {
- public DocumentsTuner(State state) {
- super(state);
+ public DocumentsTuner(Context context, State state) {
+ super(context, state);
}
@Override
@@ -154,6 +164,16 @@
moveTo.setEnabled(moveEnabled);
rename.setVisible(false);
}
+
+ @Override
+ void onModelLoaded(Model model, @ResultType int resultType) {
+ // When launched into empty recents, show drawer
+ if (resultType == DirectoryFragment.TYPE_RECENT_OPEN
+ && model.isEmpty()
+ && !mState.hasLocationChanged()) {
+ ((DocumentsActivity) mContext).setRootsDrawerOpen(true);
+ }
+ }
}
/**
@@ -161,8 +181,8 @@
*/
private static final class DownloadsTuner extends FragmentTuner {
- public DownloadsTuner(State state) {
- super(state);
+ public DownloadsTuner(Context context, State state) {
+ super(context, state);
}
@Override
@@ -189,6 +209,9 @@
moveTo.setEnabled(moveEnabled);
rename.setVisible(false);
}
+
+ @Override
+ void onModelLoaded(Model model, @ResultType int resultType) {}
}
/**
@@ -196,8 +219,10 @@
*/
private static final class FilesTuner extends FragmentTuner {
- public FilesTuner(State state) {
- super(state);
+ private static final String TAG = "FilesTuner";
+
+ public FilesTuner(Context context, State state) {
+ super(context, state);
}
@Override
@@ -221,9 +246,23 @@
Menus.disableHiddenItems(menu, copy, paste);
}
+
+ @Override
+ void onModelLoaded(Model model, @ResultType int resultType) {
+ if (DEBUG) Log.d(TAG, "Handling model loaded. Has Location shcnage: " + mState.initialiLocationHasChanged());
+ // When launched into empty root, open drawer.
+ if (model.isEmpty() && !mState.initialiLocationHasChanged()) {
+ if (DEBUG) Log.d(TAG, "Showing roots drawer cuz stuffs empty.");
+
+ // This noops on layouts without drawer, so no need to guard.
+ ((FilesActivity) mContext).setRootsDrawerOpen(true);
+ }
+ if (DEBUG) Log.d(TAG, "Donezo.");
+ }
}
private static boolean isDirectory(String mimeType) {
return Document.MIME_TYPE_DIR.equals(mimeType);
}
+
}