diff --git a/changelog.d/6967.bugfix b/changelog.d/6967.bugfix new file mode 100644 index 0000000000..e2a1f70532 --- /dev/null +++ b/changelog.d/6967.bugfix @@ -0,0 +1 @@ +Fix low occurrence crashes. 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") diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index cea845a490..e35a4fdce1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -1046,7 +1046,7 @@ class TimelineViewModel @AssistedInject constructor( val event = try { room.reportingService().reportContent(action.eventId, -100, action.reason) RoomDetailViewEvents.ActionSuccess(action) - } catch (failure: Exception) { + } catch (failure: Throwable) { RoomDetailViewEvents.ActionFailure(action, failure) } _viewEvents.post(event) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt index 2e0a6ae347..ca64a0f991 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListViewModel.kt @@ -271,7 +271,7 @@ class RoomListViewModel @AssistedInject constructor( viewModelScope.launch { try { room.roomPushRuleService().setRoomNotificationState(action.notificationState) - } catch (failure: Exception) { + } catch (failure: Throwable) { _viewEvents.post(RoomListViewEvents.Failure(failure)) } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt index 5ecf9d6d96..425f309202 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/home/HomeRoomListViewModel.kt @@ -289,7 +289,7 @@ class HomeRoomListViewModel @AssistedInject constructor( viewModelScope.launch { try { room.roomPushRuleService().setRoomNotificationState(action.notificationState) - } catch (failure: Exception) { + } catch (failure: Throwable) { _viewEvents.post(HomeRoomListViewEvents.Failure(failure)) } }