From ad76cbbc405a6c611f5e3e1486c64f9dfd9475a6 Mon Sep 17 00:00:00 2001
From: Adam Brown <adampsbrown@gmail.com>
Date: Tue, 5 Jul 2022 13:22:52 +0100
Subject: [PATCH 1/4] adding tests around share intent handling

---
 .../attachments/MultiPickerIncomingFiles.kt   |  37 ++++
 .../attachments/ShareIntentHandler.kt         |  40 +----
 .../attachments/ShareIntentHandlerTest.kt     | 166 ++++++++++++++++++
 .../im/vector/app/test/fakes/FakeFunction1.kt |  36 ++++
 .../im/vector/app/test/fakes/FakeIntent.kt    |  35 ++++
 .../fakes/FakeMultiPickerIncomingFiles.kt     |  44 +++++
 .../fixtures/ContentAttachmentDataFixture.kt  |  29 +++
 7 files changed, 354 insertions(+), 33 deletions(-)
 create mode 100644 vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt
 create mode 100644 vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt
 create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt
 create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt
 create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt
 create mode 100644 vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt

diff --git a/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt
new file mode 100644
index 0000000000..82da3a795f
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * 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 im.vector.app.features.attachments
+
+import android.content.Context
+import android.content.Intent
+import im.vector.lib.multipicker.MultiPicker
+import javax.inject.Inject
+
+class MultiPickerIncomingFiles @Inject constructor(
+        private val context: Context,
+) {
+
+    fun image(intent: Intent) = MultiPicker.get(MultiPicker.IMAGE).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
+
+    fun video(intent: Intent) = MultiPicker.get(MultiPicker.VIDEO).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
+
+    fun media(intent: Intent) = MultiPicker.get(MultiPicker.MEDIA).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
+
+    fun file(intent: Intent) = MultiPicker.get(MultiPicker.FILE).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
+    
+    fun audio(intent: Intent) = MultiPicker.get(MultiPicker.AUDIO).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
+}
diff --git a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
index 06ca949025..8cd20d36c1 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
@@ -18,11 +18,12 @@ package im.vector.app.features.attachments
 
 import android.content.Context
 import android.content.Intent
-import im.vector.lib.multipicker.MultiPicker
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
 import javax.inject.Inject
 
