diff --git a/screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialog.png b/screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialogDifferentTypes_Screenshot.png similarity index 100% rename from screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialog.png rename to screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialogDifferentTypes_Screenshot.png diff --git a/screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialog_Screenshot.png b/screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialog_Screenshot.png new file mode 100644 index 0000000000..bd3d20143b Binary files /dev/null and b/screenshots/gplay/debug/com.owncloud.android.ui.dialog.SendFilesDialogTest_showDialog_Screenshot.png differ diff --git a/src/androidTest/java/com/owncloud/android/ui/dialog/SendFilesDialogTest.kt b/src/androidTest/java/com/owncloud/android/ui/dialog/SendFilesDialogTest.kt index dc3bb17efa..79c915789c 100644 --- a/src/androidTest/java/com/owncloud/android/ui/dialog/SendFilesDialogTest.kt +++ b/src/androidTest/java/com/owncloud/android/ui/dialog/SendFilesDialogTest.kt @@ -22,29 +22,21 @@ package com.owncloud.android.ui.dialog import androidx.fragment.app.FragmentManager +import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.intent.rule.IntentsTestRule import androidx.test.platform.app.InstrumentationRegistry import com.nextcloud.client.TestActivity import com.owncloud.android.AbstractIT +import com.owncloud.android.R import com.owncloud.android.datamodel.OCFile import com.owncloud.android.utils.ScreenshotTest +import org.junit.Assert import org.junit.Rule import org.junit.Test class SendFilesDialogTest : AbstractIT() { - @get:Rule - val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false) - - @Test - @ScreenshotTest - fun showDialog() { - val activity = testActivityRule.launchActivity(null) - - val fm: FragmentManager = activity.supportFragmentManager - val ft = fm.beginTransaction() - ft.addToBackStack(null) - - val files = setOf( + companion object { + private val FILES_SAME_TYPE = setOf( OCFile("/1.jpg").apply { mimeType = "image/jpg" }, @@ -52,6 +44,28 @@ class SendFilesDialogTest : AbstractIT() { mimeType = "image/jpg" } ) + private val FILES_MIXED_TYPE = setOf( + OCFile("/1.jpg").apply { + mimeType = "image/jpg" + }, + OCFile("/2.pdf").apply { + mimeType = "application/pdf" + }, + OCFile("/3.png").apply { + mimeType = "image/png" + } + ) + } + + @get:Rule + val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false) + + private fun showDialog(files: Set): SendFilesDialog { + val activity = testActivityRule.launchActivity(null) + + val fm: FragmentManager = activity.supportFragmentManager + val ft = fm.beginTransaction() + ft.addToBackStack(null) val sut = SendFilesDialog.newInstance(files) sut.show(ft, "TAG_SEND_SHARE_DIALOG") @@ -59,6 +73,36 @@ class SendFilesDialogTest : AbstractIT() { InstrumentationRegistry.getInstrumentation().waitForIdleSync() shortSleep() + return sut + } + + @Test + fun showDialog() { + val sut = showDialog(FILES_SAME_TYPE) + val recyclerview: RecyclerView = sut.requireDialog().findViewById(R.id.send_button_recycler_view) + Assert.assertNotNull("Adapter is null", recyclerview.adapter) + Assert.assertNotEquals("Send button list is empty", 0, recyclerview.adapter!!.itemCount) + } + + @Test + @ScreenshotTest + fun showDialog_Screenshot() { + val sut = showDialog(FILES_SAME_TYPE) + sut.requireDialog().window?.decorView.let { screenshot(it) } + } + + @Test + fun showDialogDifferentTypes() { + val sut = showDialog(FILES_MIXED_TYPE) + val recyclerview: RecyclerView = sut.requireDialog().findViewById(R.id.send_button_recycler_view) + Assert.assertNotNull("Adapter is null", recyclerview.adapter) + Assert.assertNotEquals("Send button list is empty", 0, recyclerview.adapter!!.itemCount) + } + + @Test + @ScreenshotTest + fun showDialogDifferentTypes_Screenshot() { + val sut = showDialog(FILES_MIXED_TYPE) sut.requireDialog().window?.decorView.let { screenshot(it) } } } diff --git a/src/main/java/com/nextcloud/client/utils/IntentUtil.kt b/src/main/java/com/nextcloud/client/utils/IntentUtil.kt index 19bcd366f0..da32a88ed6 100644 --- a/src/main/java/com/nextcloud/client/utils/IntentUtil.kt +++ b/src/main/java/com/nextcloud/client/utils/IntentUtil.kt @@ -30,6 +30,7 @@ object IntentUtil { @JvmStatic public fun createSendIntent(context: Context, file: OCFile): Intent = createBaseSendFileIntent().apply { + action = Intent.ACTION_SEND type = file.mimeType putExtra(Intent.EXTRA_STREAM, file.getExposedFileUri(context)) } @@ -37,20 +38,21 @@ object IntentUtil { @JvmStatic public fun createSendIntent(context: Context, files: Array): Intent = createBaseSendFileIntent().apply { + action = Intent.ACTION_SEND_MULTIPLE type = getUniqueMimetype(files) - putExtra(Intent.EXTRA_STREAM, getExposedFileUris(context, files)) + putParcelableArrayListExtra(Intent.EXTRA_STREAM, getExposedFileUris(context, files)) } private fun createBaseSendFileIntent(): Intent = - Intent(Intent.ACTION_SEND).apply { + Intent().apply { addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } private fun getUniqueMimetype(files: Array): String? = when { - files.distinctBy { it.mimeType }.size > 1 -> null + files.distinctBy { it.mimeType }.size > 1 -> "*/*" else -> files[0].mimeType } - private fun getExposedFileUris(context: Context, files: Array): Array = - files.map { it.getExposedFileUri(context) }.toTypedArray() + private fun getExposedFileUris(context: Context, files: Array): ArrayList = + ArrayList(files.map { it.getExposedFileUri(context) }) } diff --git a/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.java b/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.java index 8ab51fa98e..b38bde87d6 100644 --- a/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.java +++ b/src/main/java/com/owncloud/android/ui/dialog/SendFilesDialog.java @@ -9,6 +9,7 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; import com.nextcloud.client.utils.IntentUtil; @@ -82,8 +83,14 @@ public class SendFilesDialog extends BottomSheetDialogFragment { // populate send apps Intent sendIntent = IntentUtil.createSendIntent(requireContext(), files); + List matches = requireActivity().getPackageManager().queryIntentActivities(sendIntent, 0); + if (matches.isEmpty()) { + Toast.makeText(getContext(), R.string.no_send_app, Toast.LENGTH_SHORT).show(); + dismiss(); + return null; + } - List sendButtonDataList = setupSendButtonData(sendIntent); + List sendButtonDataList = setupSendButtonData(matches); SendButtonAdapter.ClickListener clickListener = setupSendButtonClickListener(sendIntent); @@ -108,11 +115,11 @@ public class SendFilesDialog extends BottomSheetDialogFragment { } @NonNull - private List setupSendButtonData(Intent sendIntent) { + private List setupSendButtonData(List matches) { Drawable icon; SendButtonData sendButtonData; CharSequence label; - List matches = requireActivity().getPackageManager().queryIntentActivities(sendIntent, 0); + List sendButtonDataList = new ArrayList<>(matches.size()); for (ResolveInfo match : matches) { icon = match.loadIcon(requireActivity().getPackageManager()); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 81ecd3c3a9..fd820068e3 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -1006,4 +1006,5 @@ No results found for your query Found no images or videos Error creating file from template + No app available for sending the selected files