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

Commit 14380378 authored by Steve McKay's avatar Steve McKay Committed by android-build-merger
Browse files

Merge commit \'1d8b98bd\' into fixMerge

am: 01b21d8b

* commit '01b21d8b':
  Disable share when dirs selected.

Change-Id: I8335e71b05f20018c43641eebb21754aa9664ccc
parents c8c11835 01b21d8b
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.documentsui;
package com.android.documentsui;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.provider.DocumentsContract.Document;


import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentInfo;
import com.android.internal.util.Predicate;
import com.android.internal.util.Predicate;
@@ -99,4 +100,8 @@ public class MimePredicate implements Predicate<DocumentInfo> {
    public static boolean isApkType(@Nullable String mimeType) {
    public static boolean isApkType(@Nullable String mimeType) {
        return APK_TYPE.equals(mimeType);
        return APK_TYPE.equals(mimeType);
    }
    }

    public static boolean isDirectoryType(@Nullable String mimeType) {
        return Document.MIME_TYPE_DIR.equals(mimeType);
    }
}
}
+39 −20
Original line number Original line Diff line number Diff line
@@ -63,7 +63,6 @@ import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ActionMode;
import android.view.DragEvent;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.GestureDetector;
@@ -91,6 +90,7 @@ import com.android.documentsui.Events.MotionInputEvent;
import com.android.documentsui.Menus;
import com.android.documentsui.Menus;
import com.android.documentsui.MessageBar;
import com.android.documentsui.MessageBar;
import com.android.documentsui.Metrics;
import com.android.documentsui.Metrics;
import com.android.documentsui.MimePredicate;
import com.android.documentsui.R;
import com.android.documentsui.R;
import com.android.documentsui.RecentsLoader;
import com.android.documentsui.RecentsLoader;
import com.android.documentsui.RootsCache;
import com.android.documentsui.RootsCache;
@@ -105,6 +105,7 @@ import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.documentsui.services.FileOperationService.OpType;
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.Retention;
@@ -112,7 +113,6 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.HashSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
@@ -460,13 +460,17 @@ public class DirectoryFragment extends Fragment
     * ActionMode when there is a selection, canceling it when there is no selection,
     * 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.
     * and clearing selection when action mode is explicitly exited by the user.
     */
     */
    private final class SelectionModeListener
    private final class SelectionModeListener implements MultiSelectManager.Callback,
            implements MultiSelectManager.Callback, ActionMode.Callback {
            ActionMode.Callback, FragmentTuner.SelectionDetails {


        private Selection mSelected = new Selection();
        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 mNoDeleteCount = 0;
        private int mNoRenameCount = -1;
        private int mNoRenameCount = 0;

        private Menu mMenu;
        private Menu mMenu;


        @Override
        @Override
@@ -508,14 +512,19 @@ public class DirectoryFragment extends Fragment
            // TODO: Should this be happening in onSelectionChanged? Technically this callback is
            // TODO: Should this be happening in onSelectionChanged? Technically this callback is
            // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
            // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
            // selection changes here)
            // 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);
            final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
            if ((docFlags & Document.FLAG_PARTIAL) != 0) {
            if ((docFlags & Document.FLAG_PARTIAL) != 0) {
                mNoCopyCount += selected ? 1 : -1;
                mPartialCount += selected ? 1 : -1;
            }
            }
            if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
            if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
                mNoDeleteCount += selected ? 1 : -1;
                mNoDeleteCount += selected ? 1 : -1;
            }
            }
            if ((docFlags & Document.FLAG_SUPPORTS_RENAME) != 0) {
            if ((docFlags & Document.FLAG_SUPPORTS_RENAME) == 0) {
                mNoRenameCount += selected ? 1 : -1;
                mNoRenameCount += selected ? 1 : -1;
            }
            }
        }
        }
