diff options
author | 2024-12-19 14:00:41 +1100 | |
---|---|---|
committer | 2025-01-16 14:15:01 +1100 | |
commit | 05e57300f2d12992adcda6f7bdbc2179cdcd6265 (patch) | |
tree | 23fdd80b340d04b78c8358dfb7060a9aa425a9d9 | |
parent | b3714e467f5df8c061218f5b6bc4e8b128c5129c (diff) |
Add "Open" to context menu when a single file is selected
The open context has a slightly different behaviour to normal click.
Normal click does a ACTION_PREVIEW, fallback=ACTION_VIEW but the
context menu does a ACTION_VIEW without a fallback.
Reusing an existing menu item which is unused. This was disabled for
* picker in http://ag/4269998
* files in http://ag/4056064
Bug: 384607914
Flag: com.android.documentsui.flags.desktop_file_handling
Test: Unit tests and manual testing
Change-Id: I60b7a6a1cfaf0fe5f2b534341296a7c6322f4371
10 files changed, 97 insertions, 13 deletions
diff --git a/src/com/android/documentsui/AbstractActionHandler.java b/src/com/android/documentsui/AbstractActionHandler.java index b11567344..da599d47f 100644 --- a/src/com/android/documentsui/AbstractActionHandler.java +++ b/src/com/android/documentsui/AbstractActionHandler.java @@ -252,6 +252,11 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA } @Override + public void openDocumentViewOnly(DocumentInfo doc) { + throw new UnsupportedOperationException("Open doc not supported!"); + } + + @Override public void showInspector(DocumentInfo doc) { throw new UnsupportedOperationException("Can't open properties."); } diff --git a/src/com/android/documentsui/ActionHandler.java b/src/com/android/documentsui/ActionHandler.java index 15124eb33..c66a7e78c 100644 --- a/src/com/android/documentsui/ActionHandler.java +++ b/src/com/android/documentsui/ActionHandler.java @@ -129,6 +129,12 @@ public interface ActionHandler { boolean openItem(ItemDetails<String> doc, @ViewType int type, @ViewType int fallback); /** + * Similar to openItem but takes DocumentInfo instead of DocumentItemDetails and uses + * VIEW_TYPE_VIEW with no fallback. + */ + void openDocumentViewOnly(DocumentInfo doc); + + /** * This is called when user hovers over a doc for enough time during a drag n' drop, to open a * folder that accepts drop. We should only open a container that's not an archive, since archives * do not accept dropping. diff --git a/src/com/android/documentsui/MenuManager.java b/src/com/android/documentsui/MenuManager.java index 78339862b..2d1e2a59a 100644 --- a/src/com/android/documentsui/MenuManager.java +++ b/src/com/android/documentsui/MenuManager.java @@ -427,7 +427,7 @@ public abstract class MenuManager { boolean canExtract(); - boolean canOpenWith(); + boolean canOpen(); boolean canViewInOwner(); } diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java index 165599f71..43fc91e3a 100644 --- a/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -21,6 +21,7 @@ import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.base.SharedMinimal.VERBOSE; import static com.android.documentsui.base.State.MODE_GRID; import static com.android.documentsui.base.State.MODE_LIST; +import static com.android.documentsui.flags.Flags.desktopFileHandling; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -924,7 +925,17 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On mSelectionMgr.copySelection(selection); final int id = item.getItemId(); - if (id == R.id.action_menu_select || id == R.id.dir_menu_open) { + if (desktopFileHandling() && id == R.id.dir_menu_open) { + // On desktop, "open" is displayed in file management mode (i.e. `files.MenuManager`). + // This menu item behaves the same as double click on the menu item which is handled by + // onItemActivated but since onItemActivated requires a RecylcerView ItemDetails, we're + // using viewDocument that takes a Selection. + viewDocument(selection); + return true; + } else if (id == R.id.action_menu_select || id == R.id.dir_menu_open) { + // Note: this code path is never executed for `dir_menu_open`. The menu item is always + // hidden unless the desktopFileHandling flag is enabled, in which case the menu item + // will be handled by the condition above. openDocuments(selection); mActionModeController.finishActionMode(); return true; @@ -1082,6 +1093,20 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On mActions.showChooserForDoc(doc); } + private void viewDocument(final Selection<String> selected) { + Metrics.logUserAction(MetricConsts.USER_ACTION_OPEN); + + if (selected.isEmpty()) { + return; + } + + assert selected.size() == 1; + DocumentInfo doc = + DocumentInfo.fromDirectoryCursor(mModel.getItem(selected.iterator().next())); + + mActions.openDocumentViewOnly(doc); + } + private void transferDocuments( final Selection<String> selected, @Nullable DocumentStack destination, final @OpType int mode) { diff --git a/src/com/android/documentsui/dirlist/SelectionMetadata.java b/src/com/android/documentsui/dirlist/SelectionMetadata.java index 3abc3e190..74b6061b3 100644 --- a/src/com/android/documentsui/dirlist/SelectionMetadata.java +++ b/src/com/android/documentsui/dirlist/SelectionMetadata.java @@ -168,7 +168,7 @@ public class SelectionMetadata extends SelectionObserver<String> } @Override - public boolean canOpenWith() { + public boolean canOpen() { return size() == 1 && mDirectoryCount == 0 && mInArchiveCount == 0 && mPartialCount == 0; } } diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java index 1fa771178..56eef8737 100644 --- a/src/com/android/documentsui/files/ActionHandler.java +++ b/src/com/android/documentsui/files/ActionHandler.java @@ -223,6 +223,12 @@ public class ActionHandler<T extends FragmentActivity & AbstractActionHandler.Co } @Override + public void openDocumentViewOnly(DocumentInfo doc) { + mInjector.searchManager.recordHistory(); + openDocument(doc, VIEW_TYPE_REGULAR, VIEW_TYPE_NONE); + } + + @Override public void springOpenDirectory(DocumentInfo doc) { assert(doc.isDirectory()); mActionModeAddons.finishActionMode(); diff --git a/src/com/android/documentsui/files/MenuManager.java b/src/com/android/documentsui/files/MenuManager.java index 742bc9739..3e2e00feb 100644 --- a/src/com/android/documentsui/files/MenuManager.java +++ b/src/com/android/documentsui/files/MenuManager.java @@ -16,6 +16,8 @@ package com.android.documentsui.files; +import static com.android.documentsui.flags.Flags.desktopFileHandling; + import android.content.Context; import android.content.res.Resources; import android.net.Uri; @@ -161,7 +163,12 @@ public final class MenuManager extends com.android.documentsui.MenuManager { @Override protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) { - Menus.setEnabledAndVisible(openWith, selectionDetails.canOpenWith()); + Menus.setEnabledAndVisible(openWith, selectionDetails.canOpen()); + } + + @Override + protected void updateOpenInContextMenu(MenuItem open, SelectionDetails selectionDetails) { + Menus.setEnabledAndVisible(open, desktopFileHandling() && selectionDetails.canOpen()); } @Override diff --git a/tests/common/com/android/documentsui/testing/TestSelectionDetails.java b/tests/common/com/android/documentsui/testing/TestSelectionDetails.java index c63fdee59..e798174f8 100644 --- a/tests/common/com/android/documentsui/testing/TestSelectionDetails.java +++ b/tests/common/com/android/documentsui/testing/TestSelectionDetails.java @@ -32,7 +32,7 @@ public class TestSelectionDetails implements SelectionDetails { public boolean containFiles; public boolean canPasteInto; public boolean canExtract; - public boolean canOpenWith; + public boolean canOpen; public boolean canViewInOwner; @Override @@ -76,8 +76,8 @@ public class TestSelectionDetails implements SelectionDetails { } @Override - public boolean canOpenWith() { - return canOpenWith; + public boolean canOpen() { + return canOpen; } @Override diff --git a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java index 3de1a8ca7..a45778ecc 100644 --- a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java +++ b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java @@ -460,6 +460,21 @@ public class ActionHandlerTest { } @Test + public void testDocumentContextMenuOpen() throws Exception { + mActivity.resources.setQuickViewerPackage("corptropolis.viewer"); + mActivity.currentRoot = TestProvidersAccess.HOME; + + // Test normal picking (i.e. double click) behaviour will quick view + mHandler.openDocument(TestEnv.FILE_GIF, ActionHandler.VIEW_TYPE_PREVIEW, + ActionHandler.VIEW_TYPE_REGULAR); + mActivity.assertActivityStarted(Intent.ACTION_QUICK_VIEW); + + // And verify open via context menu will view instead + mHandler.openDocumentViewOnly(TestEnv.FILE_GIF); + mActivity.assertActivityStarted(Intent.ACTION_VIEW); + } + + @Test @DisableFlags({Flags.FLAG_DESKTOP_FILE_HANDLING}) public void testShowChooser() throws Exception { mActivity.currentRoot = TestProvidersAccess.DOWNLOADS; diff --git a/tests/unit/com/android/documentsui/files/MenuManagerTest.java b/tests/unit/com/android/documentsui/files/MenuManagerTest.java index 02988d62f..b869619a3 100644 --- a/tests/unit/com/android/documentsui/files/MenuManagerTest.java +++ b/tests/unit/com/android/documentsui/files/MenuManagerTest.java @@ -21,6 +21,9 @@ import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.net.Uri; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DocumentsContract.Document; import android.provider.DocumentsContract.Root; @@ -35,6 +38,7 @@ import com.android.documentsui.base.RootInfo; import com.android.documentsui.base.State; import com.android.documentsui.base.UserId; import com.android.documentsui.dirlist.TestData; +import com.android.documentsui.flags.Flags; import com.android.documentsui.testing.TestDirectoryDetails; import com.android.documentsui.testing.TestEnv; import com.android.documentsui.testing.TestFeatures; @@ -45,6 +49,7 @@ import com.android.documentsui.testing.TestSearchViewManager; import com.android.documentsui.testing.TestSelectionDetails; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -123,6 +128,9 @@ public final class MenuManagerTest { private int mFilesCount; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Before public void setUp() { testMenu = TestMenu.create(); @@ -388,7 +396,7 @@ public final class MenuManagerTest { @Test public void testActionMenu_CanOpenWith() { - selectionDetails.canOpenWith = true; + selectionDetails.canOpen = true; mgr.updateActionMenu(testMenu, selectionDetails); actionModeOpenWith.assertEnabledAndVisible(); @@ -396,7 +404,7 @@ public final class MenuManagerTest { @Test public void testActionMenu_NoOpenWith() { - selectionDetails.canOpenWith = false; + selectionDetails.canOpen = false; mgr.updateActionMenu(testMenu, selectionDetails); actionModeOpenWith.assertDisabledAndInvisible(); @@ -590,16 +598,28 @@ public final class MenuManagerTest { } @Test - public void testContextMenu_OnFile_CanOpenWith() { - selectionDetails.canOpenWith = true; + @DisableFlags({Flags.FLAG_DESKTOP_FILE_HANDLING}) + public void testContextMenu_OnFile_CanOpen() { + selectionDetails.canOpen = true; + mgr.updateContextMenuForFiles(testMenu, selectionDetails); + dirOpen.assertDisabledAndInvisible(); + dirOpenWith.assertEnabledAndVisible(); + } + + @Test + @EnableFlags({Flags.FLAG_DESKTOP_FILE_HANDLING}) + public void testContextMenu_OnFile_CanOpenDesktop() { + selectionDetails.canOpen = true; mgr.updateContextMenuForFiles(testMenu, selectionDetails); + dirOpen.assertEnabledAndVisible(); dirOpenWith.assertEnabledAndVisible(); } @Test - public void testContextMenu_OnFile_NoOpenWith() { - selectionDetails.canOpenWith = false; + public void testContextMenu_OnFile_NoOpen() { + selectionDetails.canOpen = false; mgr.updateContextMenuForFiles(testMenu, selectionDetails); + dirOpen.assertDisabledAndInvisible(); dirOpenWith.assertDisabledAndInvisible(); } |