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

Commit db6ec491 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow root item accepts drag and drop." into nyc-andromeda-dev

parents 40be122b a5588b65
Loading
Loading
Loading
Loading
+30 −13
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ import com.android.documentsui.dirlist.Model;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperations;

import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -71,6 +73,32 @@ import java.util.concurrent.Executor;
public abstract class BaseActivity extends Activity
        implements SearchManagerListener, NavigationViewManager.Environment {

    public final FileOperations.Callback fileOpCallback = (status, opType, docCount) -> {
        if (status == FileOperations.Callback.STATUS_REJECTED) {
            Snackbars.showPasteFailed(this);
            return;
        }

        if (docCount == 0) {
            // Nothing has been pasted, so there is no need to show a snackbar.
            return;
        }

        switch (opType) {
            case FileOperationService.OPERATION_MOVE:
                Snackbars.showMove(this, docCount);
                break;
            case FileOperationService.OPERATION_COPY:
                Snackbars.showCopy(this, docCount);
                break;
            case FileOperationService.OPERATION_DELETE:
                // We don't show anything for deletion.
                break;
            default:
                throw new UnsupportedOperationException("Unsupported Operation: " + opType);
        }
    };

    private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests";

    State mState;
@@ -706,17 +734,6 @@ public abstract class BaseActivity extends Activity
        mNavDrawerHasFocus = !mNavDrawerHasFocus;
    }

    DocumentInfo getRootDocumentBlocking(RootInfo root) {
        try {
            final Uri uri = DocumentsContract.buildDocumentUri(
                    root.authority, root.documentId);
            return DocumentInfo.fromUri(getContentResolver(), uri);
        } catch (FileNotFoundException e) {
            Log.w(mTag, "Failed to find root", e);
            return null;
        }
    }

    /**
     * Pops the top entry off the directory stack, and returns the user to the previous directory.
     * If the directory stack only contains one item, this method does nothing.
@@ -780,7 +797,7 @@ public abstract class BaseActivity extends Activity

        @Override
        protected DocumentInfo run(Void... params) {
            return mOwner.getRootDocumentBlocking(mRoot);
            return mRoot.getRootDocumentBlocking(mOwner);
        }

        @Override
@@ -816,7 +833,7 @@ public abstract class BaseActivity extends Activity
            final RootInfo defaultRoot = mOwner.mRoots.getDefaultRootBlocking(mOwner.mState);
            assert(defaultRoot != null);
            if (!defaultRoot.isRecents()) {
                mDefaultRootDocument = mOwner.getRootDocumentBlocking(defaultRoot);
                mDefaultRootDocument = defaultRoot.getRootDocumentBlocking(mOwner);
            }
            return defaultRoot;
        }
+1 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ abstract class CheckedTask<Input, Output>
        finish(result);
    }

    @FunctionalInterface
    interface Check {
        boolean stop();
    }
+1 −1
Original line number Diff line number Diff line
@@ -519,7 +519,7 @@ public class FilesActivity extends BaseActivity {
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Failed to resolve DocumentInfo from Uri: " + uri);
            }
            mState.stack.add(mOwner.getRootDocumentBlocking(root));
            mState.stack.add(root.getRootDocumentBlocking(mOwner));
            return null;
        }

+2 −3
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.ViewConfiguration;

import com.android.documentsui.ItemDragListener.DragHost;
import com.android.internal.annotations.VisibleForTesting;
@@ -39,7 +38,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener {
    private static final String TAG = "ItemDragListener";

    @VisibleForTesting
    static final int SPRING_TIMEOUT = ViewConfiguration.getLongPressTimeout();
    static final int SPRING_TIMEOUT = 1000;

    protected final H mDragHost;
    private final Timer mHoverTimer;
@@ -82,7 +81,7 @@ public class ItemDragListener<H extends DragHost> implements OnDragListener {
        TimerTask task = createOpenTask(v);
        assert (task != null);
        v.setTag(R.id.drag_hovering_tag, task);
        mHoverTimer.schedule(task, ViewConfiguration.getLongPressTimeout());
        mHoverTimer.schedule(task, SPRING_TIMEOUT);
    }

    private void handleLocationEvent(View v, float x, float y) {
+70 −8
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
@@ -33,16 +34,14 @@ import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.ContextMenu;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -60,7 +59,11 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.android.documentsui.CheckedTask.Check;
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
import com.android.documentsui.services.FileOperations;

import java.util.ArrayList;
import java.util.Collection;
@@ -81,6 +84,20 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
    private static final String TAG = "RootsFragment";
    private static final String EXTRA_INCLUDE_APPS = "includeApps";

    private final OnDragListener mDragListener = new ItemDragListener<RootsFragment>(this) {
        @Override
        public boolean handleDropEventChecked(View v, DragEvent event) {
            final int position = (Integer) v.getTag(R.id.item_position_tag);
            final Item item = mAdapter.getItem(position);

            assert(item.isDropTarget());

            BaseActivity activity = getBaseActivity();
            return item.dropOn(event.getClipData(), activity, RootsFragment.this::isDetached,
                    activity.fileOpCallback);
        }
    };

    private ListView mList;
    private RootsAdapter mAdapter;
    private LoaderCallbacks<Collection<RootInfo>> mCallbacks;
@@ -165,8 +182,8 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost

                Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS);

                mAdapter = new RootsAdapter(context, result, handlerAppIntent, state,
                        new ItemDragListener<>(RootsFragment.this));
                mAdapter =
                        new RootsAdapter(context, result, handlerAppIntent, state, mDragListener);
                mList.setAdapter(mAdapter);

                onCurrentRootChanged();
@@ -247,12 +264,12 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
     * In RootsFragment we open the hovered root.
     */
    @Override
    public void onViewHovered(View view) {
    public void onViewHovered(View v) {
        // SpacerView doesn't have DragListener so this view is guaranteed to be a RootItemView.
        RootItemView itemView = (RootItemView) view;
        RootItemView itemView = (RootItemView) v;
        itemView.drawRipple();

        final int position = (Integer) view.getTag(R.id.item_position_tag);
        final int position = (Integer) v.getTag(R.id.item_position_tag);
        final Item item = mAdapter.getItem(position);
        item.open(this);
    }
@@ -374,6 +391,11 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
        abstract boolean isDropTarget();

        abstract void open(RootsFragment fragment);

        boolean dropOn(ClipData data, Context context, Check check,
                FileOperations.Callback callback) {
            return false;
        }
    }

    private static class RootItem extends Item {
@@ -440,6 +462,14 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
            Metrics.logRootVisited(fragment.getActivity(), root);
            activity.onRootPicked(root);
        }

        @Override
        boolean dropOn(
                ClipData data, Context context, Check check, FileOperations.Callback callback) {
            ProviderExecutor executor = ProviderExecutor.forAuthority(root.authority);
            new DropOnRootTask(data, root, context, check, callback).executeOnExecutor(executor);
            return true;
        }
    }

    private static class SpacerItem extends Item {
@@ -518,6 +548,38 @@ public class RootsFragment extends Fragment implements ItemDragListener.DragHost
        }
    }

    private static class DropOnRootTask extends CheckedTask<Void, DocumentInfo> {
        private ClipData mData;
        private RootInfo mDstRoot;
        private Context mContext;
        private FileOperations.Callback mCallback;

        private DropOnRootTask(ClipData data, RootInfo dstRoot, Context context, Check check,
                FileOperations.Callback callback) {
            super(check);
            mData = data;
            mDstRoot = dstRoot;
            mContext = context;
            mCallback = callback;
        }

        @Override
        public DocumentInfo run(Void... args) {
            return mDstRoot.getRootDocumentBlocking(mContext);
        }

        @Override
        public void finish(DocumentInfo doc) {
            if (doc != null) {
                DocumentClipper clipper =
                        DocumentsApplication.getDocumentClipper(mContext);
                clipper.copyFromClipData(mDstRoot, doc, mData, mCallback);
            } else {
                Log.e(TAG, "Failed to get doc.");
            }
        }
    }

    private static class RootsAdapter extends ArrayAdapter<Item> {
        private static final Map<String, Long> sIdMap = new HashMap<String, Long>();
        // the next available id to associate with a new string id
Loading