-class ShareIntentHandler @Inject constructor() {
+class ShareIntentHandler @Inject constructor(
+        private val multiPickerIncomingFiles: MultiPickerIncomingFiles,
+) {
 
     /**
      * This methods aims to handle incoming share intents.
@@ -33,38 +34,11 @@ class ShareIntentHandler @Inject constructor() {
         val type = intent.resolveType(context) ?: return false
         return when {
             type == "text/plain" -> handlePlainText(intent, onPlainText)
-            type.startsWith("image") -> {
-                onFile(
-                        MultiPicker.get(MultiPicker.IMAGE).getIncomingFiles(context, intent).map {
-                            it.toContentAttachmentData()
-                        }
-                )
-                true
-            }
-            type.startsWith("video") -> {
-                onFile(
-                        MultiPicker.get(MultiPicker.VIDEO).getIncomingFiles(context, intent).map {
-                            it.toContentAttachmentData()
-                        }
-                )
-                true
-            }
-            type.startsWith("audio") -> {
-                onFile(
-                        MultiPicker.get(MultiPicker.AUDIO).getIncomingFiles(context, intent).map {
-                            it.toContentAttachmentData()
-                        }
-                )
-                true
-            }
-
+            type.startsWith("image") -> onFile(multiPickerIncomingFiles.image(intent)).let { true }
+            type.startsWith("video") -> onFile(multiPickerIncomingFiles.video(intent)).let { true }
+            type.startsWith("audio") -> onFile(multiPickerIncomingFiles.audio(intent)).let { true }
             type.startsWith("application") || type.startsWith("file") || type.startsWith("text") || type.startsWith("*") -> {
-                onFile(
-                        MultiPicker.get(MultiPicker.FILE).getIncomingFiles(context, intent).map {
-                            it.toContentAttachmentData()
-                        }
-                )
-                true
+                onFile(multiPickerIncomingFiles.file(intent)).let { true }
             }
             else -> false
         }
diff --git a/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt
new file mode 100644
index 0000000000..bb3aabf67f
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * 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 im.vector.app.features.attachments
+
+import android.content.Intent
+import im.vector.app.test.fakes.FakeContext
+import im.vector.app.test.fakes.FakeFunction1
+import im.vector.app.test.fakes.FakeIntent
+import im.vector.app.test.fakes.FakeMultiPickerIncomingFiles
+import im.vector.app.test.fixtures.ContentAttachmentDataFixture.aContentAttachmentData
+import org.amshove.kluent.shouldBeEqualTo
+import org.junit.Test
+import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+
+private val A_CONTEXT = FakeContext().instance
+private const val A_PLAIN_TEXT_EXTRA = "plain text for sharing"
+private val A_CONTENT_ATTACHMENT_LIST = listOf(aContentAttachmentData())
+
+class ShareIntentHandlerTest {
+
+    private val fakeMultiPickerIncomingFiles = FakeMultiPickerIncomingFiles()
+    private val onFile = FakeFunction1<List<ContentAttachmentData>>()
+    private val onPlainText = FakeFunction1<String>()
+
+    private val shareIntentHandler = ShareIntentHandler(fakeMultiPickerIncomingFiles.instance)
+
+    @Test
+    fun `given an unhandled sharing intent type, when handling intent, then is not handled`() {
+        val unknownShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "unknown/type") }
+
+        val handled = handleIncomingShareIntent(unknownShareIntent)
+
+        onFile.verifyNoInteractions()
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo false
+    }
+
+    @Test
+    fun `given a plain text sharing intent, when handling intent, then is handled and parses plain text content`() {
+        val plainTextShareIntent = FakeIntent().also {
+            it.givenResolvesType(A_CONTEXT, "text/plain")
+            it.givenCharSequenceExtra(key = Intent.EXTRA_TEXT, value = A_PLAIN_TEXT_EXTRA)
+        }
+
+        val handled = handleIncomingShareIntent(plainTextShareIntent)
+
+        onFile.verifyNoInteractions()
+        onPlainText.assertValue(A_PLAIN_TEXT_EXTRA)
+        handled shouldBeEqualTo true
+    }
+
+    @Test
+    fun `given an empty plain text sharing intent, when handling intent, then is not handled`() {
+        val plainTextShareIntent = FakeIntent().also {
+            it.givenResolvesType(A_CONTEXT, "text/plain")
+            it.givenCharSequenceExtra(key = Intent.EXTRA_TEXT, value = "")
+        }
+
+        val handled = handleIncomingShareIntent(plainTextShareIntent)
+
+        onFile.verifyNoInteractions()
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo false
+    }
+
+    @Test
+    fun `given an image sharing intent, when handling intent, then is handled and parses image files`() {
+        val imageShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "image/png") }
+        fakeMultiPickerIncomingFiles.givenImageReturns(imageShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        val handled = handleIncomingShareIntent(imageShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo true
+    }
+
+    @Test
+    fun `given an audio sharing intent, when handling intent, then is handled and parses audio files`() {
+        val audioShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "audio/mp3") }
+        fakeMultiPickerIncomingFiles.givenAudioReturns(audioShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        val handled = handleIncomingShareIntent(audioShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo true
+    }
+
+    @Test
+    fun `given an video sharing intent, when handling intent, then is handled and parses video files`() {
+        val videoShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "video/mp4") }
+        fakeMultiPickerIncomingFiles.givenVideoReturns(videoShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        val handled = handleIncomingShareIntent(videoShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo true
+    }
+
+    @Test
+    fun `given a file sharing intent, when handling intent, then is handled and parses files`() {
+        val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "file/*") }
+        fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        val handled = handleIncomingShareIntent(fileShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo true
+    }
+
+    @Test
+    fun `given a application sharing intent, when handling intent, then is handled and parses files`() {
+        val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "application/apk") }
+        fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        handleIncomingShareIntent(fileShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+    }
+
+    @Test
+    fun `given a text sharing intent, when handling intent, then is handled and parses text files`() {
+        val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "text/ics") }
+        fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        val handled = handleIncomingShareIntent(fileShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo true
+    }
+
+    @Test
+    fun `given a wildcard sharing intent, when handling intent, then is handled and parses files`() {
+        val fileShareIntent = FakeIntent().also { it.givenResolvesType(A_CONTEXT, "*/*") }
+        fakeMultiPickerIncomingFiles.givenFileReturns(fileShareIntent.instance, A_CONTENT_ATTACHMENT_LIST)
+
+        val handled = handleIncomingShareIntent(fileShareIntent)
+
+        onFile.assertValue(A_CONTENT_ATTACHMENT_LIST)
+        onPlainText.verifyNoInteractions()
+        handled shouldBeEqualTo true
+    }
+
+    private fun handleIncomingShareIntent(intent: FakeIntent): Boolean {
+        return shareIntentHandler.handleIncomingShareIntent(A_CONTEXT, intent.instance, onFile.capture, onPlainText.capture)
+    }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt
new file mode 100644
index 0000000000..434a661e5f
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeFunction1.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * 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 im.vector.app.test.fakes
+
+import org.amshove.kluent.shouldBeEqualTo
+
+class FakeFunction1<T : Any> {
+
+    private lateinit var capturedValue: T
+
+    val capture: (T) -> Unit = {
+        capturedValue = it
+    }
+
+    fun verifyNoInteractions() {
+        this::capturedValue.isInitialized shouldBeEqualTo false
+    }
+
+    fun assertValue(value: T) {
+        capturedValue shouldBeEqualTo value
+    }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt
new file mode 100644
index 0000000000..1b3ce3538e
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeIntent.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * 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 im.vector.app.test.fakes
+
+import android.content.Context
+import android.content.Intent
+import io.mockk.every
+import io.mockk.mockk
+
+class FakeIntent {
+
+    val instance = mockk<Intent>()
+
+    fun givenResolvesType(context: Context, type: String?) {
+        every { instance.resolveType(context) } returns type
+    }
+
+    fun givenCharSequenceExtra(key: String, value: CharSequence) {
+        every { instance.getCharSequenceExtra(key) } returns value
+    }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt
new file mode 100644
index 0000000000..00adc83e5c
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeMultiPickerIncomingFiles.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * 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 im.vector.app.test.fakes
+
+import android.content.Intent
+import im.vector.app.features.attachments.MultiPickerIncomingFiles
+import io.mockk.every
+import io.mockk.mockk
+import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+
+class FakeMultiPickerIncomingFiles {
+
+    val instance = mockk<MultiPickerIncomingFiles>()
+
+    fun givenFileReturns(intent: Intent, result: List<ContentAttachmentData>) {
+        every { instance.file(intent) } returns result
+    }
+
+    fun givenAudioReturns(intent: Intent, result: List<ContentAttachmentData>) {
+        every { instance.audio(intent) } returns result
+    }
+
+    fun givenVideoReturns(intent: Intent, result: List<ContentAttachmentData>) {
+        every { instance.video(intent) } returns result
+    }
+
+    fun givenImageReturns(intent: Intent, result: List<ContentAttachmentData>) {
+        every { instance.image(intent) } returns result
+    }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt b/vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt
new file mode 100644
index 0000000000..731d6b32d0
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/test/fixtures/ContentAttachmentDataFixture.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * 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 im.vector.app.test.fixtures
+
+import im.vector.app.test.fakes.FakeUri
+import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+
+object ContentAttachmentDataFixture {
+
+    fun aContentAttachmentData() = ContentAttachmentData(
+            type = ContentAttachmentData.Type.AUDIO,
+            queryUri = FakeUri().instance,
+            mimeType = null,
+    )
+}

From d19346b9c65ac45a0e5fd4cc728b576374f1a031 Mon Sep 17 00:00:00 2001
From: Adam Brown <adampsbrown@gmail.com>
Date: Tue, 5 Jul 2022 13:46:24 +0100
Subject: [PATCH 2/4] fixing formatting

---
 .../vector/app/features/attachments/MultiPickerIncomingFiles.kt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt
index 82da3a795f..0f2dad541c 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/MultiPickerIncomingFiles.kt
@@ -32,6 +32,6 @@ class MultiPickerIncomingFiles @Inject constructor(
     fun media(intent: Intent) = MultiPicker.get(MultiPicker.MEDIA).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
 
     fun file(intent: Intent) = MultiPicker.get(MultiPicker.FILE).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
-    
+
     fun audio(intent: Intent) = MultiPicker.get(MultiPicker.AUDIO).getIncomingFiles(context, intent).map { it.toContentAttachmentData() }
 }

From 59ef8e10c8e649a8a2b9226cead1291e68416358 Mon Sep 17 00:00:00 2001
From: Adam Brown <adampsbrown@gmail.com>
Date: Wed, 6 Jul 2022 12:02:45 +0100
Subject: [PATCH 3/4] injecting the context directly to the handler

---
 .../im/vector/app/features/attachments/ShareIntentHandler.kt  | 3 ++-
 .../vector/app/features/home/room/detail/TimelineFragment.kt  | 2 +-
 .../im/vector/app/features/share/IncomingShareFragment.kt     | 1 -
 .../vector/app/features/attachments/ShareIntentHandlerTest.kt | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
index 8cd20d36c1..1d722c2341 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
@@ -23,6 +23,7 @@ import javax.inject.Inject
 
 class ShareIntentHandler @Inject constructor(
         private val multiPickerIncomingFiles: MultiPickerIncomingFiles,
+        private val context: Context,
 ) {
 
     /**
@@ -30,7 +31,7 @@ class ShareIntentHandler @Inject constructor(
      *
      * @return true if it can handle the intent data, false otherwise
      */
-    fun handleIncomingShareIntent(context: Context, intent: Intent, onFile: (List<ContentAttachmentData>) -> Unit, onPlainText: (String) -> Unit): Boolean {
+    fun handleIncomingShareIntent(intent: Intent, onFile: (List<ContentAttachmentData>) -> Unit, onPlainText: (String) -> Unit): Boolean {
         val type = intent.resolveType(context) ?: return false
         return when {
             type == "text/plain" -> handlePlainText(intent, onPlainText)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
index 9468af7726..a3eff137c8 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
@@ -1619,7 +1619,7 @@ class TimelineFragment @Inject constructor(
 
     private fun sendUri(uri: Uri): Boolean {
         val shareIntent = Intent(Intent.ACTION_SEND, uri)
-        val isHandled = shareIntentHandler.handleIncomingShareIntent(requireContext(), shareIntent, ::onContentAttachmentsReady, onPlainText = {
+        val isHandled = shareIntentHandler.handleIncomingShareIntent(shareIntent, ::onContentAttachmentsReady, onPlainText = {
             fatalError("Should not happen as we're generating a File based share Intent", vectorPreferences.failFast())
         })
         if (!isHandled) {
diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
index a113c8105d..3f8923dd68 100644
--- a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt
@@ -116,7 +116,6 @@ class IncomingShareFragment @Inject constructor(
     }
 
     private fun handleIncomingShareIntent(intent: Intent) = shareIntentHandler.handleIncomingShareIntent(
-            requireContext(),
             intent,
             onFile = {
                 val sharedData = SharedData.Attachments(it)
diff --git a/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt
index bb3aabf67f..d2fba95eee 100644
--- a/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt
+++ b/vector/src/test/java/im/vector/app/features/attachments/ShareIntentHandlerTest.kt
@@ -36,7 +36,7 @@ class ShareIntentHandlerTest {
     private val onFile = FakeFunction1<List<ContentAttachmentData>>()
     private val onPlainText = FakeFunction1<String>()
 
-    private val shareIntentHandler = ShareIntentHandler(fakeMultiPickerIncomingFiles.instance)
+    private val shareIntentHandler = ShareIntentHandler(fakeMultiPickerIncomingFiles.instance, A_CONTEXT)
 
     @Test
     fun `given an unhandled sharing intent type, when handling intent, then is not handled`() {
@@ -161,6 +161,6 @@ class ShareIntentHandlerTest {
     }
 
     private fun handleIncomingShareIntent(intent: FakeIntent): Boolean {
-        return shareIntentHandler.handleIncomingShareIntent(A_CONTEXT, intent.instance, onFile.capture, onPlainText.capture)
+        return shareIntentHandler.handleIncomingShareIntent(intent.instance, onFile.capture, onPlainText.capture)
     }
 }

From 169ac9d0a08da3ad0acddaf74c013eb2733279f8 Mon Sep 17 00:00:00 2001
From: Adam Brown <adampsbrown@gmail.com>
Date: Wed, 6 Jul 2022 12:06:17 +0100
Subject: [PATCH 4/4] updating the known SDK mimetypes and making use of them
 for the intent switches

---
 .../matrix/android/sdk/api/util/MimeTypes.kt   |  6 ++++++
 .../features/attachments/ShareIntentHandler.kt | 18 +++++++++++++-----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt
index ef47775f1b..5ec0dedadf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MimeTypes.kt
@@ -33,9 +33,15 @@ object MimeTypes {
 
     const val Ogg = "audio/ogg"
 
+    const val PlainText = "text/plain"
+
     fun String?.normalizeMimeType() = if (this == BadJpg) Jpeg else this
 
     fun String?.isMimeTypeImage() = this?.startsWith("image/").orFalse()
     fun String?.isMimeTypeVideo() = this?.startsWith("video/").orFalse()
     fun String?.isMimeTypeAudio() = this?.startsWith("audio/").orFalse()
+    fun String?.isMimeTypeApplication() = this?.startsWith("application/").orFalse()
+    fun String?.isMimeTypeFile() = this?.startsWith("file/").orFalse()
+    fun String?.isMimeTypeText() = this?.startsWith("text/").orFalse()
+    fun String?.isMimeTypeAny() = this?.startsWith("*/").orFalse()
 }
diff --git a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
index 1d722c2341..18caba10d9 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/ShareIntentHandler.kt
@@ -19,6 +19,14 @@ package im.vector.app.features.attachments
 import android.content.Context
 import android.content.Intent
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+import org.matrix.android.sdk.api.util.MimeTypes
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeAny
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeApplication
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeAudio
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeFile
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeImage
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeText
+import org.matrix.android.sdk.api.util.MimeTypes.isMimeTypeVideo
 import javax.inject.Inject
 
 class ShareIntentHandler @Inject constructor(
@@ -34,11 +42,11 @@ class ShareIntentHandler @Inject constructor(
     fun handleIncomingShareIntent(intent: Intent, onFile: (List<ContentAttachmentData>) -> Unit, onPlainText: (String) -> Unit): Boolean {
         val type = intent.resolveType(context) ?: return false
         return when {
-            type == "text/plain" -> handlePlainText(intent, onPlainText)
-            type.startsWith("image") -> onFile(multiPickerIncomingFiles.image(intent)).let { true }
-            type.startsWith("video") -> onFile(multiPickerIncomingFiles.video(intent)).let { true }
-            type.startsWith("audio") -> onFile(multiPickerIncomingFiles.audio(intent)).let { true }
-            type.startsWith("application") || type.startsWith("file") || type.startsWith("text") || type.startsWith("*") -> {
+            type == MimeTypes.PlainText -> handlePlainText(intent, onPlainText)
+            type.isMimeTypeImage() -> onFile(multiPickerIncomingFiles.image(intent)).let { true }
+            type.isMimeTypeVideo() -> onFile(multiPickerIncomingFiles.video(intent)).let { true }
+            type.isMimeTypeAudio() -> onFile(multiPickerIncomingFiles.audio(intent)).let { true }
+            type.isMimeTypeApplication() || type.isMimeTypeFile() || type.isMimeTypeText() || type.isMimeTypeAny() -> {
                 onFile(multiPickerIncomingFiles.file(intent)).let { true }
             }
             else -> false