@@ -554,8 +563,11 @@ public class DirectoryFragment extends Fragment
            // clear selection
            // clear selection
            mSelectionManager.clearSelection();
            mSelectionManager.clearSelection();
            mSelected.clear();
            mSelected.clear();

            mDirectoryCount = 0;
            mPartialCount = 0;
            mNoDeleteCount = 0;
            mNoDeleteCount = 0;
            mNoRenameCount = -1;
            mNoRenameCount = 0;


            // Re-enable TalkBack for the toolbars, as they are no longer covered by action mode.
            // Re-enable TalkBack for the toolbars, as they are no longer covered by action mode.
            final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
            final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
@@ -603,24 +615,29 @@ public class DirectoryFragment extends Fragment
            return true;
            return true;
        }
        }


        boolean canCopySelection() {
        @Override
            return mNoCopyCount == 0;
        public boolean containsDirectories() {
            return mDirectoryCount > 0;
        }

        @Override
        public boolean containsPartialFiles() {
            return mPartialCount > 0;
        }
        }


        boolean canDeleteSelection() {
        @Override
        public boolean canDelete() {
            return mNoDeleteCount == 0;
            return mNoDeleteCount == 0;
        }
        }


        boolean canRenameSelection() {
        @Override
        public boolean canRename() {
            return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1;
            return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1;
        }
        }


        private void updateActionMenu() {
        private void updateActionMenu() {
            assert(mMenu != null);
            assert(mMenu != null);

            mTuner.updateActionMenu(mMenu, this);
            // Delegate update logic to our owning action, since specialized logic is desired.
            mTuner.updateActionMenu(
                    mMenu, mType, canCopySelection(), canDeleteSelection(), canRenameSelection());
            Menus.disableHiddenItems(mMenu);
            Menus.disableHiddenItems(mMenu);
        }
        }


