From aa15dae22d9fe3d0d51b1b28f131f0b1b74a5869 Mon Sep 17 00:00:00 2001 From: Steve McKay Date: Tue, 9 Feb 2016 16:17:24 -0800 Subject: [PATCH] Automatically open roots pane if default dir is empty. Move drawer fiddling out of DirectoryFragment into respective FragmentTuner instance. Bug: 27084308 Change-Id: Ia13fc2be1442e1a7164c2d67ea6ce4bcfda68bcc --- .../src/com/android/documentsui/BaseActivity.java | 4 +- .../com/android/documentsui/DocumentsActivity.java | 8 +-- .../src/com/android/documentsui/State.java | 25 ++++++++ .../documentsui/dirlist/DirectoryFragment.java | 23 ++++--- .../android/documentsui/dirlist/FragmentTuner.java | 71 +++++++++++++++++----- 5 files changed, 99 insertions(+), 32 deletions(-) diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java index 3c21a214b19b..67a5b256fef6 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java @@ -216,7 +216,9 @@ public abstract class BaseActivity extends Activity 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 3485fe4446f5..80bdfda035d6 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.ComponentName; 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 @@ public class DocumentsActivity extends BaseActivity { } } - @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 @@ public class DocumentsActivity extends BaseActivity { 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 d141de667f2f..bd90eef2765b 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 @@ import java.util.List; 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 @@ public class State implements android.os.Parcelable { /** 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 class State implements android.os.Parcelable { } 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 @@ public class State implements android.os.Parcelable { return mStackTouched; } + public boolean initialiLocationHasChanged() { + return mInitialRootChanged || mInitialDocChanged; + } + @Override public int describeContents() { return 0; @@ -156,6 +177,8 @@ public class State implements android.os.Parcelable { 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 CREATOR = new ClassLoaderCreator() { @@ -184,6 +207,8 @@ public class State implements android.os.Parcelable { 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 d21b157cb49c..ce9fd1b56589 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.checkNotNull; 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.DocumentStack; 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 @@ import java.util.List; */ 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 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi 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 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi 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 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi 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 container = state.dirState.remove(mStateKey); if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) { @@ -338,6 +343,8 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi } 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 a295ab2524fb..3f51e538a263 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,36 +25,43 @@ import static com.android.documentsui.State.ACTION_OPEN; import static com.android.documentsui.State.ACTION_OPEN_TREE; import static com.android.internal.util.Preconditions.checkArgument; -import com.android.documentsui.Menus; -import com.android.documentsui.MimePredicate; -import com.android.documentsui.R; -import com.android.documentsui.State; - +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 com.android.documentsui.dirlist.DirectoryFragment.ResultType; + /** * Providers support for specializing the DirectoryFragment to the "host" Activity. * Feel free to expand the role of this class to handle other specializations. */ 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 @@ public abstract class FragmentTuner { 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 @@ public abstract class FragmentTuner { 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 @@ public abstract class FragmentTuner { */ 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 @@ public abstract class FragmentTuner { moveTo.setEnabled(moveEnabled); rename.setVisible(false); } + + @Override + void onModelLoaded(Model model, @ResultType int resultType) {} } /** @@ -196,8 +219,10 @@ public abstract class FragmentTuner { */ 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 @@ public abstract class FragmentTuner { 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); } + } -- 2.11.0