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
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;
}
}
- @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.
mNavigator.revealRootsDrawer(false);
}
- public void setRootsDrawerOpen(boolean open) {
- mNavigator.revealRootsDrawer(open);
- }
-
@Override
public void onDocumentPicked(DocumentInfo doc, SiblingProvider siblings) {
final FragmentManager fm = getFragmentManager();
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;
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;
/** 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;
}
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;
}
return mStackTouched;
}
+ public boolean initialiLocationHasChanged() {
+ return mInitialRootChanged || mInitialDocChanged;
+ }
+
@Override
public int describeContents() {
return 0;
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>() {
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;
}
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;
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;
*/
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;
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;
mType = getArguments().getInt(EXTRA_TYPE);
mStateKey = buildStateKey(root, doc);
- mTuner = FragmentTuner.pick(state);
+ mTuner = FragmentTuner.pick(getContext(), state);
mClipper = new DocumentClipper(context);
boolean hideGridTitles;
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)) {
}
mLastSortOrder = state.derivedSortOrder;
+
+ mTuner.onModelLoaded(mModel, mType);
}
@Override
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;
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);
}
}
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
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);
+ }
+ }
}
/**
*/
private static final class DownloadsTuner extends FragmentTuner {
- public DownloadsTuner(State state) {
- super(state);
+ public DownloadsTuner(Context context, State state) {
+ super(context, state);
}
@Override
moveTo.setEnabled(moveEnabled);
rename.setVisible(false);
}
+
+ @Override
+ void onModelLoaded(Model model, @ResultType int resultType) {}
}
/**
*/
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
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);
}
+
}