@@ -1224,9 +1241,11 @@ public class DirectoryFragment extends Fragment
            view.setOnDragListener(mOnDragListener);
            view.setOnDragListener(mOnDragListener);
        }
        }


        if (mTuner.dragAndDropEnabled()) {
            // Make all items draggable.
            // Make all items draggable.
            view.setOnLongClickListener(onLongClickListener);
            view.setOnLongClickListener(onLongClickListener);
        }
        }
    }


    private View.OnDragListener mOnDragListener = new View.OnDragListener() {
    private View.OnDragListener mOnDragListener = new View.OnDragListener() {
        @Override
        @Override
@@ -1817,7 +1836,7 @@ public class DirectoryFragment extends Fragment
                        mRoot.authority, mRoot.rootId, mQuery)
                        mRoot.authority, mRoot.rootId, mQuery)
                        : DocumentsContract.buildChildDocumentsUri(
                        : DocumentsContract.buildChildDocumentsUri(
                                mDocument.authority, mDocument.documentId);
                                mDocument.authority, mDocument.documentId);
                if (mTuner.enableManagedMode()) {
                if (mTuner.managedModeEnabled()) {
                    contentsUri = DocumentsContract.setManageMode(contentsUri);
                    contentsUri = DocumentsContract.setManageMode(contentsUri);
                }
                }
                return new DirectoryLoader(
                return new DirectoryLoader(
+58 −34
Original line number Original line Diff line number Diff line
@@ -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.
    // 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
    // A folder is enabled such that it may be double clicked, even in settings
@@ -73,13 +70,23 @@ public abstract class FragmentTuner {
        return true;
        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.
     * When managed mode is enabled, active downloads will be visible in the UI.
     * Presumably this should only be true when in the downloads directory.
     * 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
     */
    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.
     * Provides support for Platform specific specializations of DirectoryFragment.
@@ -100,7 +107,7 @@ public abstract class FragmentTuner {
                return false;
                return false;
            }
            }


            if (isDirectory(docMimeType)) {
            if (MimePredicate.isDirectoryType(docMimeType)) {
                return false;
                return false;
            }
            }


@@ -116,9 +123,9 @@ public abstract class FragmentTuner {
        }
        }


        @Override
        @Override
        public boolean isDocumentEnabled(String docMimeType, int docFlags) {
        public boolean isDocumentEnabled(String mimeType, int docFlags) {
            // Directories are always enabled.
            // Directories are always enabled.
            if (isDirectory(docMimeType)) {
            if (MimePredicate.isDirectoryType(mimeType)) {
                return true;
                return true;
            }
            }


@@ -136,13 +143,11 @@ public abstract class FragmentTuner {
                    }
                    }
            }
            }


            return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
            return MimePredicate.mimeMatches(mState.acceptMimes, mimeType);
        }
        }


        @Override
        @Override
        public void updateActionMenu(
        public void updateActionMenu(Menu menu, SelectionDetails selection) {
                Menu menu, @ResultType int dirType,
                boolean canCopy, boolean canDelete, boolean canRename) {


            MenuItem open = menu.findItem(R.id.menu_open);
            MenuItem open = menu.findItem(R.id.menu_open);
            MenuItem share = menu.findItem(R.id.menu_share);
            MenuItem share = menu.findItem(R.id.menu_share);
@@ -150,8 +155,8 @@ public abstract class FragmentTuner {
            MenuItem rename = menu.findItem(R.id.menu_rename);
            MenuItem rename = menu.findItem(R.id.menu_rename);
            MenuItem selectAll = menu.findItem(R.id.menu_select_all);
            MenuItem selectAll = menu.findItem(R.id.menu_select_all);


            open.setVisible(mState.action == ACTION_GET_CONTENT ||
            open.setVisible(mState.action == ACTION_GET_CONTENT
                    mState.action == ACTION_OPEN);
                    || mState.action == ACTION_OPEN);
            share.setVisible(false);
            share.setVisible(false);
            delete.setVisible(false);
            delete.setVisible(false);
            rename.setVisible(false);
            rename.setVisible(false);
@@ -186,11 +191,6 @@ public abstract class FragmentTuner {
            }
            }
            mModelPreviousLoaded = true;
            mModelPreviousLoaded = true;
        }
        }

        @Override
        public boolean enableManagedMode() {
            return false;
        }
    }
    }


    /**
    /**
@@ -207,29 +207,39 @@ public abstract class FragmentTuner {
        }
        }


        @Override
        @Override
        public void updateActionMenu(
        public void updateActionMenu(Menu menu, SelectionDetails selection) {
                Menu menu, @ResultType int dirType,

                boolean canCopy, boolean canDelete, boolean canRename) {
            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 copy = menu.findItem(R.id.menu_copy_to_clipboard);
            MenuItem paste = menu.findItem(R.id.menu_paste_from_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 rename = menu.findItem(R.id.menu_rename);
            MenuItem moveTo = menu.findItem(R.id.menu_move_to);
            MenuItem moveTo = menu.findItem(R.id.menu_move_to);
            MenuItem copyTo = menu.findItem(R.id.menu_copy_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);
            copyTo.setVisible(true);
            moveTo.setVisible(true);
            moveTo.setVisible(true);
            rename.setVisible(true);
            rename.setVisible(true);


            copyTo.setEnabled(canCopy);
            copyTo.setEnabled(!selection.containsPartialFiles());
            moveTo.setEnabled(canCopy && canDelete);
            moveTo.setEnabled(!selection.containsPartialFiles() && selection.canDelete());
            rename.setEnabled(canRename);
            rename.setEnabled(!selection.containsPartialFiles() && selection.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);


            Menus.disableHiddenItems(menu, copy, paste);
            Menus.disableHiddenItems(menu, copy, paste);
        }
        }
@@ -246,7 +256,7 @@ public abstract class FragmentTuner {
        }
        }


        @Override
        @Override
        public boolean enableManagedMode() {
        public boolean managedModeEnabled() {
            // When in downloads top level directory, we also show active downloads.
            // 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
            // 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.
            // downloads that themselves can be opened and viewed like directories.
@@ -255,9 +265,23 @@ public abstract class FragmentTuner {
                    && mState.stack.root.isDownloads()
                    && mState.stack.root.isDownloads()
                    && mState.stack.size() == 1;
                    && mState.stack.size() == 1;
        }
        }

        @Override
        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();
    }
    }
}
}