Loading src/com/android/documentsui/ActionHandler.java 0 → 100644 +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."); } } src/com/android/documentsui/BaseActivity.java +11 −40 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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()); } } Loading Loading @@ -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. Loading Loading @@ -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> { Loading src/com/android/documentsui/GetRootDocumentTask.java 0 → 100644 +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); } } } src/com/android/documentsui/manager/ActionHandler.java 0 → 100644 +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); } } src/com/android/documentsui/manager/ManageActivity.java +7 −1 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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(); Loading Loading @@ -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 Loading
src/com/android/documentsui/ActionHandler.java 0 → 100644 +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."); } }
src/com/android/documentsui/BaseActivity.java +11 −40 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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()); } } Loading Loading @@ -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. Loading Loading @@ -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> { Loading
src/com/android/documentsui/GetRootDocumentTask.java 0 → 100644 +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); } } }
src/com/android/documentsui/manager/ActionHandler.java 0 → 100644 +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); } }
src/com/android/documentsui/manager/ManageActivity.java +7 −1 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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(); Loading Loading @@ -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