Loading src/com/android/documentsui/DragAndDropManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,10 @@ public interface DragAndDropManager { // type of file operations. private boolean mIsCtrlPressed; // Boolean flag for current drag and drop operation. Returns true if the files can only // be copied (ie. Read-Only files) private boolean mMustBeCopied; // Drag events info. These are used to derive state and update drag shadow when user changes // Ctrl key state. private View mView; Loading Loading @@ -231,6 +235,9 @@ public interface DragAndDropManager { List<Uri> uris = new ArrayList<>(srcs.size()); for (DocumentInfo doc : srcs) { uris.add(doc.derivedUri); if (!doc.isRemoveSupported() && !doc.isDeleteSupported()) { mMustBeCopied = true; } } mClipData = mClipper.getClipDataForDocuments( uris, FileOperationService.OPERATION_UNKNOWN, parent); Loading Loading @@ -447,9 +454,14 @@ public interface DragAndDropManager { mClipData = null; mDestDoc = null; mDestRoot = null; mMustBeCopied = false; } private @OpType int calculateOpType(ClipData clipData, RootInfo destRoot) { if (mMustBeCopied) { return FileOperationService.OPERATION_COPY; } final String srcRootUri = clipData.getDescription().getExtras().getString(SRC_ROOT_KEY); final String destRootUri = destRoot.getUri().toString(); Loading src/com/android/documentsui/base/DocumentFilters.java +10 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ public final class DocumentFilters { public static final Predicate<Cursor> ANY = (Cursor c) -> { return true; }; public static final Predicate<Cursor> VIRTUAL = DocumentFilters::isVirtual; public static final Predicate<Cursor> NOT_MOVABLE = DocumentFilters::isNotMovable; private static final Predicate<Cursor> O_SHARABLE = DocumentFilters::isSharableInO; private static final Predicate<Cursor> PREO_SHARABLE = DocumentFilters::isSharablePreO; Loading Loading @@ -70,4 +71,13 @@ public final class DocumentFilters { int flags = getCursorInt(c, Document.COLUMN_FLAGS); return (flags & Document.FLAG_VIRTUAL_DOCUMENT) != 0; } /** * Filter that passes (returns true) for files that can not be moved. */ private static final boolean isNotMovable(Cursor c) { int flags = getCursorInt(c, Document.COLUMN_FLAGS); return (flags & Document.FLAG_SUPPORTS_REMOVE) == 0 && (flags & Document.FLAG_SUPPORTS_DELETE) == 0; } } src/com/android/documentsui/dirlist/DirectoryFragment.java +5 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ import com.android.documentsui.Metrics; import com.android.documentsui.Model; import com.android.documentsui.R; import com.android.documentsui.ThumbnailCache; import com.android.documentsui.base.DocumentFilters; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.DocumentStack; import com.android.documentsui.base.EventHandler; Loading Loading @@ -657,6 +658,10 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On return true; case R.id.menu_move_to: if (mModel.hasDocuments(selection, DocumentFilters.NOT_MOVABLE)) { mInjector.dialogs.showOperationUnsupported(); return true; } // Exit selection mode first, so we avoid deselecting deleted documents. mActionModeController.finishActionMode(); transferDocuments(selection, null, FileOperationService.OPERATION_MOVE); Loading src/com/android/documentsui/files/ActionHandler.java +6 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,12 @@ public class ActionHandler<T extends Activity & Addons> extends AbstractActionHa if (selection.isEmpty()) { return; } if (mModel.hasDocuments(selection, DocumentFilters.NOT_MOVABLE)) { mDialogs.showOperationUnsupported(); return; } mSelectionMgr.clearSelection(); mClipper.clipDocumentsForCut(mModel::getItemUri, selection, mState.stack.peek()); Loading src/com/android/documentsui/ui/DialogController.java +7 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ public interface DialogController { void showProgressDialog(String jobId, FileOperation operation); void showNoApplicationFound(); void showOperationUnsupported(); void showViewInArchivesUnsupported(); void showDocumentsClipped(int size); Loading Loading @@ -110,7 +111,7 @@ public interface DialogController { public void showFileOperationStatus(@Status int status, @OpType int opType, int docCount) { if (status == FileOperations.Callback.STATUS_REJECTED) { Snackbars.showOperationRejected(mActivity); showOperationUnsupported(); return; } if (status == FileOperations.Callback.STATUS_FAILED) { Loading Loading @@ -181,6 +182,11 @@ public interface DialogController { mActivity, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show(); } @Override public void showOperationUnsupported() { Snackbars.showOperationRejected(mActivity); } @Override public void showViewInArchivesUnsupported() { Snackbars.makeSnackbar(mActivity, R.string.toast_view_in_archives_unsupported, Loading Loading
src/com/android/documentsui/DragAndDropManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,10 @@ public interface DragAndDropManager { // type of file operations. private boolean mIsCtrlPressed; // Boolean flag for current drag and drop operation. Returns true if the files can only // be copied (ie. Read-Only files) private boolean mMustBeCopied; // Drag events info. These are used to derive state and update drag shadow when user changes // Ctrl key state. private View mView; Loading Loading @@ -231,6 +235,9 @@ public interface DragAndDropManager { List<Uri> uris = new ArrayList<>(srcs.size()); for (DocumentInfo doc : srcs) { uris.add(doc.derivedUri); if (!doc.isRemoveSupported() && !doc.isDeleteSupported()) { mMustBeCopied = true; } } mClipData = mClipper.getClipDataForDocuments( uris, FileOperationService.OPERATION_UNKNOWN, parent); Loading Loading @@ -447,9 +454,14 @@ public interface DragAndDropManager { mClipData = null; mDestDoc = null; mDestRoot = null; mMustBeCopied = false; } private @OpType int calculateOpType(ClipData clipData, RootInfo destRoot) { if (mMustBeCopied) { return FileOperationService.OPERATION_COPY; } final String srcRootUri = clipData.getDescription().getExtras().getString(SRC_ROOT_KEY); final String destRootUri = destRoot.getUri().toString(); Loading
src/com/android/documentsui/base/DocumentFilters.java +10 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ public final class DocumentFilters { public static final Predicate<Cursor> ANY = (Cursor c) -> { return true; }; public static final Predicate<Cursor> VIRTUAL = DocumentFilters::isVirtual; public static final Predicate<Cursor> NOT_MOVABLE = DocumentFilters::isNotMovable; private static final Predicate<Cursor> O_SHARABLE = DocumentFilters::isSharableInO; private static final Predicate<Cursor> PREO_SHARABLE = DocumentFilters::isSharablePreO; Loading Loading @@ -70,4 +71,13 @@ public final class DocumentFilters { int flags = getCursorInt(c, Document.COLUMN_FLAGS); return (flags & Document.FLAG_VIRTUAL_DOCUMENT) != 0; } /** * Filter that passes (returns true) for files that can not be moved. */ private static final boolean isNotMovable(Cursor c) { int flags = getCursorInt(c, Document.COLUMN_FLAGS); return (flags & Document.FLAG_SUPPORTS_REMOVE) == 0 && (flags & Document.FLAG_SUPPORTS_DELETE) == 0; } }
src/com/android/documentsui/dirlist/DirectoryFragment.java +5 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ import com.android.documentsui.Metrics; import com.android.documentsui.Model; import com.android.documentsui.R; import com.android.documentsui.ThumbnailCache; import com.android.documentsui.base.DocumentFilters; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.DocumentStack; import com.android.documentsui.base.EventHandler; Loading Loading @@ -657,6 +658,10 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On return true; case R.id.menu_move_to: if (mModel.hasDocuments(selection, DocumentFilters.NOT_MOVABLE)) { mInjector.dialogs.showOperationUnsupported(); return true; } // Exit selection mode first, so we avoid deselecting deleted documents. mActionModeController.finishActionMode(); transferDocuments(selection, null, FileOperationService.OPERATION_MOVE); Loading
src/com/android/documentsui/files/ActionHandler.java +6 −0 Original line number Diff line number Diff line Loading @@ -236,6 +236,12 @@ public class ActionHandler<T extends Activity & Addons> extends AbstractActionHa if (selection.isEmpty()) { return; } if (mModel.hasDocuments(selection, DocumentFilters.NOT_MOVABLE)) { mDialogs.showOperationUnsupported(); return; } mSelectionMgr.clearSelection(); mClipper.clipDocumentsForCut(mModel::getItemUri, selection, mState.stack.peek()); Loading
src/com/android/documentsui/ui/DialogController.java +7 −1 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ public interface DialogController { void showProgressDialog(String jobId, FileOperation operation); void showNoApplicationFound(); void showOperationUnsupported(); void showViewInArchivesUnsupported(); void showDocumentsClipped(int size); Loading Loading @@ -110,7 +111,7 @@ public interface DialogController { public void showFileOperationStatus(@Status int status, @OpType int opType, int docCount) { if (status == FileOperations.Callback.STATUS_REJECTED) { Snackbars.showOperationRejected(mActivity); showOperationUnsupported(); return; } if (status == FileOperations.Callback.STATUS_FAILED) { Loading Loading @@ -181,6 +182,11 @@ public interface DialogController { mActivity, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show(); } @Override public void showOperationUnsupported() { Snackbars.showOperationRejected(mActivity); } @Override public void showViewInArchivesUnsupported() { Snackbars.makeSnackbar(mActivity, R.string.toast_view_in_archives_unsupported, Loading