Add catchingExceptions method to replace runCatching (#4797)

- Add `runCatchingExceptions` and `mapCatchingExceptions` to replace `runCatching` and `mapCatching`.
- Make `tryOrNull { ... }` catch only exceptions too.
- Apply the changes to the whole project.
- Add new Rust fakes for tests to handle the code that's now unblocked - previously it just threw an `UnsatisfiedLinkError` which we ignored.
- Add a new `detekt-rules` project with a `RunCatchingRule` to prevent `runCatching` and `mapCatching` usages.
This commit is contained in:
Jorge Martin Espinosa 2025-06-04 09:02:26 +02:00 committed by GitHub
parent 7816529fd7
commit efdc10e60a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
144 changed files with 716 additions and 375 deletions

View file

@ -22,6 +22,7 @@ import dagger.assisted.AssistedInject
import io.element.android.libraries.androidutils.R
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.extensions.mapCatchingExceptions
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState
@ -154,7 +155,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
mimeType = mediaItem.mediaInfo().mimeType,
filename = mediaItem.mediaInfo().filename
)
.mapCatching { mediaFile ->
.mapCatchingExceptions { mediaFile ->
localMediaFactory.createFromMediaFile(
mediaFile = mediaFile,
mediaInfo = mediaItem.mediaInfo()
@ -164,7 +165,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
private suspend fun saveOnDisk(mediaItem: MediaItem.Event) {
downloadMedia(mediaItem)
.mapCatching { localMedia ->
.mapCatchingExceptions { localMedia ->
localMediaActions.saveOnDisk(localMedia)
}
.onSuccess {
@ -179,7 +180,7 @@ class MediaGalleryPresenter @AssistedInject constructor(
private suspend fun share(mediaItem: MediaItem.Event) {
downloadMedia(mediaItem)
.mapCatching { localMedia ->
.mapCatchingExceptions { localMedia ->
localMediaActions.share(localMedia)
}
.onFailure {

View file

@ -32,6 +32,7 @@ import androidx.core.net.toFile
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.androidutils.system.startInstallFromSourceIntent
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.di.AppScope
@ -83,7 +84,7 @@ class AndroidLocalMediaActions @Inject constructor(
override suspend fun saveOnDisk(localMedia: LocalMedia): Result<Unit> = withContext(coroutineDispatchers.io) {
require(localMedia.uri.scheme == ContentResolver.SCHEME_FILE)
runCatching {
runCatchingExceptions {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
saveOnDiskUsingMediaStore(localMedia)
} else {
@ -98,7 +99,7 @@ class AndroidLocalMediaActions @Inject constructor(
override suspend fun share(localMedia: LocalMedia): Result<Unit> = withContext(coroutineDispatchers.io) {
require(localMedia.uri.scheme == ContentResolver.SCHEME_FILE)
runCatching {
runCatchingExceptions {
val shareableUri = localMedia.toShareableUri()
val shareMediaIntent = Intent(Intent.ACTION_SEND)
.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
@ -117,7 +118,7 @@ class AndroidLocalMediaActions @Inject constructor(
override suspend fun open(localMedia: LocalMedia): Result<Unit> = withContext(coroutineDispatchers.io) {
require(localMedia.uri.scheme == ContentResolver.SCHEME_FILE)
runCatching {
runCatchingExceptions {
when (localMedia.info.mimeType) {
MimeTypes.Apk -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

View file

@ -10,10 +10,11 @@ package io.element.android.libraries.mediaviewer.impl.local.pdf
import android.content.Context
import android.net.Uri
import android.os.ParcelFileDescriptor
import io.element.android.libraries.core.extensions.runCatchingExceptions
import java.io.File
class ParcelFileDescriptorFactory(private val context: Context) {
fun create(model: Any?) = runCatching {
fun create(model: Any?) = runCatchingExceptions {
when (model) {
is File -> ParcelFileDescriptor.open(model, ParcelFileDescriptor.MODE_READ_ONLY)
is Uri -> context.contentResolver.openFileDescriptor(model, "r")!!

View file

@ -10,6 +10,7 @@ package io.element.android.libraries.mediaviewer.impl.local.pdf
import android.graphics.pdf.PdfRenderer
import android.os.ParcelFileDescriptor
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.extensions.runCatchingExceptions
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
@ -35,7 +36,7 @@ class PdfRendererManager(
coroutineScope.launch {
mutex.withLock {
withContext(Dispatchers.IO) {
pdfRenderer = runCatching {
pdfRenderer = runCatchingExceptions {
PdfRenderer(parcelFileDescriptor)
}.fold(
onSuccess = { pdfRenderer ->

View file

@ -21,6 +21,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.viewfolder.api.TextFileViewer
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
@ -43,7 +44,7 @@ fun TextFileView(
data.value = AsyncData.Loading()
if (localMedia?.uri != null) {
// Load the file content
val result = runCatching {
val result = runCatchingExceptions {
context.contentResolver.openInputStream(localMedia.uri).use {
it?.bufferedReader()?.readLines()?.toList().orEmpty()
}

View file

@ -15,6 +15,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.core.extensions.mapCatchingExceptions
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaFile
import io.element.android.libraries.matrix.api.timeline.Timeline
@ -173,7 +174,7 @@ class MediaViewerDataSource(
.onSuccess { mediaFile ->
mediaFiles.add(mediaFile)
}
.mapCatching { mediaFile ->
.mapCatchingExceptions { mediaFile ->
localMediaFactory.createFromMediaFile(
mediaFile = mediaFile,
mediaInfo = data.mediaInfo