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

Commit fb3445c9 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Sort order is sticky for session, back leaves.

Instead of persisting sort order per-directory, the order is now
sticky for that session.  Any user selected sort order takes
precedence over an ordering hinted by a backend.

When a restored DocumentStack is untouched, the back key now leaves
the dialog, instead of popping from the restored stack.

Persist list/grid mode changes async.

Bug: 10659604, 10672973
Change-Id: I9f022a081c014537447c9c2af10e19d8cd9566aa
parent 3f4c205f
Loading
Loading
Loading
Loading
+48 −20
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
@@ -65,6 +66,7 @@ import android.widget.TextView;
import android.widget.Toast;

import com.android.documentsui.DocumentsActivity.State;
import com.android.documentsui.RecentsProvider.StateColumns;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
import com.android.internal.util.Predicate;
@@ -190,11 +192,13 @@ public class DirectoryFragment extends Fragment {
                    case TYPE_NORMAL:
                        contentsUri = DocumentsContract.buildChildDocumentsUri(
                                doc.authority, doc.documentId);
                        return new DirectoryLoader(context, root, doc, contentsUri);
                        return new DirectoryLoader(
                                context, root, doc, contentsUri, state.userSortOrder);
                    case TYPE_SEARCH:
                        contentsUri = DocumentsContract.buildSearchDocumentsUri(
                                doc.authority, doc.documentId, query);
                        return new DirectoryLoader(context, root, doc, contentsUri);
                        return new DirectoryLoader(
                                context, root, doc, contentsUri, state.userSortOrder);
                    case TYPE_RECENT_OPEN:
                        final RootsCache roots = DocumentsApplication.getRootsCache(context);
                        final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
@@ -212,14 +216,14 @@ public class DirectoryFragment extends Fragment {

                // Push latest state up to UI
                // TODO: if mode change was racing with us, don't overwrite it
                state.mode = result.mode;
                state.sortOrder = result.sortOrder;
                state.derivedMode = result.mode;
                state.derivedSortOrder = result.sortOrder;
                ((DocumentsActivity) context).onStateChanged();

                updateDisplayState();

                if (mLastSortOrder != result.sortOrder) {
                    mLastSortOrder = result.sortOrder;
                if (mLastSortOrder != state.derivedSortOrder) {
                    mLastSortOrder = state.derivedSortOrder;
                    mListView.smoothScrollToPosition(0);
                    mGridView.smoothScrollToPosition(0);
                }
@@ -244,12 +248,36 @@ public class DirectoryFragment extends Fragment {
    }

    public void onUserSortOrderChanged() {
        // User change always triggers reload
        // Sort order change always triggers reload; we'll trigger state change
        // on the flip side.
        getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
    }

    public void onUserModeChanged() {
        // Mode change is just display; no need to reload
        final ContentResolver resolver = getActivity().getContentResolver();
        final State state = getDisplayState(this);

        final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
        final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);

        final Uri stateUri = RecentsProvider.buildState(
                root.authority, root.rootId, doc.documentId);
        final ContentValues values = new ContentValues();
        values.put(StateColumns.MODE, state.userMode);

        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                resolver.insert(stateUri, values);
                return null;
            }
        }.execute();

        // Mode change is just visual change; no need to kick loader, and
        // deliver change event immediately.
        state.derivedMode = state.userMode;
        ((DocumentsActivity) getActivity()).onStateChanged();

        updateDisplayState();
    }

