Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa15dae2 authored by Steve McKay's avatar Steve McKay
Browse files

Automatically open roots pane if default dir is empty.

Move drawer fiddling out of DirectoryFragment into respective
    FragmentTuner instance.

Bug: 27084308
Change-Id: Ia13fc2be1442e1a7164c2d67ea6ce4bcfda68bcc
parent f854174e
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -216,7 +216,9 @@ public abstract class BaseActivity extends Activity
        return state;
        return state;
    }
    }


    void onStackRestored(boolean restored, boolean external) {}
    public void setRootsDrawerOpen(boolean open) {
        mNavigator.revealRootsDrawer(open);
    }


    void onRootPicked(RootInfo root) {
    void onRootPicked(RootInfo root) {
        // Skip refreshing if root didn't change
        // Skip refreshing if root didn't change
+1 −7
Original line number Original line Diff line number Diff line
@@ -32,7 +32,6 @@ import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.Resources;
@@ -141,8 +140,7 @@ public class DocumentsActivity extends BaseActivity {
        }
        }
    }
    }


    @Override
    private void onStackRestored(boolean restored, boolean external) {
    void onStackRestored(boolean restored, boolean external) {
        // Show drawer when no stack restored, but only when requesting
        // Show drawer when no stack restored, but only when requesting
        // non-visual content. However, if we last used an external app,
        // non-visual content. However, if we last used an external app,
        // drawer is always shown.
        // drawer is always shown.
@@ -329,10 +327,6 @@ public class DocumentsActivity extends BaseActivity {
        mNavigator.revealRootsDrawer(false);
        mNavigator.revealRootsDrawer(false);
    }
    }


    public void setRootsDrawerOpen(boolean open) {
        mNavigator.revealRootsDrawer(open);
    }

    @Override
    @Override
    public void onDocumentPicked(DocumentInfo doc, SiblingProvider siblings) {
    public void onDocumentPicked(DocumentInfo doc, SiblingProvider siblings) {
        final FragmentManager fm = getFragmentManager();
        final FragmentManager fm = getFragmentManager();
+25 −0
Original line number Original line Diff line number Diff line
@@ -16,10 +16,13 @@


package com.android.documentsui;
package com.android.documentsui;


import static com.android.documentsui.Shared.DEBUG;

import android.annotation.IntDef;
import android.annotation.IntDef;
import android.content.Intent;
import android.content.Intent;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;


import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentInfo;
@@ -35,6 +38,8 @@ import java.util.List;


public class State implements android.os.Parcelable {
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_OPEN = 1;
    public static final int ACTION_CREATE = 2;
    public static final int ACTION_CREATE = 2;
    public static final int ACTION_GET_CONTENT = 3;
    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. */
    /** Current user navigation stack; empty implies recents. */
    public DocumentStack stack = new DocumentStack();
    public DocumentStack stack = new DocumentStack();
    private boolean mStackTouched;
    private boolean mStackTouched;
    private boolean mInitialRootChanged;
    private boolean mInitialDocChanged;


    /** Currently active search, overriding any stack. */
    /** Currently active search, overriding any stack. */
    public String currentSearch;
    public String currentSearch;
@@ -108,22 +115,32 @@ public class State implements android.os.Parcelable {
    }
    }


    public void onRootChanged(RootInfo root) {
    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.root = root;
        stack.clear();
        stack.clear();
        mStackTouched = true;
        mStackTouched = true;
    }
    }


    public void pushDocument(DocumentInfo info) {
    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);
        stack.push(info);
        mStackTouched = true;
        mStackTouched = true;
    }
    }


    public void popDocument() {
    public void popDocument() {
        if (DEBUG) Log.d(TAG, "Popping doc off stack.");
        stack.pop();
        stack.pop();
        mStackTouched = true;
        mStackTouched = true;
    }
    }


    public void setStack(DocumentStack stack) {
    public void setStack(DocumentStack stack) {
        if (DEBUG) Log.d(TAG, "Setting the whole darn stack to: " + stack);
        this.stack = stack;
        this.stack = stack;
        mStackTouched = true;
        mStackTouched = true;
    }
    }
