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

Commit 7d75f7bb authored by Garfield Tan's avatar Garfield Tan
Browse files

Refactor RootsFragment to use the same pattern of injection.

Also pull out RootsAdapter and Items from RootsFragment.

Change-Id: I2d81630333a1f7d0fc9bc7e0137ba922ee5a6bbb
parent d890e3be
Loading
Loading
Loading
Loading
+96 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui;

import android.content.ClipData;
import android.content.pm.ResolveInfo;

import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.clipping.DocumentClipper;
import com.android.documentsui.sidebar.EjectRootTask;
import com.android.documentsui.sidebar.RootsFragment;

import java.util.function.BooleanSupplier;
import java.util.function.Consumer;

/**
 * Provides support for specializing the actions (openDocument etc.) to the host activity.
 */
public class ActionHandler<T extends BaseActivity> {

    protected T mActivity;

    public ActionHandler(T activity) {
        mActivity = activity;
    }

    public void openSettings(RootInfo root) {
        throw new UnsupportedOperationException("Can't open settings.");
    }

    public boolean dropOn(ClipData data, RootsFragment fragment, RootInfo root) {
        new GetRootDocumentTask(
                root,
                fragment,
                (DocumentInfo doc) -> dropOn(data, root, doc)
        ).executeOnExecutor(ProviderExecutor.forAuthority(root.authority));
        return true;
    }

    private void dropOn(ClipData data, RootInfo root, DocumentInfo doc) {
        DocumentClipper clipper
                = DocumentsApplication.getDocumentClipper(mActivity);
        clipper.copyFromClipData(root, doc, data, mActivity.fileOpCallback);
    }

    public void ejectRoot(
            RootInfo root, BooleanSupplier ejectCanceledCheck, Consumer<Boolean> listener) {
        assert(ejectCanceledCheck != null);
        ejectRoot(
                root.authority,
                root.rootId,
                ejectCanceledCheck,
                listener);
    }

    private void ejectRoot(
            String authority,
            String rootId,
            BooleanSupplier ejectCanceledCheck,
            Consumer<Boolean> listener) {
        new EjectRootTask(
                mActivity,
                authority,
                rootId,
                ejectCanceledCheck,
                listener).executeOnExecutor(ProviderExecutor.forAuthority(authority));
    }

    public void showAppDetails(ResolveInfo info) {
        throw new UnsupportedOperationException("Can't show app details.");
    }

    public void open(RootInfo root) {
        Metrics.logRootVisited(mActivity, root);
        mActivity.onRootPicked(root);
    }

    public void open(ResolveInfo app) {
        throw new UnsupportedOperationException("Can't open an app.");
    }
}
+11 −40
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ import android.view.View;
import com.android.documentsui.NavigationViewManager.Breadcrumb;
import com.android.documentsui.SearchViewManager.SearchManagerListener;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.DocumentStack;
import com.android.documentsui.base.Events;
import com.android.documentsui.base.LocalPreferences;
import com.android.documentsui.base.PairedTask;
@@ -77,7 +76,6 @@ import com.android.documentsui.sidebar.RootsFragment;
import com.android.documentsui.sorting.SortController;
import com.android.documentsui.sorting.SortModel;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
@@ -158,6 +156,12 @@ public abstract class BaseActivity extends Activity
     */
    public abstract MenuManager getMenuManager();

    /**
     * Provides Activity a means of injection into and specialization of
     * fragment actions.
     */
    public abstract ActionHandler<? extends BaseActivity> getActionHandler();

    public abstract void onDocumentPicked(DocumentInfo doc, Model model);
    public abstract void onDocumentsPicked(List<DocumentInfo> docs);

@@ -311,7 +315,11 @@ public abstract class BaseActivity extends Activity
        if (mRoots.isRecentsRoot(root)) {
            refreshCurrentRootAndDirectory(AnimationView.ANIM_NONE);
        } else {
            new PickRootTask(this, root).executeOnExecutor(getExecutorForCurrentDirectory());
            new GetRootDocumentTask(
                    root,
                    this,
                    this::openContainerDocument)
                    .executeOnExecutor(getExecutorForCurrentDirectory());
        }
    }

