From 36e3abece61806fcd0c7d45b6e1998bef0beee7b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 29 Aug 2022 17:27:53 +0200 Subject: [PATCH] Handle missing external application when trying to Record a Video or on other cases. https://github.com/matrix-org/element-android-rageshakes/issues/42362 --- .../vector/app/core/error/ErrorFormatter.kt | 3 +++ .../features/attachments/AttachmentsHelper.kt | 22 ++++++++++++++----- .../home/room/detail/TimelineFragment.kt | 4 ++++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt index d9a08bd81a..a09f852958 100644 --- a/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt +++ b/vector/src/main/java/im/vector/app/core/error/ErrorFormatter.kt @@ -16,6 +16,7 @@ package im.vector.app.core.error +import android.content.ActivityNotFoundException import im.vector.app.R import im.vector.app.core.resources.StringProvider import im.vector.app.features.call.dialpad.DialPadLookup @@ -134,6 +135,8 @@ class DefaultErrorFormatter @Inject constructor( is MatrixIdFailure.InvalidMatrixId -> stringProvider.getString(R.string.login_signin_matrix_id_error_invalid_matrix_id) is VoiceFailure -> voiceMessageError(throwable) + is ActivityNotFoundException -> + stringProvider.getString(R.string.error_no_external_application_found) else -> throwable.localizedMessage } ?: stringProvider.getString(R.string.unknown_error) diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt index f8aa22f418..646758654f 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentsHelper.kt @@ -16,6 +16,7 @@ package im.vector.app.features.attachments import android.app.Activity +import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent import android.net.Uri @@ -44,6 +45,7 @@ class AttachmentsHelper( interface Callback { fun onContactAttachmentReady(contactAttachment: ContactAttachment) fun onContentAttachmentsReady(attachments: List) + fun onAttachmentError(throwable: Throwable) } // Capture path allows to handle camera image picking. It must be restored if the activity gets killed. @@ -73,21 +75,21 @@ class AttachmentsHelper( /** * Starts the process for handling file picking. */ - fun selectFile(activityResultLauncher: ActivityResultLauncher) { + fun selectFile(activityResultLauncher: ActivityResultLauncher) = doSafe { MultiPicker.get(MultiPicker.FILE).startWith(activityResultLauncher) } /** * Starts the process for handling image/video picking. */ - fun selectGallery(activityResultLauncher: ActivityResultLauncher) { + fun selectGallery(activityResultLauncher: ActivityResultLauncher) = doSafe { MultiPicker.get(MultiPicker.MEDIA).startWith(activityResultLauncher) } /** * Starts the process for handling audio picking. */ - fun selectAudio(activityResultLauncher: ActivityResultLauncher) { + fun selectAudio(activityResultLauncher: ActivityResultLauncher) = doSafe { MultiPicker.get(MultiPicker.AUDIO).startWith(activityResultLauncher) } @@ -101,11 +103,11 @@ class AttachmentsHelper( cameraVideoActivityResultLauncher: ActivityResultLauncher ) { PhotoOrVideoDialog(activity, vectorPreferences).show(object : PhotoOrVideoDialog.PhotoOrVideoDialogListener { - override fun takePhoto() { + override fun takePhoto() = doSafe { captureUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(context, cameraActivityResultLauncher) } - override fun takeVideo() { + override fun takeVideo() = doSafe { captureUri = MultiPicker.get(MultiPicker.CAMERA_VIDEO).startWithExpectingFile(context, cameraVideoActivityResultLauncher) } }) @@ -114,10 +116,18 @@ class AttachmentsHelper( /** * Starts the process for handling contact picking. */ - fun selectContact(activityResultLauncher: ActivityResultLauncher) { + fun selectContact(activityResultLauncher: ActivityResultLauncher) = doSafe { MultiPicker.get(MultiPicker.CONTACT).startWith(activityResultLauncher) } + private fun doSafe(function: () -> Unit) { + try { + function() + } catch (activityNotFound: ActivityNotFoundException) { + callback.onAttachmentError(activityNotFound) + } + } + /** * This methods aims to handle the result data. */ 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 b5eb0608d4..3d42c2fef2 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 @@ -2658,6 +2658,10 @@ class TimelineFragment : messageComposerViewModel.handle(MessageComposerAction.SendMessage(formattedContact, false)) } + override fun onAttachmentError(throwable: Throwable) { + showFailure(throwable) + } + private fun onViewWidgetsClicked() { RoomWidgetsBottomSheet.newInstance() .show(childFragmentManager, "ROOM_WIDGETS_BOTTOM_SHEET")