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
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user