Merge "Disable share when dirs selected." into nyc-dev

This commit is contained in:
Steve McKay
2016-05-04 16:46:18 +00:00
committed by Android (Google) Code Review
3 changed files with 91 additions and 60 deletions

View File

@@ -17,6 +17,7 @@
package com.android.documentsui;
import android.annotation.Nullable;
import android.provider.DocumentsContract.Document;
import com.android.documentsui.model.DocumentInfo;
import com.android.internal.util.Predicate;
@@ -99,4 +100,8 @@ public class MimePredicate implements Predicate<DocumentInfo> {
public static boolean isApkType(@Nullable String mimeType) {
return APK_TYPE.equals(mimeType);
}
public static boolean isDirectoryType(@Nullable String mimeType) {
return Document.MIME_TYPE_DIR.equals(mimeType);
}
}

View File

@@ -62,7 +62,6 @@ import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.DragEvent;
import android.view.GestureDetector;
@@ -89,6 +88,7 @@ import com.android.documentsui.Events.MotionInputEvent;
import com.android.documentsui.Menus;
import com.android.documentsui.MessageBar;
import com.android.documentsui.Metrics;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
import com.android.documentsui.RecentsLoader;
import com.android.documentsui.RootsCache;
@@ -103,6 +103,7 @@ import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.documentsui.services.FileOperations;
import com.google.common.collect.Lists;
import java.lang.annotation.Retention;
@@ -110,7 +111,6 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -458,13 +458,17 @@ public class DirectoryFragment extends Fragment
* ActionMode when there is a selection, canceling it when there is no selection,
* and clearing selection when action mode is explicitly exited by the user.
*/
private final class SelectionModeListener
implements MultiSelectManager.Callback, ActionMode.Callback {
private final class SelectionModeListener implements MultiSelectManager.Callback,
ActionMode.Callback, FragmentTuner.SelectionDetails {
private Selection mSelected = new Selection();
private int mNoCopyCount = 0;
// Partial files are files that haven't been fully downloaded.
private int mPartialCount = 0;
private int mDirectoryCount = 0;
private int mNoDeleteCount = 0;
private int mNoRenameCount = -1;
private int mNoRenameCount = 0;
private Menu mMenu;
@Override
@@ -506,14 +510,19 @@ public class DirectoryFragment extends Fragment
// TODO: Should this be happening in onSelectionChanged? Technically this callback is
// triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
// selection changes here)
final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
if (MimePredicate.isDirectoryType(mimeType)) {
mDirectoryCount += selected ? 1 : -1;
}
final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
if ((docFlags & Document.FLAG_PARTIAL) != 0) {
mNoCopyCount += selected ? 1 : -1;
mPartialCount += selected ? 1 : -1;
}
if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
mNoDeleteCount += selected ? 1 : -1;
}
if ((docFlags & Document.FLAG_SUPPORTS_RENAME) != 0) {
if ((docFlags & Document.FLAG_SUPPORTS_RENAME) == 0) {
mNoRenameCount += selected ? 1 : -1;
}
}
@@ -552,8 +561,11 @@ public class DirectoryFragment extends Fragment
// clear selection
mSelectionManager.clearSelection();
mSelected.clear();
mDirectoryCount = 0;
mPartialCount = 0;
mNoDeleteCount = 0;
mNoRenameCount = -1;
mNoRenameCount = 0;
// Re-enable TalkBack for the toolbars, as they are no longer covered by action mode.
final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
@@ -601,24 +613,29 @@ public class DirectoryFragment extends Fragment
return true;
}
boolean canCopySelection() {
return mNoCopyCount == 0;
@Override
public boolean containsDirectories() {
return mDirectoryCount > 0;
}
boolean canDeleteSelection() {
@Override
public boolean containsPartialFiles() {
return mPartialCount > 0;
}
@Override
public boolean canDelete() {
return mNoDeleteCount == 0;
}
boolean canRenameSelection() {
@Override
public boolean canRename() {
return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1;
}
private void updateActionMenu() {
assert(mMenu != null);
// Delegate update logic to our owning action, since specialized logic is desired.
mTuner.updateActionMenu(
mMenu, mType, canCopySelection(), canDeleteSelection(), canRenameSelection());
mTuner.updateActionMenu(mMenu, this);
Menus.disableHiddenItems(mMenu);
}
@@ -1174,7 +1191,7 @@ public class DirectoryFragment extends Fragment
view.setOnDragListener(mOnDragListener);
}
if (mTuner.allowDragNDrop()) {
if (mTuner.dragAndDropEnabled()) {
// Make all items draggable.
view.setOnLongClickListener(onLongClickListener);
}
@@ -1761,7 +1778,7 @@ public class DirectoryFragment extends Fragment
mRoot.authority, mRoot.rootId, mQuery)
: DocumentsContract.buildChildDocumentsUri(
mDocument.authority, mDocument.documentId);
if (mTuner.enableManagedMode()) {
if (mTuner.managedModeEnabled()) {
contentsUri = DocumentsContract.setManageMode(contentsUri);
}
return new DirectoryLoader(

View File

@@ -58,9 +58,6 @@ public abstract class FragmentTuner {
}
}
public abstract void updateActionMenu(
Menu menu, @ResultType int dirType,
boolean canCopy, boolean canDelete, boolean canRename);
// Subtly different from isDocumentEnabled. The reason may be illuminated as follows.
// A folder is enabled such that it may be double clicked, even in settings
@@ -73,18 +70,23 @@ public abstract class FragmentTuner {
return true;
}
abstract void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch);
/**
* When managed mode is enabled, active downloads will be visible in the UI.
* Presumably this should only be true when in the downloads directory.
*/
abstract boolean enableManagedMode();
boolean managedModeEnabled() {
return false;
}
/**
* Whether drag n' drop is allowed in this context
*/
abstract boolean allowDragNDrop();
boolean dragAndDropEnabled() {
return false;
}
abstract void updateActionMenu(Menu menu, SelectionDetails selection);
abstract void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch);
/**
* Provides support for Platform specific specializations of DirectoryFragment.
@@ -105,7 +107,7 @@ public abstract class FragmentTuner {
return false;
}
if (isDirectory(docMimeType)) {
if (MimePredicate.isDirectoryType(docMimeType)) {
return false;
}
@@ -121,9 +123,9 @@ public abstract class FragmentTuner {
}
@Override
public boolean isDocumentEnabled(String docMimeType, int docFlags) {
public boolean isDocumentEnabled(String mimeType, int docFlags) {
// Directories are always enabled.
if (isDirectory(docMimeType)) {
if (MimePredicate.isDirectoryType(mimeType)) {
return true;
}
@@ -141,13 +143,11 @@ public abstract class FragmentTuner {
}
}
return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
return MimePredicate.mimeMatches(mState.acceptMimes, mimeType);
}
@Override
public void updateActionMenu(
Menu menu, @ResultType int dirType,
boolean canCopy, boolean canDelete, boolean canRename) {
public void updateActionMenu(Menu menu, SelectionDetails selection) {
MenuItem open = menu.findItem(R.id.menu_open);
MenuItem share = menu.findItem(R.id.menu_share);
@@ -155,8 +155,8 @@ public abstract class FragmentTuner {
MenuItem rename = menu.findItem(R.id.menu_rename);
MenuItem selectAll = menu.findItem(R.id.menu_select_all);
open.setVisible(mState.action == ACTION_GET_CONTENT ||
mState.action == ACTION_OPEN);
open.setVisible(mState.action == ACTION_GET_CONTENT
|| mState.action == ACTION_OPEN);
share.setVisible(false);
delete.setVisible(false);
rename.setVisible(false);
@@ -191,16 +191,6 @@ public abstract class FragmentTuner {
}
mModelPreviousLoaded = true;
}
@Override
public boolean enableManagedMode() {
return false;
}
@Override
public boolean allowDragNDrop() {
return false;
}
}
/**
@@ -217,29 +207,39 @@ public abstract class FragmentTuner {
}
@Override
public void updateActionMenu(
Menu menu, @ResultType int dirType,
boolean canCopy, boolean canDelete, boolean canRename) {
public void updateActionMenu(Menu menu, SelectionDetails selection) {
menu.findItem(R.id.menu_open).setVisible(false); // "open" is never used in Files.
// Commands accessible only via keyboard...
MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
copy.setEnabled(canCopy);
// Commands visible in the UI...
MenuItem rename = menu.findItem(R.id.menu_rename);
MenuItem moveTo = menu.findItem(R.id.menu_move_to);
MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
MenuItem share = menu.findItem(R.id.menu_share);
MenuItem delete = menu.findItem(R.id.menu_delete);
// copy is not visible, keyboard only
copy.setEnabled(!selection.containsPartialFiles());
// Commands usually on action-bar, so we always manage visibility.
share.setVisible(!selection.containsDirectories() && !selection.containsPartialFiles());
delete.setVisible(selection.canDelete());
share.setEnabled(!selection.containsDirectories() && !selection.containsPartialFiles());
delete.setEnabled(selection.canDelete());
// Commands always in overflow, so we don't bother showing/hiding...
copyTo.setVisible(true);
moveTo.setVisible(true);
rename.setVisible(true);
copyTo.setEnabled(canCopy);
moveTo.setEnabled(canCopy && canDelete);
rename.setEnabled(canRename);
menu.findItem(R.id.menu_share).setVisible(true);
menu.findItem(R.id.menu_delete).setVisible(canDelete);
menu.findItem(R.id.menu_open).setVisible(false);
copyTo.setEnabled(!selection.containsPartialFiles());
moveTo.setEnabled(!selection.containsPartialFiles() && selection.canDelete());
rename.setEnabled(!selection.containsPartialFiles() && selection.canRename());
Menus.disableHiddenItems(menu, copy, paste);
}
@@ -256,7 +256,7 @@ public abstract class FragmentTuner {
}
@Override
public boolean enableManagedMode() {
public boolean managedModeEnabled() {
// When in downloads top level directory, we also show active downloads.
// And while we don't allow folders in Downloads, we do allow Zip files in
// downloads that themselves can be opened and viewed like directories.
@@ -267,12 +267,21 @@ public abstract class FragmentTuner {
}
@Override
public boolean allowDragNDrop() {
public boolean dragAndDropEnabled() {
return true;
}
}
private static boolean isDirectory(String mimeType) {
return Document.MIME_TYPE_DIR.equals(mimeType);
/**
* Access to meta data about the selection.
*/
interface SelectionDetails {
boolean containsDirectories();
boolean containsPartialFiles();
// TODO: Update these to express characteristics instead of answering concrete questions,
// since the answer to those questions is (or can be) activity specific.
boolean canDelete();
boolean canRename();
}
}