@@ -630,18 +638,6 @@ public abstract class BaseActivity extends Activity
        return false;
    }

    public void onStackPicked(DocumentStack stack) {
        try {
            // Update the restored stack to ensure we have freshest data
            stack.updateDocuments(getContentResolver());
            mState.setStack(stack);
            refreshCurrentRootAndDirectory(AnimationView.ANIM_SIDE);

        } catch (FileNotFoundException e) {
            Log.w(mTag, "Failed to restore stack: " + e);
        }
    }

    /**
     * Declare a global key handler to route key events when there isn't a specific focus view. This
     * covers the scenario where a user opens DocumentsUI and just starts typing.
@@ -759,34 +755,9 @@ public abstract class BaseActivity extends Activity
                        return false;
                    }
                });
                new Handler().post(new Runnable() {
                    @Override public void run() {
            }
        });
    }
        });
    }

    private static final class PickRootTask extends PairedTask<BaseActivity, Void, DocumentInfo> {
        private RootInfo mRoot;

        public PickRootTask(BaseActivity activity, RootInfo root) {
            super(activity);
            mRoot = root;
        }

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

        @Override
        protected void finish(DocumentInfo result) {
            if (result != null) {
                mOwner.openContainerDocument(result);
            }
        }
    }

    private static final class HandleRootsChangedTask
            extends PairedTask<BaseActivity, RootInfo, RootInfo> {
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui;

import android.annotation.Nullable;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.util.Log;

import com.android.documentsui.base.CheckedTask;
import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.RootInfo;

import java.util.function.Consumer;

/**
 * A {@link CheckedTask} that takes {@link RootInfo} and query SAF to obtain the
 * {@link DocumentInfo} of its root document and call supplied callback to handle the
 * {@link DocumentInfo}.
 */
public class GetRootDocumentTask extends CheckedTask<Void, DocumentInfo> {

    private final static String TAG = "GetRootDocumentTask";

    private final RootInfo mRootInfo;
    private final Context mContext;
    private final Consumer<DocumentInfo> mCallback;

    public GetRootDocumentTask(
            RootInfo rootInfo, Activity activity, Consumer<DocumentInfo> callback) {
        this(rootInfo, activity, activity::isDestroyed, callback);
    }

    public GetRootDocumentTask(
            RootInfo rootInfo, Fragment fragment, Consumer<DocumentInfo> callback) {
        this(rootInfo, fragment.getContext(), fragment::isDetached, callback);
    }

    private GetRootDocumentTask(
            RootInfo rootInfo, Context context, Check check, Consumer<DocumentInfo> callback) {
        super(check);
        mRootInfo = rootInfo;
        mContext = context.getApplicationContext();
        mCallback = callback;
    }

    @Override
    public @Nullable DocumentInfo run(Void... rootInfo) {
        return mRootInfo.getRootDocumentBlocking(mContext);
    }

    @Override
    public void finish(@Nullable DocumentInfo documentInfo) {
        if (documentInfo != null) {
            mCallback.accept(documentInfo);
        } else {
            Log.e(TAG, "Cannot find document info for root: " + mRootInfo);
        }
    }
}
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui.manager;

import com.android.documentsui.base.RootInfo;

/**
 * Provides {@link ManageActivity} action specializations to fragments.
 */
public class ActionHandler extends com.android.documentsui.ActionHandler<ManageActivity> {

    ActionHandler(ManageActivity activity) {
        super(activity);
    }

    @Override
    public void openSettings(RootInfo root) {
        mActivity.openRootSettings(root);
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ public class ManageActivity extends BaseActivity {
    private Tuner mTuner;
    private MenuManager mMenuManager;
    private FocusManager mFocusManager;
    private ActionHandler mActionHandler;
    private DocumentClipper mClipper;

    public ManageActivity() {
@@ -107,9 +108,10 @@ public class ManageActivity extends BaseActivity {
        mTuner = new Tuner(this, mState);
        // Make sure this is done after the RecyclerView and the Model are set up.
        mFocusManager = new FocusManager(getColor(R.color.accent_dark));
        mActionHandler = new ActionHandler(this);
        mClipper = DocumentsApplication.getDocumentClipper(this);

        RootsFragment.show(getFragmentManager(), this::openRootSettings);
        RootsFragment.show(getFragmentManager(), null);

        final Intent intent = getIntent();
        final Uri uri = intent.getData();
@@ -580,6 +582,10 @@ public class ManageActivity extends BaseActivity {
        return mMenuManager;
    }

    @Override
    public ActionHandler getActionHandler() {
        return mActionHandler;
    }
    /**
     * Builds a stack for the specific Uris. Multi roots are not supported, as it's impossible
     * to know which root to select. Also, the stack doesn't contain intermediate directories.
Loading