diff --git a/app/src/androidTest/java/app/opendocument/droid/test/LandingTests.kt b/app/src/androidTest/java/app/opendocument/droid/test/LandingTests.kt index e526011dd7da..2de747335a94 100644 --- a/app/src/androidTest/java/app/opendocument/droid/test/LandingTests.kt +++ b/app/src/androidTest/java/app/opendocument/droid/test/LandingTests.kt @@ -3,6 +3,8 @@ package app.opendocument.droid.test +import android.app.Activity +import android.app.Instrumentation import android.content.Context import android.content.Intent import android.net.Uri @@ -12,6 +14,7 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.intent.Intents +import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText @@ -70,6 +73,30 @@ class LandingTests { onView(withId(R.id.landing_empty)).check(matches(isDisplayed())) } + @Test + fun emptyStateOpensTheSystemPicker() { + stubOpenDocumentCancelled() + + launch() + + onView(withId(R.id.landing_empty_open)).perform(click()) + + Intents.intended(hasAction(Intent.ACTION_OPEN_DOCUMENT)) + } + + @Test + fun theFabOpensTheSystemPicker() { + // the fab is hidden behind the empty state, which offers the same thing with a label + seedRecentDocument() + stubOpenDocumentCancelled() + + launch() + + onView(withId(R.id.landing_open_fab)).perform(click()) + + Intents.intended(hasAction(Intent.ACTION_OPEN_DOCUMENT)) + } + @Test fun aRecentDocumentIsListed() { seedRecentDocument() @@ -115,6 +142,15 @@ class LandingTests { return activity } + /** + * The picker is stubbed as cancelled: these tests are about what the landing screen asks for, + * not about loading a document. + */ + private fun stubOpenDocumentCancelled() { + Intents.intending(hasAction(Intent.ACTION_OPEN_DOCUMENT)) + .respondWith(Instrumentation.ActivityResult(Activity.RESULT_CANCELED, null)) + } + private fun seedRecentDocument() { RecentDocumentsUtil.addRecentDocument(context(), TEST_DOCUMENT, uriOf(requireTestFile())) } diff --git a/app/src/androidTest/java/app/opendocument/droid/test/MainActivityTests.kt b/app/src/androidTest/java/app/opendocument/droid/test/MainActivityTests.kt index 67dd71ca98fa..8f200797694f 100644 --- a/app/src/androidTest/java/app/opendocument/droid/test/MainActivityTests.kt +++ b/app/src/androidTest/java/app/opendocument/droid/test/MainActivityTests.kt @@ -48,7 +48,6 @@ import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicReference import org.hamcrest.Matchers.allOf -import org.hamcrest.Matchers.anyOf import org.hamcrest.Matchers.equalTo import org.junit.After import org.junit.AfterClass @@ -254,6 +253,8 @@ class MainActivityTests { ) } + // the toolbar action now launches ACTION_OPEN_DOCUMENT directly, which the test stubs out. + // it used to raise a chooser of our own that a file manager had to be picked from first. private fun openDocumentThroughPicker() { onView( allOf( @@ -263,16 +264,6 @@ class MainActivityTests { ) ) .perform(click()) - - // The menu item could be either Documents or Files. - onView( - allOf( - withId(android.R.id.text1), - anyOf(withText("Documents"), withText("Files")), - isDisplayed(), - ) - ) - .perform(click()) } private fun clickEditWithOverflowFallback() { diff --git a/app/src/main/java/app/opendocument/droid/ui/activity/MainActivity.kt b/app/src/main/java/app/opendocument/droid/ui/activity/MainActivity.kt index 0b3ec7a8f3bf..7656b7466ac1 100644 --- a/app/src/main/java/app/opendocument/droid/ui/activity/MainActivity.kt +++ b/app/src/main/java/app/opendocument/droid/ui/activity/MainActivity.kt @@ -5,7 +5,6 @@ import android.content.ActivityNotFoundException import android.content.ComponentName import android.content.Intent import android.content.ServiceConnection -import android.content.pm.ResolveInfo import android.content.res.Configuration import android.net.Uri import android.os.Bundle @@ -20,7 +19,6 @@ import android.view.View import android.widget.LinearLayout import androidx.activity.OnBackPressedCallback import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.view.MenuProvider import androidx.core.view.ViewCompat @@ -641,51 +639,33 @@ class MainActivity : AppCompatActivity(), MenuProvider { intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - val packageManager = packageManager - val targetList: List = - packageManager.queryIntentActivities(intent, 0).filter { target -> - target.activityInfo.packageName == packageName || target.activityInfo.exported - } - - // the recently opened documents used to be the last row here; they are the landing - // screen itself now - val targetNames = targetList.map { it.loadLabel(packageManager).toString() }.toTypedArray() - - val builder = AlertDialog.Builder(this) - builder.setTitle(R.string.dialog_choose_filemanager) - builder.setItems(targetNames) { dialog, which -> - val target = targetList[which] - - intent.component = - ComponentName(target.activityInfo.packageName, target.activityInfo.name) - - try { - OpenFileIdling.increment() - - openDocumentLauncher.launch(intent) - } catch (e: Exception) { - OpenFileIdling.decrement() + // straight to the system picker. this used to put an "Open document via:" dialog of our + // own in front of it, listing every app that answers ACTION_OPEN_DOCUMENT - an extra tap + // that duplicated what the picker itself already offers, since it can browse Drive, + // Downloads, a usb stick and every installed file manager on its own. + try { + OpenFileIdling.increment() - crashManager.log(e) + openDocumentLauncher.launch(intent) + } catch (e: ActivityNotFoundException) { + OpenFileIdling.decrement() - SnackbarHelper.show( - this, - R.string.crouton_error_open_app, - { findDocument() }, - true, - true, - ) - } + crashManager.log(e) - analyticsManager.report( - AnalyticsConstants.EVENT_SELECT_CONTENT, - AnalyticsConstants.PARAM_CONTENT_TYPE, - target.activityInfo.packageName, + SnackbarHelper.show( + this, + R.string.crouton_error_open_app, + { findDocument() }, + true, + true, ) - - dialog.dismiss() } - builder.show() + + analyticsManager.report( + AnalyticsConstants.EVENT_SELECT_CONTENT, + AnalyticsConstants.PARAM_CONTENT_TYPE, + "picker", + ) } override fun onPause() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 769d8f0577d0..e9faa9d8e9a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,15 +11,11 @@ File could not be saved. Please contact support@opendocument.app Device out of memory! Too many pictures, or file too big. This document is password-protected - Recent documents - Open document via: Loading… Uploading… Please wait, this could take a few minutes. Uploaded files are private and automatically deleted after 24 hours. We aren\'t able to open this document, because we don\'t support its format. Do you want to upload it to our server temporarily, so we can display it for you anyway? Uploaded files are private and automatically deleted after 24 hours. - No documents found - Recently opened documents Search in document Open document Open with...