@@ -132,6 +149,10 @@ public class State implements android.os.Parcelable {
        return mStackTouched;
        return mStackTouched;
    }
    }


    public boolean initialiLocationHasChanged() {
        return mInitialRootChanged || mInitialDocChanged;
    }

    @Override
    @Override
    public int describeContents() {
    public int describeContents() {
        return 0;
        return 0;
@@ -156,6 +177,8 @@ public class State implements android.os.Parcelable {
        out.writeList(excludedAuthorities);
        out.writeList(excludedAuthorities);
        out.writeInt(openableOnly ? 1 : 0);
        out.writeInt(openableOnly ? 1 : 0);
        out.writeInt(mStackTouched ? 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>() {
    public static final ClassLoaderCreator<State> CREATOR = new ClassLoaderCreator<State>() {
@@ -184,6 +207,8 @@ public class State implements android.os.Parcelable {
            in.readList(state.excludedAuthorities, loader);
            in.readList(state.excludedAuthorities, loader);
            state.openableOnly = in.readInt() != 0;
            state.openableOnly = in.readInt() != 0;
            state.mStackTouched = in.readInt() != 0;
            state.mStackTouched = in.readInt() != 0;
            state.mInitialRootChanged = in.readInt() != 0;
            state.mInitialDocChanged = in.readInt() != 0;
            return state;
            return state;
        }
        }


+15 −8
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
import static com.android.internal.util.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkArgument;


import android.annotation.IntDef;
import android.annotation.StringRes;
import android.annotation.StringRes;
import android.app.Activity;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager;
@@ -100,8 +101,11 @@ import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperations;
import com.android.documentsui.services.FileOperations;

import com.google.common.collect.Lists;
import com.google.common.collect.Lists;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.List;
@@ -111,6 +115,13 @@ import java.util.List;
 */
 */
public class DirectoryFragment extends Fragment implements DocumentsAdapter.Environment {
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_NORMAL = 1;
    public static final int TYPE_SEARCH = 2;
    public static final int TYPE_SEARCH = 2;
    public static final int TYPE_RECENT_OPEN = 3;
    public static final int TYPE_RECENT_OPEN = 3;
@@ -147,7 +158,7 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
    private RecyclerView mRecView;
    private RecyclerView mRecView;
    private ListeningGestureDetector mGestureDetector;
    private ListeningGestureDetector mGestureDetector;


    private int mType = TYPE_NORMAL;
    private @ResultType int mType = TYPE_NORMAL;
    private String mStateKey;
    private String mStateKey;


    private int mLastSortOrder = SORT_ORDER_UNKNOWN;
    private int mLastSortOrder = SORT_ORDER_UNKNOWN;
@@ -262,7 +273,7 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
        mType = getArguments().getInt(EXTRA_TYPE);
        mType = getArguments().getInt(EXTRA_TYPE);
        mStateKey = buildStateKey(root, doc);
        mStateKey = buildStateKey(root, doc);


        mTuner = FragmentTuner.pick(state);
        mTuner = FragmentTuner.pick(getContext(), state);
        mClipper = new DocumentClipper(context);
        mClipper = new DocumentClipper(context);


        boolean hideGridTitles;
        boolean hideGridTitles;
@@ -320,12 +331,6 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi


                updateDisplayState();
                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
                // Restore any previous instance state
                final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
                final SparseArray<Parcelable> container = state.dirState.remove(mStateKey);
                if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) {
                if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) {
@@ -338,6 +343,8 @@ public class DirectoryFragment extends Fragment implements DocumentsAdapter.Envi
                }
                }


                mLastSortOrder = state.derivedSortOrder;
                mLastSortOrder = state.derivedSortOrder;

                mTuner.onModelLoaded(mModel, mType);
            }
            }


            @Override
            @Override
+55 −16
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.documentsui.dirlist;
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_BROWSE;
import static com.android.documentsui.State.ACTION_CREATE;
import static com.android.documentsui.State.ACTION_CREATE;
import static com.android.documentsui.State.ACTION_GET_CONTENT;
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.documentsui.State.ACTION_OPEN_TREE;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkArgument;


import com.android.documentsui.Menus;
import android.content.Context;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
import com.android.documentsui.State;

import android.os.SystemProperties;
import android.os.SystemProperties;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Document;
import android.util.Log;
import android.view.Menu;
import android.view.Menu;
import android.view.MenuItem;
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.
 * Providers support for specializing the DirectoryFragment to the "host" Activity.
 * Feel free to expand the role of this class to handle other specializations.
 * Feel free to expand the role of this class to handle other specializations.
 */
 */
public abstract class FragmentTuner {
public abstract class FragmentTuner {


    final Context mContext;
    final State mState;
    final State mState;


    public FragmentTuner(State state) {
    public FragmentTuner(Context context, State state) {
        mContext = context;
        mState = state;
        mState = state;
    }
    }


    public static FragmentTuner pick(State state) {
    public static FragmentTuner pick(Context context, State state) {
        switch (state.action) {
        switch (state.action) {
            case ACTION_BROWSE:
            case ACTION_BROWSE:
                return new FilesTuner(state);
                return new FilesTuner(context, state);
            case ACTION_MANAGE:
            case ACTION_MANAGE:
                return new DownloadsTuner(state);
                return new DownloadsTuner(context, state);
            default:
            default:
                return new DocumentsTuner(state);
                return new DocumentsTuner(context, state);
        }
        }
    }
    }


@@ -76,13 +84,15 @@ public abstract class FragmentTuner {
        return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
        return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
    }
    }


    abstract void onModelLoaded(Model model, @ResultType int resultType);

    /**
    /**
     * Provides support for Platform specific specializations of DirectoryFragment.
     * Provides support for Platform specific specializations of DirectoryFragment.
     */
     */
    private static final class DocumentsTuner extends FragmentTuner {
    private static final class DocumentsTuner extends FragmentTuner {


        public DocumentsTuner(State state) {
        public DocumentsTuner(Context context, State state) {
            super(state);
            super(context, state);
        }
        }


        @Override
        @Override
@@ -154,6 +164,16 @@ public abstract class FragmentTuner {
            moveTo.setEnabled(moveEnabled);
            moveTo.setEnabled(moveEnabled);
            rename.setVisible(false);
            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 {
    private static final class DownloadsTuner extends FragmentTuner {


        public DownloadsTuner(State state) {
        public DownloadsTuner(Context context, State state) {
            super(state);
            super(context, state);
        }
        }


        @Override
        @Override
@@ -189,6 +209,9 @@ public abstract class FragmentTuner {
            moveTo.setEnabled(moveEnabled);
            moveTo.setEnabled(moveEnabled);
            rename.setVisible(false);
            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 {
    private static final class FilesTuner extends FragmentTuner {


        public FilesTuner(State state) {
        private static final String TAG = "FilesTuner";
            super(state);

        public FilesTuner(Context context, State state) {
            super(context, state);
        }
        }


        @Override
        @Override
@@ -221,9 +246,23 @@ public abstract class FragmentTuner {


            Menus.disableHiddenItems(menu, copy, paste);
            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) {
    private static boolean isDirectory(String mimeType) {
        return Document.MIME_TYPE_DIR.equals(mimeType);
        return Document.MIME_TYPE_DIR.equals(mimeType);
    }
    }

}
}