@@ -258,11 +286,11 @@ public class DirectoryFragment extends Fragment {

        mFilter = new MimePredicate(state.acceptMimes);

        if (mLastMode == state.mode) return;
        mLastMode = state.mode;
        if (mLastMode == state.derivedMode) return;
        mLastMode = state.derivedMode;

        mListView.setVisibility(state.mode == MODE_LIST ? View.VISIBLE : View.GONE);
        mGridView.setVisibility(state.mode == MODE_GRID ? View.VISIBLE : View.GONE);
        mListView.setVisibility(state.derivedMode == MODE_LIST ? View.VISIBLE : View.GONE);
        mGridView.setVisibility(state.derivedMode == MODE_GRID ? View.VISIBLE : View.GONE);

        final int choiceMode;
        if (state.allowMultiple) {
@@ -272,7 +300,7 @@ public class DirectoryFragment extends Fragment {
        }

        final int thumbSize;
        if (state.mode == MODE_GRID) {
        if (state.derivedMode == MODE_GRID) {
            thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
            mListView.setAdapter(null);
            mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -281,7 +309,7 @@ public class DirectoryFragment extends Fragment {
            mGridView.setNumColumns(GridView.AUTO_FIT);
            mGridView.setChoiceMode(choiceMode);
            mCurrentView = mGridView;
        } else if (state.mode == MODE_LIST) {
        } else if (state.derivedMode == MODE_LIST) {
            thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
            mGridView.setAdapter(null);
            mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -289,7 +317,7 @@ public class DirectoryFragment extends Fragment {
            mListView.setChoiceMode(choiceMode);
            mCurrentView = mListView;
        } else {
            throw new IllegalStateException("Unknown state " + state.mode);
            throw new IllegalStateException("Unknown state " + state.derivedMode);
        }

        mThumbSize = new Point(thumbSize, thumbSize);
@@ -505,9 +533,9 @@ public class DirectoryFragment extends Fragment {

            if (convertView == null) {
                final LayoutInflater inflater = LayoutInflater.from(context);
                if (state.mode == MODE_LIST) {
                if (state.derivedMode == MODE_LIST) {
                    convertView = inflater.inflate(R.layout.item_message_list, parent, false);
                } else if (state.mode == MODE_GRID) {
                } else if (state.derivedMode == MODE_GRID) {
                    convertView = inflater.inflate(R.layout.item_message_grid, parent, false);
                } else {
                    throw new IllegalStateException();
@@ -582,9 +610,9 @@ public class DirectoryFragment extends Fragment {

            if (convertView == null) {
                final LayoutInflater inflater = LayoutInflater.from(context);
                if (state.mode == MODE_LIST) {
                if (state.derivedMode == MODE_LIST) {
                    convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
                } else if (state.mode == MODE_GRID) {
                } else if (state.derivedMode == MODE_GRID) {
                    convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
                } else {
                    throw new IllegalStateException();
@@ -618,7 +646,7 @@ public class DirectoryFragment extends Fragment {
            }

            final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
            final boolean allowThumbnail = (state.mode == MODE_GRID)
            final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
                    || MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);

            if (supportsThumbnail && allowThumbnail) {
+7 −6
Original line number Diff line number Diff line
@@ -65,15 +65,18 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
    private final RootInfo mRoot;
    private final DocumentInfo mDoc;
    private final Uri mUri;
    private final int mUserSortOrder;

    private CancellationSignal mSignal;
    private DirectoryResult mResult;

    public DirectoryLoader(Context context, RootInfo root, DocumentInfo doc, Uri uri) {
    public DirectoryLoader(
            Context context, RootInfo root, DocumentInfo doc, Uri uri, int userSortOrder) {
        super(context);
        mRoot = root;
        mDoc = doc;
        mUri = uri;
        mUserSortOrder = userSortOrder;
    }

    @Override
@@ -91,7 +94,6 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
        final DirectoryResult result = new DirectoryResult();

        int userMode = State.MODE_UNKNOWN;
        int userSortOrder = State.SORT_ORDER_UNKNOWN;

        // Pick up any custom modes requested by user
        Cursor cursor = null;
@@ -101,7 +103,6 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
            cursor = resolver.query(stateUri, null, null, null, null);
            if (cursor.moveToFirst()) {
                userMode = getCursorInt(cursor, StateColumns.MODE);
                userSortOrder = getCursorInt(cursor, StateColumns.SORT_ORDER);
            }
        } finally {
            IoUtils.closeQuietly(cursor);
@@ -117,8 +118,8 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
            }
        }

        if (userSortOrder != State.SORT_ORDER_UNKNOWN) {
            result.sortOrder = userSortOrder;
        if (mUserSortOrder != State.SORT_ORDER_UNKNOWN) {
            result.sortOrder = mUserSortOrder;
        } else {
            if ((mDoc.flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0) {
                result.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
@@ -127,7 +128,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
            }
        }

        Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + userSortOrder + " --> mode="
        Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
                + result.mode + ", sortOrder=" + result.sortOrder);

        try {
+31 −42
Original line number Diff line number Diff line
@@ -170,10 +170,6 @@ public class DocumentsActivity extends Activity {
        mState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
        mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);

        if (mState.action == ACTION_MANAGE) {
            mState.sortOrder = SORT_ORDER_LAST_MODIFIED;
        }

        if (mState.action == ACTION_MANAGE) {
            final Uri uri = intent.getData();
            final String rootId = DocumentsContract.getRootId(uri);
@@ -348,8 +344,8 @@ public class DocumentsActivity extends Activity {

        if (cwd != null) {
            sort.setVisible(true);
            grid.setVisible(mState.mode != MODE_GRID);
            list.setVisible(mState.mode != MODE_LIST);
            grid.setVisible(mState.derivedMode != MODE_GRID);
            list.setVisible(mState.derivedMode != MODE_LIST);
        } else {
            sort.setVisible(false);
            grid.setVisible(false);
@@ -433,42 +429,25 @@ public class DocumentsActivity extends Activity {
     * Set state sort order based on explicit user action.
     */
    private void setUserSortOrder(int sortOrder) {
        final RootInfo root = getCurrentRoot();
        final DocumentInfo cwd = getCurrentDirectory();

        // TODO: persist async, then trigger rebind
        final Uri stateUri = RecentsProvider.buildState(
                root.authority, root.rootId, cwd.documentId);
        final ContentValues values = new ContentValues();
        values.put(StateColumns.SORT_ORDER, sortOrder);
        getContentResolver().insert(stateUri, values);

        mState.userSortOrder = sortOrder;
        DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
        onStateChanged();
    }

    /**
     * Set state mode based on explicit user action.
     */
    private void setUserMode(int mode) {
        final RootInfo root = getCurrentRoot();
        final DocumentInfo cwd = getCurrentDirectory();

        // TODO: persist async, then trigger rebind
        final Uri stateUri = RecentsProvider.buildState(
                root.authority, root.rootId, cwd.documentId);
        final ContentValues values = new ContentValues();
        values.put(StateColumns.MODE, mode);
        getContentResolver().insert(stateUri, values);

        mState.mode = mode;

        mState.userMode = mode;
        DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
        onStateChanged();
    }

    @Override
    public void onBackPressed() {
        if (!mState.stackTouched) {
            super.onBackPressed();
            return;
        }

        final int size = mState.stack.size();
        if (size > 1) {
            mState.stack.pop();
@@ -564,6 +543,7 @@ public class DocumentsActivity extends Activity {
            }

            while (mState.stack.size() > itemPosition + 1) {
                mState.stackTouched = true;
                mState.stack.pop();
            }
            onCurrentDirectoryChanged();
@@ -629,6 +609,7 @@ public class DocumentsActivity extends Activity {

    public void onStackPicked(DocumentStack stack) {
        mState.stack = stack;
        mState.stackTouched = true;
        onCurrentDirectoryChanged();
    }

@@ -636,6 +617,7 @@ public class DocumentsActivity extends Activity {
        // Clear entire backstack and start in new root
        mState.stack.root = root;
        mState.stack.clear();
        mState.stackTouched = true;

        if (!mRoots.isRecentsRoot(root)) {
            try {
@@ -664,13 +646,8 @@ public class DocumentsActivity extends Activity {
    public void onDocumentPicked(DocumentInfo doc) {
        final FragmentManager fm = getFragmentManager();
        if (doc.isDirectory()) {
            // TODO: query display mode user preference for this dir
            if (doc.isGridPreferred()) {
                mState.mode = MODE_GRID;
            } else {
                mState.mode = MODE_LIST;
            }
            mState.stack.push(doc);
            mState.stackTouched = true;
            onCurrentDirectoryChanged();
        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
            // Explicit file picked, return
@@ -774,13 +751,23 @@ public class DocumentsActivity extends Activity {

    public static class State implements android.os.Parcelable {
        public int action;
        public int mode = MODE_LIST;
        public String[] acceptMimes;
        public int sortOrder = SORT_ORDER_DISPLAY_NAME;

        /** Explicit user choice */
        public int userMode = MODE_UNKNOWN;
        /** Derived after loader */
        public int derivedMode = MODE_LIST;

        /** Explicit user choice */
        public int userSortOrder = SORT_ORDER_UNKNOWN;
        /** Derived after loader */
        public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;

        public boolean allowMultiple = false;
        public boolean showSize = false;
        public boolean localOnly = false;
        public boolean showAdvanced = false;
        public boolean stackTouched = false;

        /** Current user navigation stack; empty implies recents. */
        public DocumentStack stack = new DocumentStack();
@@ -809,13 +796,14 @@ public class DocumentsActivity extends Activity {
        @Override
        public void writeToParcel(Parcel out, int flags) {
            out.writeInt(action);
            out.writeInt(mode);
            out.writeInt(userMode);
            out.writeStringArray(acceptMimes);
            out.writeInt(sortOrder);
            out.writeInt(userSortOrder);
            out.writeInt(allowMultiple ? 1 : 0);
            out.writeInt(showSize ? 1 : 0);
            out.writeInt(localOnly ? 1 : 0);
            out.writeInt(showAdvanced ? 1 : 0);
            out.writeInt(stackTouched ? 1 : 0);
            DurableUtils.writeToParcel(out, stack);
            out.writeString(currentSearch);
        }
@@ -825,13 +813,14 @@ public class DocumentsActivity extends Activity {
            public State createFromParcel(Parcel in) {
                final State state = new State();
                state.action = in.readInt();
                state.mode = in.readInt();
                state.userMode = in.readInt();
                state.acceptMimes = in.readStringArray();
                state.sortOrder = in.readInt();
                state.userSortOrder = in.readInt();
                state.allowMultiple = in.readInt() != 0;
                state.showSize = in.readInt() != 0;
                state.localOnly = in.readInt() != 0;
                state.showAdvanced = in.readInt() != 0;
                state.stackTouched = in.readInt() != 0;
                DurableUtils.readFromParcel(in, state.stack);
                state.currentSearch = in.readString();
                return state;