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:
committed by
GitHub
parent
01d6012760
commit
58a3ea8b1f
@@ -21,6 +21,7 @@ import im.vector.app.features.analytics.plan.CryptoSessionStateChange
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
@@ -125,7 +126,7 @@ class LoggedInPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
// Force the user to log out if they were using the proxy sliding sync as it's no longer supported by the SDK
|
||||
private suspend fun MatrixClient.needsForcedNativeSlidingSyncMigration(): Result<Boolean> = runCatching {
|
||||
private suspend fun MatrixClient.needsForcedNativeSlidingSyncMigration(): Result<Boolean> = runCatchingExceptions {
|
||||
val currentSlidingSyncVersion = currentSlidingSyncVersion().getOrThrow()
|
||||
currentSlidingSyncVersion == SlidingSyncVersion.Proxy
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ allprojects {
|
||||
}
|
||||
dependencies {
|
||||
detektPlugins("io.nlopez.compose.rules:detekt:0.4.22")
|
||||
detektPlugins(project(":tests:detekt-rules"))
|
||||
}
|
||||
|
||||
tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
|
||||
|
||||
@@ -10,6 +10,7 @@ package io.element.android.features.cachecleaner.impl
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.features.cachecleaner.api.CacheCleaner
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.CacheDirectory
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -33,7 +34,7 @@ class DefaultCacheCleaner @Inject constructor(
|
||||
|
||||
override fun clearCache() {
|
||||
scope.launch(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
SUBDIRS_TO_CLEANUP.forEach {
|
||||
File(cacheDir.path, it).apply {
|
||||
if (exists()) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import io.element.android.features.call.impl.R
|
||||
import io.element.android.features.call.impl.ui.ElementCallActivity
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.push.api.notifications.ForegroundServiceType
|
||||
import io.element.android.libraries.push.api.notifications.NotificationIdProvider
|
||||
@@ -78,7 +79,7 @@ class CallForegroundService : Service() {
|
||||
} else {
|
||||
0
|
||||
}
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
ServiceCompat.startForeground(this, notificationId, notification, serviceType)
|
||||
}.onFailure {
|
||||
Timber.e(it, "Failed to start ongoing call foreground service")
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.element.android.features.call.api.CallType
|
||||
import io.element.android.features.call.api.CurrentCall
|
||||
import io.element.android.features.call.impl.notifications.CallNotificationData
|
||||
import io.element.android.features.call.impl.notifications.RingingCallNotificationCreator
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
@@ -218,7 +219,7 @@ class DefaultActiveCallManager @Inject constructor(
|
||||
timestamp = notificationData.timestamp,
|
||||
textContent = notificationData.textContent,
|
||||
) ?: return
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationManagerCompat.notify(
|
||||
NotificationIdProvider.getForegroundServiceNotificationId(ForegroundServiceType.INCOMING_CALL),
|
||||
notification,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.features.call.impl.utils
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
@@ -33,7 +34,7 @@ class DefaultCallWidgetProvider @Inject constructor(
|
||||
clientId: String,
|
||||
languageTag: String?,
|
||||
theme: String?,
|
||||
): Result<CallWidgetProvider.GetWidgetResult> = runCatching {
|
||||
): Result<CallWidgetProvider.GetWidgetResult> = runCatchingExceptions {
|
||||
val matrixClient = matrixClientsProvider.getOrRestore(sessionId).getOrThrow()
|
||||
val room = activeRoomsHolder.getActiveRoomMatching(sessionId, roomId)
|
||||
?: matrixClient.getJoinedRoom(roomId)
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
package io.element.android.features.call.impl.utils
|
||||
|
||||
import io.element.android.features.call.impl.data.WidgetMessage
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
object WidgetMessageSerializer {
|
||||
private val coder = Json { ignoreUnknownKeys = true }
|
||||
|
||||
fun deserialize(message: String): Result<WidgetMessage> {
|
||||
return runCatching { coder.decodeFromString(WidgetMessage.serializer(), message) }
|
||||
return runCatchingExceptions { coder.decodeFromString(WidgetMessage.serializer(), message) }
|
||||
}
|
||||
|
||||
fun serialize(message: WidgetMessage): String {
|
||||
|
||||
@@ -35,7 +35,7 @@ open class CreateRoomRootStateProvider : PreviewParameterProvider<CreateRoomRoot
|
||||
}
|
||||
),
|
||||
aCreateRoomRootState(
|
||||
startDmAction = AsyncAction.Failure(Throwable("error")),
|
||||
startDmAction = AsyncAction.Failure(RuntimeException("error")),
|
||||
userListState = aMatrixUser().let {
|
||||
aUserListState().copy(
|
||||
searchQuery = it.userId.value,
|
||||
|
||||
@@ -14,8 +14,8 @@ import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUse
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
@@ -70,13 +70,13 @@ class DefaultStartDMActionTest {
|
||||
fun `when dm creation fails, assert state is updated with given error`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(null)
|
||||
givenCreateDmResult(Result.failure(A_THROWABLE))
|
||||
givenCreateDmResult(Result.failure(AN_EXCEPTION))
|
||||
}
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val action = createStartDMAction(matrixClient, analyticsService)
|
||||
val state = mutableStateOf<AsyncAction<RoomId>>(AsyncAction.Uninitialized)
|
||||
action.execute(aMatrixUser(), true, state)
|
||||
assertThat(state.value).isEqualTo(AsyncAction.Failure(A_THROWABLE))
|
||||
assertThat(state.value).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
|
||||
assertThat(analyticsService.capturedEvents).isEmpty()
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_MESSAGE
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_NAME
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.alias.FakeRoomAliasHelper
|
||||
import io.element.android.libraries.matrix.ui.components.aMatrixUser
|
||||
@@ -274,7 +274,7 @@ class ConfigureBaseRoomPresenterTest {
|
||||
createRoomDataStore.setAvatarUri(Uri.parse(AN_URI_FROM_GALLERY))
|
||||
skipItems(1)
|
||||
mediaPreProcessor.givenResult(Result.success(MediaUploadInfo.Image(mockk(), mockk(), mockk())))
|
||||
matrixClient.givenUploadMediaResult(Result.failure(A_THROWABLE))
|
||||
matrixClient.givenUploadMediaResult(Result.failure(AN_EXCEPTION))
|
||||
|
||||
initialState.eventSink(ConfigureRoomEvents.CreateRoom)
|
||||
assertThat(awaitItem().createRoomAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
@@ -298,7 +298,7 @@ class ConfigureBaseRoomPresenterTest {
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = initialState()
|
||||
val createRoomResult = Result.failure<RoomId>(A_THROWABLE)
|
||||
val createRoomResult = Result.failure<RoomId>(AN_EXCEPTION)
|
||||
|
||||
fakeMatrixClient.givenCreateRoomResult(createRoomResult)
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
@@ -42,7 +42,7 @@ class CreateBaseRoomRootPresenterTest {
|
||||
|
||||
@Test
|
||||
fun `present - start DM action failure scenario`() = runTest {
|
||||
val startDMFailureResult = AsyncAction.Failure(A_THROWABLE)
|
||||
val startDMFailureResult = AsyncAction.Failure(AN_EXCEPTION)
|
||||
val executeResult = lambdaRecorder<MatrixUser, Boolean, MutableState<AsyncAction<RoomId>>, Unit> { _, _, actionState ->
|
||||
actionState.value = startDMFailureResult
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ open class AcceptDeclineInviteStateProvider : PreviewParameterProvider<AcceptDec
|
||||
),
|
||||
),
|
||||
anAcceptDeclineInviteState(
|
||||
acceptAction = AsyncAction.Failure(Throwable("Error while accepting invite")),
|
||||
acceptAction = AsyncAction.Failure(RuntimeException("Error while accepting invite")),
|
||||
),
|
||||
anAcceptDeclineInviteState(
|
||||
declineAction = AsyncAction.Failure(Throwable("Error while declining invite")),
|
||||
declineAction = AsyncAction.Failure(RuntimeException("Error while declining invite")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class DefaultAcceptInviteTest {
|
||||
fun `accept invite failure scenario`() = runTest {
|
||||
val joinRoomLambda =
|
||||
lambdaRecorder<RoomIdOrAlias, List<String>, JoinedRoom.Trigger, Result<Unit>> { _, _, _ ->
|
||||
Result.failure(Throwable("Join room failed"))
|
||||
Result.failure(RuntimeException("Join room failed"))
|
||||
}
|
||||
|
||||
val acceptInvite = DefaultAcceptInvite(
|
||||
|
||||
@@ -89,7 +89,7 @@ open class KnockRequestsListStateProvider : PreviewParameterProvider<KnockReques
|
||||
canBan = true,
|
||||
),
|
||||
currentAction = KnockRequestsAction.AcceptAll,
|
||||
asyncAction = AsyncAction.Failure(Throwable("Failed to accept all")),
|
||||
asyncAction = AsyncAction.Failure(RuntimeException("Failed to accept all")),
|
||||
),
|
||||
aKnockRequestsListState(
|
||||
knockRequests = AsyncData.Success(
|
||||
|
||||
@@ -108,7 +108,7 @@ class KnockRequestsListViewTest {
|
||||
rule.setKnockRequestsListView(
|
||||
aKnockRequestsListState(
|
||||
knockRequests = AsyncData.Success(knockRequests),
|
||||
asyncAction = AsyncAction.Failure(Throwable("Failed to accept all")),
|
||||
asyncAction = AsyncAction.Failure(RuntimeException("Failed to accept all")),
|
||||
currentAction = KnockRequestsAction.AcceptAll,
|
||||
eventSink = eventsRecorder,
|
||||
),
|
||||
@@ -124,7 +124,7 @@ class KnockRequestsListViewTest {
|
||||
rule.setKnockRequestsListView(
|
||||
aKnockRequestsListState(
|
||||
knockRequests = AsyncData.Success(knockRequests),
|
||||
asyncAction = AsyncAction.Failure(Throwable("Failed to accept all")),
|
||||
asyncAction = AsyncAction.Failure(RuntimeException("Failed to accept all")),
|
||||
currentAction = KnockRequestsAction.AcceptAll,
|
||||
eventSink = eventsRecorder,
|
||||
),
|
||||
|
||||
@@ -17,6 +17,7 @@ import io.element.android.features.licenses.impl.LicensesProvider
|
||||
import io.element.android.features.licenses.impl.model.DependencyLicenseItem
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import javax.inject.Inject
|
||||
@@ -34,7 +35,7 @@ class DependencyLicensesListPresenter @Inject constructor(
|
||||
}
|
||||
var filter by remember { mutableStateOf("") }
|
||||
LaunchedEffect(Unit) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
licenses = AsyncData.Success(licensesProvider.provides().toPersistentList())
|
||||
}.onFailure {
|
||||
licenses = AsyncData.Failure(it)
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.core.net.toUri
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.libraries.androidutils.system.openAppSettingsPage
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import timber.log.Timber
|
||||
@@ -26,7 +27,7 @@ class AndroidLocationActions @Inject constructor(
|
||||
@ApplicationContext private val context: Context
|
||||
) : LocationActions {
|
||||
override fun share(location: Location, label: String?) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val uri = buildUrl(location, label).toUri()
|
||||
val showMapsIntent = Intent(Intent.ACTION_VIEW).setData(uri)
|
||||
val chooserIntent = Intent.createChooser(showMapsIntent, null)
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.biometric.BiometricPrompt.CryptoObject
|
||||
import androidx.biometric.BiometricPrompt.PromptInfo
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.cryptography.api.EncryptionDecryptionService
|
||||
import io.element.android.libraries.cryptography.api.SecretKeyRepository
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -119,7 +120,7 @@ private class AuthenticationCallback(
|
||||
|
||||
private fun Cipher?.isValid(): Boolean {
|
||||
if (this == null) return false
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
doFinal("biometric_challenge".toByteArray())
|
||||
}.isSuccess
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.core.extensions.flatMap
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
@@ -74,7 +75,7 @@ class CreateAccountPresenter @AssistedInject constructor(
|
||||
|
||||
private fun CoroutineScope.importSession(message: String, loggedInState: MutableState<AsyncAction<SessionId>>) = launch {
|
||||
loggedInState.value = AsyncAction.Loading
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
messageParser.parse(message)
|
||||
}.flatMap { externalSession ->
|
||||
authenticationService.importCreatedSession(externalSession)
|
||||
|
||||
@@ -17,7 +17,7 @@ open class CreateAccountStateProvider : PreviewParameterProvider<CreateAccountSt
|
||||
aCreateAccountState(),
|
||||
aCreateAccountState(pageProgress = 33),
|
||||
aCreateAccountState(createAction = AsyncAction.Loading),
|
||||
aCreateAccountState(createAction = AsyncAction.Failure(Throwable("Failed to create account"))),
|
||||
aCreateAccountState(createAction = AsyncAction.Failure(RuntimeException("Failed to create account"))),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class ErrorFormatterTest {
|
||||
// region loginError
|
||||
@Test
|
||||
fun `loginError - invalid unknown error returns unknown error message`() {
|
||||
val error = Throwable("Some unknown error")
|
||||
val error = RuntimeException("Some unknown error")
|
||||
assertThat(loginError(error)).isEqualTo(CommonStrings.error_unknown)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.core.uri.ensureProtocol
|
||||
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2
|
||||
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_3
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.test
|
||||
@@ -113,7 +113,7 @@ class ChooseAccountProviderPresenterTest {
|
||||
}
|
||||
awaitItem().also {
|
||||
assertThat(it.selectedAccountProvider).isEqualTo(accountProvider1)
|
||||
authenticationService.givenChangeServerError(A_THROWABLE)
|
||||
authenticationService.givenChangeServerError(AN_EXCEPTION)
|
||||
it.eventSink(ChooseAccountProviderEvents.Continue)
|
||||
skipItems(1) // Loading
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ import io.element.android.features.login.impl.web.FakeWebClientUrlForAuthenticat
|
||||
import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_HOMESERVER
|
||||
import io.element.android.libraries.matrix.test.A_HOMESERVER_OIDC
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||
import io.element.android.libraries.oidc.api.OidcAction
|
||||
import io.element.android.libraries.oidc.api.OidcActionFlow
|
||||
@@ -118,7 +118,7 @@ class ConfirmAccountProviderPresenterTest {
|
||||
assertThat(successState.submitEnabled).isFalse()
|
||||
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
|
||||
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java)
|
||||
authenticationService.givenOidcCancelError(A_THROWABLE)
|
||||
authenticationService.givenOidcCancelError(AN_EXCEPTION)
|
||||
defaultOidcActionFlow.post(OidcAction.GoBack)
|
||||
val cancelFailureState = awaitItem()
|
||||
assertThat(cancelFailureState.loginMode).isInstanceOf(AsyncData.Failure::class.java)
|
||||
@@ -173,7 +173,7 @@ class ConfirmAccountProviderPresenterTest {
|
||||
assertThat(successState.submitEnabled).isFalse()
|
||||
assertThat(successState.loginMode).isInstanceOf(AsyncData.Success::class.java)
|
||||
assertThat(successState.loginMode.dataOrNull()).isInstanceOf(LoginMode.Oidc::class.java)
|
||||
authenticationService.givenLoginError(A_THROWABLE)
|
||||
authenticationService.givenLoginError(AN_EXCEPTION)
|
||||
defaultOidcActionFlow.post(OidcAction.Success("aUrl"))
|
||||
val cancelLoadingState = awaitItem()
|
||||
assertThat(cancelLoadingState.loginMode).isInstanceOf(AsyncData.Loading::class.java)
|
||||
@@ -225,7 +225,7 @@ class ConfirmAccountProviderPresenterTest {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
authenticationService.givenChangeServerError(Throwable())
|
||||
authenticationService.givenChangeServerError(RuntimeException())
|
||||
initialState.eventSink.invoke(ConfirmAccountProviderEvents.Continue)
|
||||
skipItems(1) // Loading
|
||||
val failureState = awaitItem()
|
||||
@@ -246,7 +246,7 @@ class ConfirmAccountProviderPresenterTest {
|
||||
val initialState = awaitItem()
|
||||
|
||||
// Submit will return an error
|
||||
authenticationService.givenChangeServerError(A_THROWABLE)
|
||||
authenticationService.givenChangeServerError(AN_EXCEPTION)
|
||||
initialState.eventSink(ConfirmAccountProviderEvents.Continue)
|
||||
|
||||
skipItems(1) // Loading
|
||||
|
||||
@@ -16,11 +16,14 @@ import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.api.auth.external.ExternalSession
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
|
||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
@@ -89,12 +92,16 @@ class CreateAccountPresenterTest {
|
||||
defaultLoginUserStory.setLoginFlowIsDone(false)
|
||||
assertThat(defaultLoginUserStory.loginFlowIsDone.value).isFalse()
|
||||
val lambda = lambdaRecorder<String, ExternalSession> { _ -> anExternalSession() }
|
||||
val sessionVerificationService = FakeSessionVerificationService()
|
||||
val client = FakeMatrixClient(sessionVerificationService = sessionVerificationService)
|
||||
val clientProvider = FakeMatrixClientProvider(getClient = { Result.success(client) })
|
||||
val presenter = createPresenter(
|
||||
authenticationService = FakeMatrixAuthenticationService(
|
||||
importCreatedSessionLambda = { Result.success(A_SESSION_ID) }
|
||||
),
|
||||
messageParser = FakeMessageParser(lambda),
|
||||
defaultLoginUserStory = defaultLoginUserStory,
|
||||
clientProvider = clientProvider,
|
||||
)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
@@ -102,6 +109,7 @@ class CreateAccountPresenterTest {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(CreateAccountEvents.OnMessageReceived("aMessage"))
|
||||
assertThat(awaitItem().createAction.isLoading()).isTrue()
|
||||
sessionVerificationService.emitVerifiedStatus(SessionVerifiedStatus.Verified)
|
||||
assertThat(awaitItem().createAction.dataOrNull()).isEqualTo(A_SESSION_ID)
|
||||
}
|
||||
lambda.assertions().isCalledOnce().with(value("aMessage"))
|
||||
|
||||
@@ -14,10 +14,10 @@ import io.element.android.features.login.impl.DefaultLoginUserStory
|
||||
import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_HOMESERVER
|
||||
import io.element.android.libraries.matrix.test.A_PASSWORD
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
@@ -96,12 +96,12 @@ class LoginPasswordPresenterTest {
|
||||
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
|
||||
skipItems(1)
|
||||
val loginAndPasswordState = awaitItem()
|
||||
authenticationService.givenLoginError(A_THROWABLE)
|
||||
authenticationService.givenLoginError(AN_EXCEPTION)
|
||||
loginAndPasswordState.eventSink.invoke(LoginPasswordEvents.Submit)
|
||||
val submitState = awaitItem()
|
||||
assertThat(submitState.loginAction).isInstanceOf(AsyncData.Loading::class.java)
|
||||
val loggedInState = awaitItem()
|
||||
assertThat(loggedInState.loginAction).isEqualTo(AsyncData.Failure<SessionId>(A_THROWABLE))
|
||||
assertThat(loggedInState.loginAction).isEqualTo(AsyncData.Failure<SessionId>(AN_EXCEPTION))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,13 +117,13 @@ class LoginPasswordPresenterTest {
|
||||
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
|
||||
skipItems(1)
|
||||
val loginAndPasswordState = awaitItem()
|
||||
authenticationService.givenLoginError(A_THROWABLE)
|
||||
authenticationService.givenLoginError(AN_EXCEPTION)
|
||||
loginAndPasswordState.eventSink.invoke(LoginPasswordEvents.Submit)
|
||||
val submitState = awaitItem()
|
||||
assertThat(submitState.loginAction).isInstanceOf(AsyncData.Loading::class.java)
|
||||
val loggedInState = awaitItem()
|
||||
// Check an error was returned
|
||||
assertThat(loggedInState.loginAction).isEqualTo(AsyncData.Failure<SessionId>(A_THROWABLE))
|
||||
assertThat(loggedInState.loginAction).isEqualTo(AsyncData.Failure<SessionId>(AN_EXCEPTION))
|
||||
// Assert the error is then cleared
|
||||
loggedInState.eventSink(LoginPasswordEvents.ClearError)
|
||||
val clearedState = awaitItem()
|
||||
|
||||
@@ -24,9 +24,9 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER
|
||||
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2
|
||||
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_3
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
|
||||
import io.element.android.libraries.matrix.test.A_LOGIN_HINT
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.oidc.api.OidcActionFlow
|
||||
@@ -192,7 +192,7 @@ class OnBoardingPresenterTest {
|
||||
skipItems(3)
|
||||
awaitItem().also {
|
||||
assertThat(it.defaultAccountProvider).isEqualTo(A_HOMESERVER_URL)
|
||||
authenticationService.givenChangeServerError(A_THROWABLE)
|
||||
authenticationService.givenChangeServerError(AN_EXCEPTION)
|
||||
it.eventSink(OnBoardingEvents.OnSignIn(A_HOMESERVER_URL))
|
||||
skipItems(1) // Loading
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
@@ -165,7 +165,7 @@ class LogoutPresenterTest {
|
||||
fun `present - logout with error then cancel`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
logoutLambda = { _, _ ->
|
||||
throw A_THROWABLE
|
||||
throw AN_EXCEPTION
|
||||
}
|
||||
}
|
||||
val presenter = createLogoutPresenter(
|
||||
@@ -182,7 +182,7 @@ class LogoutPresenterTest {
|
||||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(A_THROWABLE))
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
|
||||
errorState.eventSink.invoke(LogoutEvents.CloseDialogs)
|
||||
val finalState = awaitItem()
|
||||
assertThat(finalState.logoutAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
@@ -194,9 +194,7 @@ class LogoutPresenterTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
logoutLambda = { ignoreSdkError, _ ->
|
||||
if (!ignoreSdkError) {
|
||||
throw A_THROWABLE
|
||||
} else {
|
||||
null
|
||||
throw AN_EXCEPTION
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +212,7 @@ class LogoutPresenterTest {
|
||||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(A_THROWABLE))
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
|
||||
errorState.eventSink.invoke(LogoutEvents.Logout(ignoreSdkError = true))
|
||||
val loadingState2 = awaitItem()
|
||||
assertThat(loadingState2.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
|
||||
@@ -17,7 +17,7 @@ import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupUploadState
|
||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
@@ -117,7 +117,7 @@ class DirectLogoutPresenterTest {
|
||||
fun `present - logout with error then cancel`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
logoutLambda = { _, _ ->
|
||||
throw A_THROWABLE
|
||||
throw AN_EXCEPTION
|
||||
}
|
||||
}
|
||||
val presenter = createDirectLogoutPresenter(
|
||||
@@ -134,7 +134,7 @@ class DirectLogoutPresenterTest {
|
||||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(A_THROWABLE))
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
|
||||
errorState.eventSink.invoke(DirectLogoutEvents.CloseDialogs)
|
||||
val finalState = awaitItem()
|
||||
assertThat(finalState.logoutAction).isEqualTo(AsyncAction.Uninitialized)
|
||||
@@ -146,9 +146,7 @@ class DirectLogoutPresenterTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
logoutLambda = { ignoreSdkError, _ ->
|
||||
if (!ignoreSdkError) {
|
||||
throw A_THROWABLE
|
||||
} else {
|
||||
null
|
||||
throw AN_EXCEPTION
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,7 +164,7 @@ class DirectLogoutPresenterTest {
|
||||
val loadingState = awaitItem()
|
||||
assertThat(loadingState.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(A_THROWABLE))
|
||||
assertThat(errorState.logoutAction).isEqualTo(AsyncAction.Failure(AN_EXCEPTION))
|
||||
errorState.eventSink.invoke(DirectLogoutEvents.Logout(ignoreSdkError = true))
|
||||
val loadingState2 = awaitItem()
|
||||
assertThat(loadingState2.logoutAction).isInstanceOf(AsyncAction.Loading::class.java)
|
||||
|
||||
@@ -56,6 +56,7 @@ import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
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.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
@@ -387,7 +388,7 @@ class MessagesPresenter @AssistedInject constructor(
|
||||
|
||||
private fun CoroutineScope.reinviteOtherUser(inviteProgress: MutableState<AsyncData<Unit>>) = launch(dispatchers.io) {
|
||||
inviteProgress.value = AsyncData.Loading()
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val memberList = when (val memberState = room.membersStateFlow.value) {
|
||||
is RoomMembersState.Ready -> memberState.roomMembers
|
||||
is RoomMembersState.Error -> memberState.prevRoomMembers.orEmpty()
|
||||
|
||||
@@ -27,6 +27,7 @@ import io.element.android.libraries.androidutils.file.safeDelete
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.coroutine.firstInstanceOf
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
@@ -240,7 +241,7 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(
|
||||
sendActionState: MutableState<SendActionState>,
|
||||
dismissAfterSend: Boolean,
|
||||
replyParameters: ReplyParameters?,
|
||||
) = runCatching {
|
||||
) = runCatchingExceptions {
|
||||
val context = coroutineContext
|
||||
val progressCallback = object : ProgressCallback {
|
||||
override fun onProgress(current: Long, total: Long) {
|
||||
|
||||
@@ -24,7 +24,7 @@ open class ForwardMessagesStateProvider : PreviewParameterProvider<ForwardMessag
|
||||
)
|
||||
),
|
||||
aForwardMessagesState(
|
||||
forwardAction = AsyncAction.Failure(Throwable("error")),
|
||||
forwardAction = AsyncAction.Failure(RuntimeException("error")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import io.element.android.features.messages.impl.messagecomposer.suggestions.Sug
|
||||
import io.element.android.features.messages.impl.timeline.TimelineController
|
||||
import io.element.android.features.messages.impl.utils.TextPillificationHelper
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
@@ -512,7 +513,7 @@ class MessageComposerPresenter @AssistedInject constructor(
|
||||
private suspend fun sendMedia(
|
||||
uri: Uri,
|
||||
mimeType: String,
|
||||
) = runCatching {
|
||||
) = runCatchingExceptions {
|
||||
mediaSender.sendMedia(
|
||||
uri = uri,
|
||||
mimeType = mimeType,
|
||||
|
||||
@@ -17,7 +17,7 @@ open class ReportMessageStateProvider : PreviewParameterProvider<ReportMessageSt
|
||||
aReportMessageState(reason = "This user is making the chat very toxic."),
|
||||
aReportMessageState(reason = "This user is making the chat very toxic.", blockUser = true),
|
||||
aReportMessageState(reason = "This user is making the chat very toxic.", blockUser = true, result = AsyncAction.Loading),
|
||||
aReportMessageState(reason = "This user is making the chat very toxic.", blockUser = true, result = AsyncAction.Failure(Throwable("error"))),
|
||||
aReportMessageState(reason = "This user is making the chat very toxic.", blockUser = true, result = AsyncAction.Failure(RuntimeException("error"))),
|
||||
aReportMessageState(reason = "This user is making the chat very toxic.", blockUser = true, result = AsyncAction.Success(Unit)),
|
||||
// Add other states here
|
||||
)
|
||||
|
||||
@@ -62,11 +62,11 @@ import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransa
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_CAPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
@@ -744,7 +744,7 @@ class MessagesPresenterTest {
|
||||
canUserPinUnpinResult = { Result.success(true) },
|
||||
),
|
||||
typingNoticeResult = { Result.success(Unit) },
|
||||
inviteUserResult = { Result.failure(Throwable("Oops!")) },
|
||||
inviteUserResult = { Result.failure(RuntimeException("Oops!")) },
|
||||
)
|
||||
room.givenRoomMembersState(
|
||||
RoomMembersState.Ready(
|
||||
@@ -892,7 +892,7 @@ class MessagesPresenterTest {
|
||||
@Test
|
||||
fun `present - handle action pin`() = runTest {
|
||||
val successPinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) }
|
||||
val failurePinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(A_THROWABLE) }
|
||||
val failurePinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(AN_EXCEPTION) }
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val timeline = FakeTimeline()
|
||||
val room = FakeJoinedRoom(
|
||||
@@ -932,7 +932,7 @@ class MessagesPresenterTest {
|
||||
@Test
|
||||
fun `present - handle action unpin`() = runTest {
|
||||
val successUnpinEventLambda = lambdaRecorder { _: EventId -> Result.success(true) }
|
||||
val failureUnpinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(A_THROWABLE) }
|
||||
val failureUnpinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(AN_EXCEPTION) }
|
||||
val timeline = FakeTimeline()
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val room = FakeJoinedRoom(
|
||||
|
||||
@@ -25,7 +25,7 @@ import io.element.android.libraries.matrix.api.sync.SyncService
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
|
||||
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
|
||||
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
|
||||
@@ -157,7 +157,7 @@ class PinnedMessagesListPresenterTest {
|
||||
@Test
|
||||
fun `present - unpin event`() = runTest {
|
||||
val successUnpinEventLambda = lambdaRecorder { _: EventId? -> Result.success(true) }
|
||||
val failureUnpinEventLambda = lambdaRecorder { _: EventId? -> Result.failure<Boolean>(A_THROWABLE) }
|
||||
val failureUnpinEventLambda = lambdaRecorder { _: EventId? -> Result.failure<Boolean>(AN_EXCEPTION) }
|
||||
val pinnedEventsTimeline = createPinnedMessagesTimeline()
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val room = FakeJoinedRoom(
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.messages.impl.utils.FakeMentionSpanFormatter
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
|
||||
import io.element.android.libraries.textcomposer.mentions.MentionSpanProvider
|
||||
@@ -35,7 +36,7 @@ class DefaultHtmlConverterProviderTest {
|
||||
|
||||
@Test
|
||||
fun `calling provide without calling Update first should throw an exception`() {
|
||||
val exception = runCatching { provider.provide() }.exceptionOrNull()
|
||||
val exception = runCatchingExceptions { provider.provide() }.exceptionOrNull()
|
||||
|
||||
assertThat(exception).isInstanceOf(IllegalStateException::class.java)
|
||||
}
|
||||
@@ -47,7 +48,7 @@ class DefaultHtmlConverterProviderTest {
|
||||
provider.Update()
|
||||
}
|
||||
}
|
||||
val htmlConverter = runCatching { provider.provide() }.getOrNull()
|
||||
val htmlConverter = runCatchingExceptions { provider.provide() }.getOrNull()
|
||||
|
||||
assertThat(htmlConverter).isNotNull()
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
liveTimeline = FakeTimeline(
|
||||
timelineItems = flowOf(emptyList()),
|
||||
),
|
||||
createTimelineResult = { Result.failure(Throwable("An error")) },
|
||||
createTimelineResult = { Result.failure(RuntimeException("An error")) },
|
||||
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.features.migration.impl.migrations
|
||||
|
||||
import android.content.Context
|
||||
import com.squareup.anvil.annotations.ContributesMultibinding
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
@@ -26,6 +27,6 @@ class AppMigration04 @Inject constructor(
|
||||
override val order: Int = 4
|
||||
|
||||
override suspend fun migrate() {
|
||||
runCatching { context.getDatabasePath(NOTIFICATION_FILE_NAME).delete() }
|
||||
runCatchingExceptions { context.getDatabasePath(NOTIFICATION_FILE_NAME).delete() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package io.element.android.features.poll.impl.data
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
@@ -22,7 +23,7 @@ class PollRepository @Inject constructor(
|
||||
private val room: JoinedRoom,
|
||||
private val timelineProvider: TimelineProvider,
|
||||
) {
|
||||
suspend fun getPoll(eventId: EventId): Result<PollContent> = runCatching {
|
||||
suspend fun getPoll(eventId: EventId): Result<PollContent> = runCatchingExceptions {
|
||||
timelineProvider
|
||||
.getActiveTimeline()
|
||||
.timelineItems
|
||||
|
||||
@@ -21,7 +21,7 @@ class BlockedUsersStateProvider : PreviewParameterProvider<BlockedUsersState> {
|
||||
aBlockedUsersState(blockedUsers = emptyList()),
|
||||
aBlockedUsersState(unblockUserAction = AsyncAction.ConfirmingNoParams),
|
||||
aBlockedUsersState(unblockUserAction = AsyncAction.Loading),
|
||||
aBlockedUsersState(unblockUserAction = AsyncAction.Failure(Throwable("Failed to unblock user"))),
|
||||
aBlockedUsersState(unblockUserAction = AsyncAction.Failure(RuntimeException("Failed to unblock user"))),
|
||||
aBlockedUsersState(unblockUserAction = AsyncAction.Success(Unit)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.featureflag.api.Feature
|
||||
@@ -201,8 +202,8 @@ class DeveloperSettingsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun customElementCallUrlValidator(url: String?): Boolean {
|
||||
return runCatching {
|
||||
if (url.isNullOrEmpty()) return@runCatching
|
||||
return runCatchingExceptions {
|
||||
if (url.isNullOrEmpty()) return@runCatchingExceptions
|
||||
val parsedUrl = URL(url)
|
||||
if (parsedUrl.protocol !in listOf("http", "https")) error("Incorrect protocol")
|
||||
if (parsedUrl.host.isNullOrBlank()) error("Missing host")
|
||||
|
||||
@@ -22,6 +22,7 @@ import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runUpdatingStateNoSuccess
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||
@@ -209,7 +210,7 @@ class NotificationSettingsPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private fun CoroutineScope.fixConfigurationMismatch(target: MutableState<NotificationSettingsState.MatrixSettings>) = launch {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val groupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = false, isOneToOne = false).getOrThrow()
|
||||
val encryptedGroupDefaultMode = notificationSettingsService.getDefaultRoomNotificationMode(isEncrypted = true, isOneToOne = false).getOrThrow()
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ open class NotificationSettingsStateProvider : PreviewParameterProvider<Notifica
|
||||
aValidNotificationSettingsState(systemNotificationsEnabled = false),
|
||||
aValidNotificationSettingsState(),
|
||||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Loading),
|
||||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
|
||||
aValidNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(RuntimeException("error"))),
|
||||
aValidNotificationSettingsState(
|
||||
availablePushDistributors = listOf(aDistributor("Firebase")),
|
||||
changeNotificationSettingAction = AsyncAction.Failure(Throwable("error")),
|
||||
changeNotificationSettingAction = AsyncAction.Failure(RuntimeException("error")),
|
||||
),
|
||||
aValidNotificationSettingsState(availablePushDistributors = listOf(aDistributor("Firebase"))),
|
||||
aValidNotificationSettingsState(showChangePushProviderDialog = true),
|
||||
|
||||
@@ -21,7 +21,7 @@ open class EditDefaultNotificationSettingStateProvider : PreviewParameterProvide
|
||||
anEditDefaultNotificationSettingsState(),
|
||||
anEditDefaultNotificationSettingsState(isOneToOne = true),
|
||||
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Loading),
|
||||
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
|
||||
anEditDefaultNotificationSettingsState(changeNotificationSettingAction = AsyncAction.Failure(RuntimeException("error"))),
|
||||
anEditDefaultNotificationSettingsState(displayMentionsOnlyDisclaimer = true),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
@@ -168,7 +169,7 @@ class EditUserProfilePresenter @AssistedInject constructor(
|
||||
}
|
||||
|
||||
private suspend fun updateAvatar(avatarUri: Uri?): Result<Unit> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
if (avatarUri != null) {
|
||||
val preprocessed = mediaPreProcessor.process(
|
||||
uri = avatarUri,
|
||||
|
||||
@@ -14,7 +14,7 @@ import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingPresenter
|
||||
import io.element.android.features.preferences.impl.notifications.edit.EditDefaultNotificationSettingStateEvents
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||
import io.element.android.libraries.matrix.test.room.aRoomSummary
|
||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||
@@ -81,7 +81,7 @@ class EditDefaultNotificationSettingsPresenterTest {
|
||||
fun `present - edit default notification setting failed`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
val presenter = createEditDefaultNotificationSettingPresenter(notificationSettingsService)
|
||||
notificationSettingsService.givenSetDefaultNotificationModeError(A_THROWABLE)
|
||||
notificationSettingsService.givenSetDefaultNotificationModeError(AN_EXCEPTION)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
||||
@@ -16,7 +16,7 @@ import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermiss
|
||||
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
@@ -208,7 +208,7 @@ class NotificationSettingsPresenterTest {
|
||||
fun `present - clear notification settings change error`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
val presenter = createNotificationSettingsPresenter(notificationSettingsService)
|
||||
notificationSettingsService.givenSetAtRoomError(A_THROWABLE)
|
||||
notificationSettingsService.givenSetAtRoomError(AN_EXCEPTION)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
|
||||
@@ -393,7 +393,7 @@ class EditUserProfilePresenterTest {
|
||||
),
|
||||
)
|
||||
fakePickerProvider.givenResult(anotherAvatarUri)
|
||||
fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no")))
|
||||
fakeMediaPreProcessor.givenResult(Result.failure(RuntimeException("Oh no")))
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
@@ -410,7 +410,7 @@ class EditUserProfilePresenterTest {
|
||||
fun `present - sets save action to failure if name update fails`() = runTest {
|
||||
val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenSetDisplayNameResult(Result.failure(Throwable("!")))
|
||||
givenSetDisplayNameResult(Result.failure(RuntimeException("!")))
|
||||
}
|
||||
saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.UpdateDisplayName("New name"))
|
||||
}
|
||||
@@ -419,7 +419,7 @@ class EditUserProfilePresenterTest {
|
||||
fun `present - sets save action to failure if removing avatar fails`() = runTest {
|
||||
val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenRemoveAvatarResult(Result.failure(Throwable("!")))
|
||||
givenRemoveAvatarResult(Result.failure(RuntimeException("!")))
|
||||
}
|
||||
saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.HandleAvatarAction(AvatarAction.Remove))
|
||||
}
|
||||
@@ -429,7 +429,7 @@ class EditUserProfilePresenterTest {
|
||||
givenPickerReturnsFile()
|
||||
val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenUploadAvatarResult(Result.failure(Throwable("!")))
|
||||
givenUploadAvatarResult(Result.failure(RuntimeException("!")))
|
||||
}
|
||||
saveAndAssertFailure(user, matrixClient, EditUserProfileEvents.HandleAvatarAction(AvatarAction.ChoosePhoto))
|
||||
}
|
||||
@@ -439,7 +439,7 @@ class EditUserProfilePresenterTest {
|
||||
givenPickerReturnsFile()
|
||||
val user = aMatrixUser(id = A_USER_ID.value, displayName = "Name", avatarUrl = AN_AVATAR_URL)
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenSetDisplayNameResult(Result.failure(Throwable("!")))
|
||||
givenSetDisplayNameResult(Result.failure(RuntimeException("!")))
|
||||
}
|
||||
val presenter = createEditUserProfilePresenter(matrixUser = user, matrixClient = matrixClient)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
|
||||
@@ -308,7 +308,7 @@ class DefaultBugReporter @Inject constructor(
|
||||
*/
|
||||
private fun getLogFiles(): List<File> {
|
||||
return tryOrNull(
|
||||
onError = { Timber.e(it, "## getLogFiles() failed") }
|
||||
onException = { Timber.e(it, "## getLogFiles() failed") }
|
||||
) {
|
||||
val logDirectory = logDirectory()
|
||||
logDirectory.listFiles()?.toList()
|
||||
|
||||
@@ -24,6 +24,7 @@ import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.StateEventType
|
||||
@@ -216,7 +217,7 @@ class RoomDetailsEditPresenter @Inject constructor(
|
||||
}
|
||||
|
||||
private suspend fun updateAvatar(avatarUri: Uri?): Result<Unit> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
if (avatarUri != null) {
|
||||
val preprocessed = mediaPreProcessor.process(
|
||||
uri = avatarUri,
|
||||
|
||||
@@ -27,7 +27,7 @@ open class RoomDetailsEditStateProvider : PreviewParameterProvider<RoomDetailsEd
|
||||
aRoomDetailsEditState(canChangeName = true, canChangeTopic = false, canChangeAvatar = true, saveButtonEnabled = false),
|
||||
aRoomDetailsEditState(canChangeName = false, canChangeTopic = true, canChangeAvatar = false, saveButtonEnabled = false),
|
||||
aRoomDetailsEditState(saveAction = AsyncAction.Loading),
|
||||
aRoomDetailsEditState(saveAction = AsyncAction.Failure(Throwable("Whelp"))),
|
||||
aRoomDetailsEditState(saveAction = AsyncAction.Failure(RuntimeException("Whelp"))),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@ internal class RoomNotificationSettingsStateProvider : PreviewParameterProvider<
|
||||
aRoomNotificationSettingsState(),
|
||||
aRoomNotificationSettingsState(isDefault = false),
|
||||
aRoomNotificationSettingsState(setNotificationSettingAction = AsyncAction.Loading),
|
||||
aRoomNotificationSettingsState(setNotificationSettingAction = AsyncAction.Failure(Throwable("error"))),
|
||||
aRoomNotificationSettingsState(setNotificationSettingAction = AsyncAction.Failure(RuntimeException("error"))),
|
||||
aRoomNotificationSettingsState(restoreDefaultAction = AsyncAction.Loading),
|
||||
aRoomNotificationSettingsState(restoreDefaultAction = AsyncAction.Failure(Throwable("error"))),
|
||||
aRoomNotificationSettingsState(restoreDefaultAction = AsyncAction.Failure(RuntimeException("error"))),
|
||||
aRoomNotificationSettingsState(displayMentionsOnlyDisclaimer = true)
|
||||
)
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ class RoomDetailsPresenterTest {
|
||||
@Test
|
||||
fun `present - initial state when canInvite errors`() = runTest {
|
||||
val room = aJoinedRoom(
|
||||
canInviteResult = { Result.failure(Throwable("Whoops")) },
|
||||
canInviteResult = { Result.failure(RuntimeException("Whoops")) },
|
||||
canUserJoinCallResult = { Result.success(true) },
|
||||
canSendStateResult = { _, _ -> Result.success(true) },
|
||||
)
|
||||
@@ -277,7 +277,7 @@ class RoomDetailsPresenterTest {
|
||||
when (stateEventType) {
|
||||
StateEventType.ROOM_TOPIC -> Result.success(true)
|
||||
StateEventType.ROOM_NAME -> Result.success(false)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
canBanResult = { Result.success(false) },
|
||||
@@ -306,7 +306,7 @@ class RoomDetailsPresenterTest {
|
||||
StateEventType.ROOM_TOPIC,
|
||||
StateEventType.ROOM_NAME,
|
||||
StateEventType.ROOM_AVATAR -> Result.success(true)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
canKickResult = { Result.success(false) },
|
||||
@@ -357,7 +357,7 @@ class RoomDetailsPresenterTest {
|
||||
StateEventType.ROOM_AVATAR,
|
||||
StateEventType.ROOM_TOPIC,
|
||||
StateEventType.ROOM_NAME -> Result.success(true)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
userDisplayNameResult = { Result.success(A_USER_NAME) },
|
||||
@@ -403,7 +403,7 @@ class RoomDetailsPresenterTest {
|
||||
StateEventType.ROOM_TOPIC,
|
||||
StateEventType.ROOM_NAME,
|
||||
StateEventType.ROOM_AVATAR -> Result.success(true)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
canKickResult = {
|
||||
@@ -436,7 +436,7 @@ class RoomDetailsPresenterTest {
|
||||
StateEventType.ROOM_TOPIC,
|
||||
StateEventType.ROOM_NAME,
|
||||
StateEventType.ROOM_AVATAR -> Result.success(false)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
canBanResult = {
|
||||
@@ -468,7 +468,7 @@ class RoomDetailsPresenterTest {
|
||||
StateEventType.ROOM_AVATAR,
|
||||
StateEventType.ROOM_NAME -> Result.success(true)
|
||||
StateEventType.ROOM_TOPIC -> Result.success(false)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
canKickResult = {
|
||||
@@ -500,7 +500,7 @@ class RoomDetailsPresenterTest {
|
||||
StateEventType.ROOM_AVATAR,
|
||||
StateEventType.ROOM_TOPIC,
|
||||
StateEventType.ROOM_NAME -> Result.success(true)
|
||||
else -> Result.failure(Throwable("Whelp"))
|
||||
else -> Result.failure(RuntimeException("Whelp"))
|
||||
}
|
||||
},
|
||||
canKickResult = {
|
||||
|
||||
@@ -124,7 +124,7 @@ class RoomDetailsEditPresenterTest {
|
||||
when (stateEventType) {
|
||||
StateEventType.ROOM_NAME -> Result.success(true)
|
||||
StateEventType.ROOM_AVATAR -> Result.success(false)
|
||||
StateEventType.ROOM_TOPIC -> Result.failure(Throwable("Oops"))
|
||||
StateEventType.ROOM_TOPIC -> Result.failure(RuntimeException("Oops"))
|
||||
else -> lambdaError()
|
||||
}
|
||||
},
|
||||
@@ -157,7 +157,7 @@ class RoomDetailsEditPresenterTest {
|
||||
when (stateEventType) {
|
||||
StateEventType.ROOM_NAME -> Result.success(false)
|
||||
StateEventType.ROOM_AVATAR -> Result.success(true)
|
||||
StateEventType.ROOM_TOPIC -> Result.failure(Throwable("Oops"))
|
||||
StateEventType.ROOM_TOPIC -> Result.failure(RuntimeException("Oops"))
|
||||
else -> lambdaError()
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ class RoomDetailsEditPresenterTest {
|
||||
canSendStateResult = { _, stateEventType ->
|
||||
when (stateEventType) {
|
||||
StateEventType.ROOM_NAME -> Result.success(false)
|
||||
StateEventType.ROOM_AVATAR -> Result.failure(Throwable("Oops"))
|
||||
StateEventType.ROOM_AVATAR -> Result.failure(RuntimeException("Oops"))
|
||||
StateEventType.ROOM_TOPIC -> Result.success(true)
|
||||
else -> lambdaError()
|
||||
}
|
||||
@@ -559,7 +559,7 @@ class RoomDetailsEditPresenterTest {
|
||||
canSendStateResult = { _, _ -> Result.success(true) }
|
||||
)
|
||||
fakePickerProvider.givenResult(anotherAvatarUri)
|
||||
fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no")))
|
||||
fakeMediaPreProcessor.givenResult(Result.failure(RuntimeException("Oh no")))
|
||||
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
|
||||
val presenter = createRoomDetailsEditPresenter(
|
||||
room = room,
|
||||
@@ -580,7 +580,7 @@ class RoomDetailsEditPresenterTest {
|
||||
topic = "My topic",
|
||||
displayName = "Name",
|
||||
avatarUrl = AN_AVATAR_URL,
|
||||
setNameResult = { Result.failure(Throwable("!")) },
|
||||
setNameResult = { Result.failure(RuntimeException("!")) },
|
||||
canSendStateResult = { _, _ -> Result.success(true) }
|
||||
)
|
||||
saveAndAssertFailure(room, RoomDetailsEditEvents.UpdateRoomName("New name"), deleteCallbackNumberOfInvocation = 1)
|
||||
@@ -592,7 +592,7 @@ class RoomDetailsEditPresenterTest {
|
||||
topic = "My topic",
|
||||
displayName = "Name",
|
||||
avatarUrl = AN_AVATAR_URL,
|
||||
setTopicResult = { Result.failure(Throwable("!")) },
|
||||
setTopicResult = { Result.failure(RuntimeException("!")) },
|
||||
canSendStateResult = { _, _ -> Result.success(true) }
|
||||
)
|
||||
saveAndAssertFailure(room, RoomDetailsEditEvents.UpdateRoomTopic("New topic"), deleteCallbackNumberOfInvocation = 1)
|
||||
@@ -604,7 +604,7 @@ class RoomDetailsEditPresenterTest {
|
||||
topic = "My topic",
|
||||
displayName = "Name",
|
||||
avatarUrl = AN_AVATAR_URL,
|
||||
removeAvatarResult = { Result.failure(Throwable("!")) },
|
||||
removeAvatarResult = { Result.failure(RuntimeException("!")) },
|
||||
canSendStateResult = { _, _ -> Result.success(true) }
|
||||
)
|
||||
saveAndAssertFailure(room, RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.Remove), deleteCallbackNumberOfInvocation = 2)
|
||||
@@ -617,7 +617,7 @@ class RoomDetailsEditPresenterTest {
|
||||
topic = "My topic",
|
||||
displayName = "Name",
|
||||
avatarUrl = AN_AVATAR_URL,
|
||||
updateAvatarResult = { _, _ -> Result.failure(Throwable("!")) },
|
||||
updateAvatarResult = { _, _ -> Result.failure(RuntimeException("!")) },
|
||||
canSendStateResult = { _, _ -> Result.success(true) }
|
||||
)
|
||||
saveAndAssertFailure(room, RoomDetailsEditEvents.HandleAvatarAction(AvatarAction.ChoosePhoto), deleteCallbackNumberOfInvocation = 2)
|
||||
@@ -630,7 +630,7 @@ class RoomDetailsEditPresenterTest {
|
||||
topic = "My topic",
|
||||
displayName = "Name",
|
||||
avatarUrl = AN_AVATAR_URL,
|
||||
setTopicResult = { Result.failure(Throwable("!")) },
|
||||
setTopicResult = { Result.failure(RuntimeException("!")) },
|
||||
canSendStateResult = { _, _ -> Result.success(true) }
|
||||
)
|
||||
val deleteCallback = lambdaRecorder<Uri?, Unit> {}
|
||||
|
||||
@@ -205,7 +205,7 @@ class RoomDetailsEditViewTest {
|
||||
rule.setRoomDetailsEditView(
|
||||
aRoomDetailsEditState(
|
||||
eventSink = eventsRecorder,
|
||||
saveAction = AsyncAction.Failure(Throwable("Whelp")),
|
||||
saveAction = AsyncAction.Failure(RuntimeException("Whelp")),
|
||||
),
|
||||
)
|
||||
rule.clickOn(CommonStrings.action_ok)
|
||||
|
||||
@@ -186,7 +186,7 @@ class RoomMemberListPresenterTest {
|
||||
val presenter = createPresenter(
|
||||
joinedRoom = FakeJoinedRoom(
|
||||
baseRoom = FakeBaseRoom(
|
||||
canInviteResult = { Result.failure(Throwable("Eek")) },
|
||||
canInviteResult = { Result.failure(RuntimeException("Eek")) },
|
||||
updateMembersResult = { Result.success(Unit) }
|
||||
)
|
||||
)
|
||||
|
||||
@@ -78,8 +78,8 @@ class RoomMemberDetailsPresenterTest {
|
||||
avatarUrl = "Alice Avatar url",
|
||||
)
|
||||
val room = aJoinedRoom(
|
||||
userDisplayNameResult = { Result.failure(Throwable()) },
|
||||
userAvatarUrlResult = { Result.failure(Throwable()) },
|
||||
userDisplayNameResult = { Result.failure(RuntimeException()) },
|
||||
userAvatarUrlResult = { Result.failure(RuntimeException()) },
|
||||
getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) },
|
||||
).apply {
|
||||
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
|
||||
|
||||
@@ -13,8 +13,8 @@ import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.features.roomdetails.impl.aJoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
|
||||
import io.element.android.tests.testutils.awaitLastSequentialItem
|
||||
@@ -71,7 +71,7 @@ class RoomNotificationSettingsPresenterTest {
|
||||
@Test
|
||||
fun `present - notification settings set custom failed`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
notificationSettingsService.givenSetNotificationModeError(A_THROWABLE)
|
||||
notificationSettingsService.givenSetNotificationModeError(AN_EXCEPTION)
|
||||
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
@@ -131,7 +131,7 @@ class RoomNotificationSettingsPresenterTest {
|
||||
@Test
|
||||
fun `present - notification settings restore default failed`() = runTest {
|
||||
val notificationSettingsService = FakeNotificationSettingsService()
|
||||
notificationSettingsService.givenRestoreDefaultNotificationModeError(A_THROWABLE)
|
||||
notificationSettingsService.givenRestoreDefaultNotificationModeError(AN_EXCEPTION)
|
||||
val presenter = createRoomNotificationSettingsPresenter(notificationSettingsService)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.compose.ui.test.performClick
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||
import io.element.android.libraries.matrix.api.room.toMatrixUser
|
||||
@@ -41,7 +42,7 @@ class ChangeRolesViewTest {
|
||||
|
||||
@Test
|
||||
fun `passing a 'USER' role throws an exception`() {
|
||||
val exception = runCatching {
|
||||
val exception = runCatchingExceptions {
|
||||
rule.setChangeRolesContent(
|
||||
state = aChangeRolesState(
|
||||
role = RoomMember.Role.USER,
|
||||
|
||||
@@ -27,6 +27,7 @@ import io.element.android.libraries.preferences.api.store.SessionPreferencesStor
|
||||
import io.element.android.services.appnavstate.api.ActiveRoomsHolder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
class SharePresenter @AssistedInject constructor(
|
||||
@Assisted private val intent: Intent,
|
||||
@@ -89,12 +90,21 @@ class SharePresenter @AssistedInject constructor(
|
||||
)
|
||||
filesToShare
|
||||
.map { fileToShare ->
|
||||
mediaSender.sendMedia(
|
||||
val result = mediaSender.sendMedia(
|
||||
uri = fileToShare.uri,
|
||||
mimeType = fileToShare.mimeType,
|
||||
).isSuccess
|
||||
)
|
||||
// If the coroutine was cancelled, destroy the room and rethrow the exception
|
||||
val cancellationException = result.exceptionOrNull() as? CancellationException
|
||||
if (cancellationException != null) {
|
||||
if (activeRoomsHolder.getActiveRoomMatching(matrixClient.sessionId, roomId) == null) {
|
||||
room.destroy()
|
||||
}
|
||||
throw cancellationException
|
||||
}
|
||||
result.isSuccess
|
||||
}
|
||||
.all { it }
|
||||
.all { isSuccess -> isSuccess }
|
||||
.also {
|
||||
if (activeRoomsHolder.getActiveRoomMatching(matrixClient.sessionId, roomId) == null) {
|
||||
room.destroy()
|
||||
|
||||
@@ -24,7 +24,7 @@ open class ShareStateProvider : PreviewParameterProvider<ShareState> {
|
||||
)
|
||||
),
|
||||
aShareState(
|
||||
shareAction = AsyncAction.Failure(Throwable("error")),
|
||||
shareAction = AsyncAction.Failure(RuntimeException("error")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
@@ -215,7 +214,7 @@ class UserProfilePresenterTest {
|
||||
@Test
|
||||
fun `present - BlockUser with error`() = runTest {
|
||||
val matrixClient = createFakeMatrixClient(
|
||||
ignoreUserResult = { Result.failure(A_THROWABLE) }
|
||||
ignoreUserResult = { Result.failure(AN_EXCEPTION) }
|
||||
)
|
||||
val presenter = createUserProfilePresenter(client = matrixClient)
|
||||
presenter.test {
|
||||
@@ -223,7 +222,7 @@ class UserProfilePresenterTest {
|
||||
initialState.eventSink(UserProfileEvents.BlockUser(needsConfirmation = false))
|
||||
assertThat(awaitItem().isBlocked.isLoading()).isTrue()
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(A_THROWABLE)
|
||||
assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(AN_EXCEPTION)
|
||||
// Clear error
|
||||
initialState.eventSink(UserProfileEvents.ClearBlockUserError)
|
||||
assertThat(awaitItem().isBlocked).isEqualTo(AsyncData.Success(false))
|
||||
@@ -233,7 +232,7 @@ class UserProfilePresenterTest {
|
||||
@Test
|
||||
fun `present - UnblockUser with error`() = runTest {
|
||||
val matrixClient = createFakeMatrixClient(
|
||||
unIgnoreUserResult = { Result.failure(A_THROWABLE) }
|
||||
unIgnoreUserResult = { Result.failure(AN_EXCEPTION) }
|
||||
)
|
||||
val presenter = createUserProfilePresenter(client = matrixClient)
|
||||
presenter.test {
|
||||
@@ -241,7 +240,7 @@ class UserProfilePresenterTest {
|
||||
initialState.eventSink(UserProfileEvents.UnblockUser(needsConfirmation = false))
|
||||
assertThat(awaitItem().isBlocked.isLoading()).isTrue()
|
||||
val errorState = awaitItem()
|
||||
assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(A_THROWABLE)
|
||||
assertThat(errorState.isBlocked.errorOrNull()).isEqualTo(AN_EXCEPTION)
|
||||
// Clear error
|
||||
initialState.eventSink(UserProfileEvents.ClearBlockUserError)
|
||||
assertThat(awaitItem().isBlocked).isEqualTo(AsyncData.Success(true))
|
||||
@@ -265,7 +264,7 @@ class UserProfilePresenterTest {
|
||||
|
||||
@Test
|
||||
fun `present - start DM action failure scenario`() = runTest {
|
||||
val startDMFailureResult = AsyncAction.Failure(A_THROWABLE)
|
||||
val startDMFailureResult = AsyncAction.Failure(AN_EXCEPTION)
|
||||
val executeResult = lambdaRecorder<MatrixUser, Boolean, MutableState<AsyncAction<RoomId>>, Unit> { _, _, actionState ->
|
||||
actionState.value = startDMFailureResult
|
||||
}
|
||||
|
||||
@@ -206,6 +206,7 @@ class OutgoingVerificationPresenterTest {
|
||||
)
|
||||
)
|
||||
service.emitVerificationFlowState(VerificationFlowState.DidFinish)
|
||||
service.emitVerifiedStatus(SessionVerifiedStatus.Verified)
|
||||
assertThat(awaitItem().step).isEqualTo(Step.Completed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.features.viewfolder.impl.file
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
@@ -23,7 +24,7 @@ class DefaultFileContentReader @Inject constructor(
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
) : FileContentReader {
|
||||
override suspend fun getLines(path: String): Result<List<String>> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
File(path).readLines()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.annotation.RequiresApi
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.androidutils.system.toast
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
@@ -40,7 +41,7 @@ class DefaultFileSave @Inject constructor(
|
||||
path: String,
|
||||
) {
|
||||
withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
saveOnDiskUsingMediaStore(path)
|
||||
} else {
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.net.Uri
|
||||
import androidx.core.content.FileProvider
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
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
|
||||
@@ -37,7 +38,7 @@ class DefaultFileShare @Inject constructor(
|
||||
override suspend fun share(
|
||||
path: String,
|
||||
) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val file = File(path)
|
||||
val shareableUri = file.toShareableUri()
|
||||
val shareMediaIntent = Intent(Intent.ACTION_SEND)
|
||||
|
||||
@@ -37,6 +37,7 @@ datetime = "0.6.2"
|
||||
serialization_json = "1.8.1"
|
||||
|
||||
#other
|
||||
detekt = "1.23.8"
|
||||
coil = "3.1.0"
|
||||
showkase = "1.0.3"
|
||||
appyx = "1.7.1"
|
||||
@@ -152,6 +153,8 @@ test_parameter_injector = "com.google.testparameterinjector:test-parameter-injec
|
||||
test_robolectric = "org.robolectric:robolectric:4.14.1"
|
||||
test_appyx_junit = { module = "com.bumble.appyx:testing-junit4", version.ref = "appyx" }
|
||||
test_composable_preview_scanner = "io.github.sergio-sastre.ComposablePreviewScanner:android:0.6.1"
|
||||
test_detekt_api = { module = "io.gitlab.arturbosch.detekt:detekt-api", version.ref = "detekt" }
|
||||
test_detekt_test = { module = "io.gitlab.arturbosch.detekt:detekt-test", version.ref = "detekt" }
|
||||
|
||||
# Others
|
||||
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
|
||||
@@ -231,7 +234,7 @@ kotlin_serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi
|
||||
kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
anvil = { id = "dev.zacsweers.anvil", version.ref = "anvil" }
|
||||
detekt = "io.gitlab.arturbosch.detekt:1.23.8"
|
||||
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
|
||||
ktlint = "org.jlleitschuh.gradle.ktlint:12.3.0"
|
||||
dependencygraph = "com.savvasdalkitsis.module-dependency-graph:0.12"
|
||||
dependencycheck = "org.owasp.dependencycheck:12.1.1"
|
||||
|
||||
@@ -41,7 +41,7 @@ fun AudioManager.enableExternalAudioDevice() {
|
||||
selectedDevice?.let { device ->
|
||||
Timber.d("Audio device selected, type: ${device.type}")
|
||||
tryOrNull(
|
||||
onError = { failure ->
|
||||
onException = { failure ->
|
||||
Timber.e(failure, "Audio: exception when setting communication device")
|
||||
}
|
||||
) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.OpenableColumns
|
||||
import androidx.core.net.toFile
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
|
||||
fun Context.getMimeType(uri: Uri): String? = when (uri.scheme) {
|
||||
ContentResolver.SCHEME_CONTENT -> contentResolver.getType(uri)
|
||||
@@ -32,14 +33,14 @@ fun Context.getFileSize(uri: Uri): Long {
|
||||
} ?: 0
|
||||
}
|
||||
|
||||
private fun Context.getContentFileSize(uri: Uri): Long? = runCatching {
|
||||
private fun Context.getContentFileSize(uri: Uri): Long? = runCatchingExceptions {
|
||||
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
return@use cursor.getColumnIndexOrThrow(OpenableColumns.SIZE).let(cursor::getLong)
|
||||
}
|
||||
}.getOrNull()
|
||||
|
||||
private fun Context.getContentFileName(uri: Uri): String? = runCatching {
|
||||
private fun Context.getContentFileName(uri: Uri): String? = runCatchingExceptions {
|
||||
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
|
||||
cursor.moveToFirst()
|
||||
return@use cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME).let(cursor::getString)
|
||||
|
||||
@@ -17,7 +17,7 @@ import java.util.UUID
|
||||
fun File.safeDelete() {
|
||||
if (exists().not()) return
|
||||
tryOrNull(
|
||||
onError = {
|
||||
onException = {
|
||||
Timber.e(it, "Error, unable to delete file $path")
|
||||
},
|
||||
operation = {
|
||||
@@ -30,7 +30,7 @@ fun File.safeDelete() {
|
||||
|
||||
fun File.safeRenameTo(dest: File) {
|
||||
tryOrNull(
|
||||
onError = {
|
||||
onException = {
|
||||
Timber.e(it, "Error, unable to rename file $path to ${dest.path}")
|
||||
},
|
||||
operation = {
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.text.util.Linkify
|
||||
import androidx.core.text.getSpans
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.text.util.LinkifyCompat
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import timber.log.Timber
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
@@ -48,7 +49,7 @@ object LinkifyHelper {
|
||||
|
||||
// Try to avoid including trailing punctuation in the link.
|
||||
// Since this might fail in some edge cases, we catch the exception and just use the original end index.
|
||||
val newEnd = runCatching {
|
||||
val newEnd = runCatchingExceptions {
|
||||
adjustLinkifiedUrlSpanEndIndex(spannable, start, end)
|
||||
}.onFailure {
|
||||
Timber.e(it, "Failed to adjust end index for link span")
|
||||
|
||||
@@ -15,6 +15,7 @@ android {
|
||||
|
||||
dependencies {
|
||||
api(projects.libraries.di)
|
||||
api(projects.libraries.core)
|
||||
api(libs.dagger)
|
||||
api(libs.appyx.core)
|
||||
api(libs.androidx.lifecycle.runtime)
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.libraries.architecture
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.Stable
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
@@ -90,7 +91,7 @@ suspend inline fun <T> MutableState<AsyncAction<T>>.runCatchingUpdatingState(
|
||||
state = this,
|
||||
errorTransform = errorTransform,
|
||||
resultBlock = {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
block()
|
||||
}
|
||||
},
|
||||
@@ -103,7 +104,7 @@ suspend inline fun <T> (suspend () -> T).runCatchingUpdatingState(
|
||||
state = state,
|
||||
errorTransform = errorTransform,
|
||||
resultBlock = {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
this()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.libraries.architecture
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.Stable
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
@@ -93,7 +94,7 @@ suspend inline fun <T> MutableState<AsyncData<T>>.runCatchingUpdatingState(
|
||||
state = this,
|
||||
errorTransform = errorTransform,
|
||||
resultBlock = {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
block()
|
||||
}
|
||||
},
|
||||
@@ -106,7 +107,7 @@ suspend inline fun <T> (suspend () -> T).runCatchingUpdatingState(
|
||||
state = state,
|
||||
errorTransform = errorTransform,
|
||||
resultBlock = {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
this()
|
||||
}
|
||||
},
|
||||
|
||||
@@ -38,15 +38,15 @@ class AsyncDataKtTest {
|
||||
|
||||
val result = runUpdatingState(state) {
|
||||
delay(1)
|
||||
Result.failure(MyThrowable("hello"))
|
||||
Result.failure(MyException("hello"))
|
||||
}
|
||||
|
||||
assertThat(result.isFailure).isTrue()
|
||||
assertThat(result.exceptionOrNull()).isEqualTo(MyThrowable("hello"))
|
||||
assertThat(result.exceptionOrNull()).isEqualTo(MyException("hello"))
|
||||
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Uninitialized)
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Loading(null))
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Failure<Int>(MyThrowable("hello")))
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Failure<Int>(MyException("hello")))
|
||||
state.assertNoMoreValues()
|
||||
}
|
||||
|
||||
@@ -54,17 +54,17 @@ class AsyncDataKtTest {
|
||||
fun `updates state when block returns failure transforming the error`() = runTest {
|
||||
val state = TestableMutableState<AsyncData<Int>>(AsyncData.Uninitialized)
|
||||
|
||||
val result = runUpdatingState(state, { MyThrowable(it.message + " world") }) {
|
||||
val result = runUpdatingState(state, { MyException(it.message + " world") }) {
|
||||
delay(1)
|
||||
Result.failure(MyThrowable("hello"))
|
||||
Result.failure(MyException("hello"))
|
||||
}
|
||||
|
||||
assertThat(result.isFailure).isTrue()
|
||||
assertThat(result.exceptionOrNull()).isEqualTo(MyThrowable("hello world"))
|
||||
assertThat(result.exceptionOrNull()).isEqualTo(MyException("hello world"))
|
||||
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Uninitialized)
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Loading(null))
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Failure<Int>(MyThrowable("hello world")))
|
||||
assertThat(state.popFirst()).isEqualTo(AsyncData.Failure<Int>(MyException("hello world")))
|
||||
state.assertNoMoreValues()
|
||||
}
|
||||
}
|
||||
@@ -101,4 +101,4 @@ private class TestableMutableState<T>(
|
||||
/**
|
||||
* An exception that is also a data class so we can compare it using equals.
|
||||
*/
|
||||
private data class MyThrowable(val myMessage: String) : Throwable(myMessage)
|
||||
private data class MyException(val myMessage: String) : Exception(myMessage)
|
||||
|
||||
@@ -7,11 +7,20 @@
|
||||
|
||||
package io.element.android.libraries.core.data
|
||||
|
||||
inline fun <A> tryOrNull(onError: ((Throwable) -> Unit) = { }, operation: () -> A): A? {
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
/**
|
||||
* Can be used to catch [Exception]s in a block of code, returning `null` if an exception occurs.
|
||||
*
|
||||
* If the block throws a [CancellationException], it will be rethrown.
|
||||
*/
|
||||
inline fun <A> tryOrNull(onException: ((Exception) -> Unit) = { }, operation: () -> A): A? {
|
||||
return try {
|
||||
operation()
|
||||
} catch (any: Throwable) {
|
||||
onError.invoke(any)
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
onException.invoke(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,61 @@
|
||||
|
||||
package io.element.android.libraries.core.extensions
|
||||
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
/**
|
||||
* Can be used to catch exceptions in a block of code and return a [Result].
|
||||
* If the block throws a [CancellationException], it will be rethrown.
|
||||
* If it throws any other exception, it will be wrapped in a [Result.failure].
|
||||
*
|
||||
* [Error]s are not caught by this function, as they are not meant to be caught in normal application flow.
|
||||
*/
|
||||
inline fun <T> runCatchingExceptions(
|
||||
block: () -> T
|
||||
): Result<T> {
|
||||
return try {
|
||||
Result.success(block())
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to catch exceptions in a block of code and return a [Result].
|
||||
* If the block throws a [CancellationException], it will be rethrown.
|
||||
* If it throws any other exception, it will be wrapped in a [Result.failure].
|
||||
*
|
||||
* [Error]s are not caught by this function, as they are not meant to be caught in normal application flow.
|
||||
*/
|
||||
inline fun <T, R> T.runCatchingExceptions(
|
||||
block: T.() -> R
|
||||
): Result<R> {
|
||||
return try {
|
||||
Result.success(block())
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to transform a [Result] into another [Result] by applying a [block] to the value if it is successful.
|
||||
* If the original [Result] is a failure, the exception will be wrapped in a new [Result.failure].
|
||||
*
|
||||
* This is a safer version of [Result.mapCatching].
|
||||
*/
|
||||
inline fun <R, T> Result<T>.mapCatchingExceptions(
|
||||
block: (T) -> R,
|
||||
): Result<R> {
|
||||
return fold(
|
||||
onSuccess = { value -> runCatchingExceptions { block(value) } },
|
||||
onFailure = { exception -> Result.failure(exception) }
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to transform some Throwable into some other.
|
||||
*/
|
||||
@@ -33,12 +88,16 @@ inline fun <R, T> Result<T>.flatMap(transform: (T) -> Result<R>): Result<R> {
|
||||
* @return The result of the transform or a caught exception wrapped in a [Result].
|
||||
*/
|
||||
inline fun <R, T> Result<T>.flatMapCatching(transform: (T) -> Result<R>): Result<R> {
|
||||
return mapCatching(transform).fold(
|
||||
return mapCatchingExceptions(transform).fold(
|
||||
onSuccess = { it },
|
||||
onFailure = { Result.failure(it) }
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to execute a block of code after the [Result] has been processed, regardless of whether it was successful or not.
|
||||
* The block receives the exception if there was one, or `null` if the result was successful.
|
||||
*/
|
||||
inline fun <T> Result<T>.finally(block: (exception: Throwable?) -> Unit): Result<T> {
|
||||
onSuccess { block(null) }
|
||||
onFailure(block)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.api.room.powerlevels
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.room.BaseRoom
|
||||
import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.room.StateEventType
|
||||
@@ -60,7 +61,7 @@ suspend fun BaseRoom.canRedactOther(): Result<Boolean> = canUserRedactOther(sess
|
||||
/**
|
||||
* Shortcut for checking if current user can handle knock requests.
|
||||
*/
|
||||
suspend fun BaseRoom.canHandleKnockRequests(): Result<Boolean> = runCatching {
|
||||
suspend fun BaseRoom.canHandleKnockRequests(): Result<Boolean> = runCatchingExceptions {
|
||||
canInvite().getOrThrow() || canBan().getOrThrow() || canKick().getOrThrow()
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.coroutine.childScope
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.core.extensions.mapFailure
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.DeviceId
|
||||
@@ -250,7 +251,7 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override fun userIdServerName(): String {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
innerClient.userIdServerName()
|
||||
}
|
||||
.onFailure {
|
||||
@@ -261,7 +262,7 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override suspend fun getUrl(url: String): Result<String> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.getUrl(url)
|
||||
}
|
||||
}
|
||||
@@ -301,19 +302,19 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override suspend fun ignoreUser(userId: UserId): Result<Unit> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.ignoreUser(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun unignoreUser(userId: UserId): Result<Unit> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.unignoreUser(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun createRoom(createRoomParams: CreateRoomParameters): Result<RoomId> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val rustParams = RustCreateRoomParameters(
|
||||
name = createRoomParams.name,
|
||||
topic = createRoomParams.topic,
|
||||
@@ -363,7 +364,7 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override suspend fun getProfile(userId: UserId): Result<MatrixUser> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.getProfile(userId.value).let(UserProfileMapper::map)
|
||||
}
|
||||
}
|
||||
@@ -373,28 +374,28 @@ class RustMatrixClient(
|
||||
|
||||
override suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults> =
|
||||
withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.searchUsers(searchTerm, limit.toULong()).let(UserSearchResultMapper::map)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setDisplayName(displayName: String): Result<Unit> =
|
||||
withContext(sessionDispatcher) {
|
||||
runCatching { innerClient.setDisplayName(displayName) }
|
||||
runCatchingExceptions { innerClient.setDisplayName(displayName) }
|
||||
}
|
||||
|
||||
override suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result<Unit> =
|
||||
withContext(sessionDispatcher) {
|
||||
runCatching { innerClient.uploadAvatar(mimeType, data) }
|
||||
runCatchingExceptions { innerClient.uploadAvatar(mimeType, data) }
|
||||
}
|
||||
|
||||
override suspend fun removeAvatar(): Result<Unit> =
|
||||
withContext(sessionDispatcher) {
|
||||
runCatching { innerClient.removeAvatar() }
|
||||
runCatchingExceptions { innerClient.removeAvatar() }
|
||||
}
|
||||
|
||||
override suspend fun joinRoom(roomId: RoomId): Result<RoomSummary?> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.joinRoomById(roomId.value).destroy()
|
||||
try {
|
||||
awaitRoom(roomId.toRoomIdOrAlias(), 10.seconds, CurrentUserMembership.JOINED)
|
||||
@@ -406,7 +407,7 @@ class RustMatrixClient(
|
||||
}.mapFailure { it.mapClientException() }
|
||||
|
||||
override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomSummary?> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.joinRoomByIdOrAlias(
|
||||
roomIdOrAlias = roomIdOrAlias.identifier,
|
||||
serverNames = serverNames,
|
||||
@@ -423,7 +424,7 @@ class RustMatrixClient(
|
||||
override suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List<String>): Result<RoomSummary?> = withContext(
|
||||
sessionDispatcher
|
||||
) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.knock(roomIdOrAlias.identifier, message, serverNames).destroy()
|
||||
try {
|
||||
awaitRoom(roomIdOrAlias, 10.seconds, CurrentUserMembership.KNOCKED)
|
||||
@@ -435,19 +436,19 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result<Unit> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.trackRecentlyVisitedRoom(roomId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getRecentlyVisitedRooms(): Result<List<RoomId>> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.getRecentlyVisitedRooms().map(::RoomId)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result<Optional<ResolvedRoomAlias>> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val result = innerClient.resolveRoomAlias(roomAlias.value)?.let {
|
||||
ResolvedRoomAlias(
|
||||
roomId = RoomId(it.roomId),
|
||||
@@ -459,7 +460,7 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<NotJoinedRoom> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
when (roomIdOrAlias) {
|
||||
is RoomIdOrAlias.Alias -> {
|
||||
val roomId = innerClient.resolveRoomAlias(roomIdOrAlias.roomAlias.value)?.roomId?.let { RoomId(it) }
|
||||
@@ -556,7 +557,7 @@ class RustMatrixClient(
|
||||
}
|
||||
|
||||
override fun canDeactivateAccount(): Boolean {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
innerClient.canDeactivateAccount()
|
||||
}
|
||||
.getOrNull()
|
||||
@@ -568,9 +569,9 @@ class RustMatrixClient(
|
||||
// Remove current delegate so we don't receive an auth error
|
||||
clientDelegateTaskHandle?.cancelAndDestroy()
|
||||
clientDelegateTaskHandle = null
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
// First call without AuthData, should fail
|
||||
val firstAttempt = runCatching {
|
||||
val firstAttempt = runCatchingExceptions {
|
||||
innerClient.deactivateAccount(
|
||||
authData = null,
|
||||
eraseData = eraseData,
|
||||
@@ -579,7 +580,7 @@ class RustMatrixClient(
|
||||
if (firstAttempt.isFailure) {
|
||||
Timber.w(firstAttempt.exceptionOrNull(), "Expected failure, try again")
|
||||
// This is expected, try again with the password
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.deactivateAccount(
|
||||
authData = AuthData.Password(
|
||||
passwordDetails = AuthDataPasswordDetails(
|
||||
@@ -606,13 +607,13 @@ class RustMatrixClient(
|
||||
|
||||
override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?> = withContext(sessionDispatcher) {
|
||||
val rustAction = action?.toRustAction()
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.accountUrl(rustAction)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result<String> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.uploadMedia(mimeType, data, progressCallback?.toProgressWatcher())
|
||||
}
|
||||
}
|
||||
@@ -654,19 +655,19 @@ class RustMatrixClient(
|
||||
}.buffer(Channel.UNLIMITED)
|
||||
|
||||
override suspend fun availableSlidingSyncVersions(): Result<List<SlidingSyncVersion>> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.availableSlidingSyncVersions().map { it.map() }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun currentSlidingSyncVersion(): Result<SlidingSyncVersion> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.session().slidingSyncVersion.map()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canReportRoom(): Boolean = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerClient.isReportRoomApiSupported()
|
||||
}.getOrDefault(false)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.auth
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.mapFailure
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
@@ -91,7 +92,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun restoreSession(sessionId: SessionId): Result<MatrixClient> = withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val sessionData = sessionStore.getSession(sessionId.value)
|
||||
if (sessionData != null) {
|
||||
if (sessionData.isTokenValid) {
|
||||
@@ -126,7 +127,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
override suspend fun setHomeserver(homeserver: String): Result<Unit> =
|
||||
withContext(coroutineDispatchers.io) {
|
||||
val emptySessionPath = rotateSessionPath()
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val client = makeClient(sessionPaths = emptySessionPath) {
|
||||
serverNameOrHomeserverUrl(homeserver)
|
||||
}
|
||||
@@ -144,7 +145,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
|
||||
override suspend fun login(username: String, password: String): Result<SessionId> =
|
||||
withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val client = currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first")
|
||||
client.login(username, password, "Element X Android", null)
|
||||
@@ -170,7 +171,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
|
||||
override suspend fun importCreatedSession(externalSession: ExternalSession): Result<SessionId> =
|
||||
withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first")
|
||||
val sessionData = externalSession.toSessionData(
|
||||
@@ -192,7 +193,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
loginHint: String?,
|
||||
): Result<OidcDetails> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val client = currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
val oAuthAuthorizationData = client.urlForOidc(
|
||||
oidcConfiguration = oidcConfigurationProvider.get(),
|
||||
@@ -211,7 +212,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
|
||||
override suspend fun cancelOidcLogin(): Result<Unit> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
pendingOAuthAuthorizationData?.use {
|
||||
currentClient?.abortOidcAuth(it)
|
||||
}
|
||||
@@ -228,7 +229,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
*/
|
||||
override suspend fun loginWithOidc(callbackUrl: String): Result<SessionId> {
|
||||
return withContext(coroutineDispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val client = currentClient ?: error("You need to call `setHomeserver()` first")
|
||||
val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first")
|
||||
client.loginWithOidcCallback(callbackUrl)
|
||||
@@ -268,7 +269,7 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||
progress(state.toStep())
|
||||
}
|
||||
}
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val client = makeQrCodeLoginClient(
|
||||
sessionPaths = emptySessionPaths,
|
||||
passphrase = pendingPassphrase,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.auth.qrlogin
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
|
||||
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginDataFactory
|
||||
@@ -17,6 +18,6 @@ import javax.inject.Inject
|
||||
@ContributesBinding(AppScope::class)
|
||||
class RustQrCodeLoginDataFactory @Inject constructor() : MatrixQrCodeLoginDataFactory {
|
||||
override fun parseQrCodeData(data: ByteArray): Result<MatrixQrCodeLoginData> {
|
||||
return runCatching { SdkQrCodeLoginData(QrCodeData.fromBytes(data)) }
|
||||
return runCatchingExceptions { SdkQrCodeLoginData(QrCodeData.fromBytes(data)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.call
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import org.matrix.rustcomponents.sdk.ElementWellKnown
|
||||
import org.matrix.rustcomponents.sdk.makeElementWellKnown
|
||||
@@ -20,7 +21,7 @@ interface ElementWellKnownParser {
|
||||
@ContributesBinding(AppScope::class)
|
||||
class RustElementWellKnownParser @Inject constructor() : ElementWellKnownParser {
|
||||
override fun parse(str: String): Result<ElementWellKnown> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
makeElementWellKnown(str)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.core
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.SendHandle
|
||||
|
||||
class RustSendHandle(
|
||||
val inner: org.matrix.rustcomponents.sdk.SendHandle,
|
||||
) : SendHandle {
|
||||
override suspend fun retry(): Result<Unit> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
inner.tryResend()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.encryption
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.flatMap
|
||||
import io.element.android.libraries.core.extensions.mapFailure
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||
@@ -96,7 +97,7 @@ internal class RustEncryptionService(
|
||||
.stateIn(sessionCoroutineScope, SharingStarted.Eagerly, false)
|
||||
|
||||
override suspend fun enableBackups(): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.enableBackups()
|
||||
}.mapFailure {
|
||||
it.mapRecoveryException()
|
||||
@@ -106,7 +107,7 @@ internal class RustEncryptionService(
|
||||
override suspend fun enableRecovery(
|
||||
waitForBackupsToUpload: Boolean,
|
||||
): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.enableRecovery(
|
||||
waitForBackupsToUpload = waitForBackupsToUpload,
|
||||
progressListener = object : EnableRecoveryProgressListener {
|
||||
@@ -124,14 +125,14 @@ internal class RustEncryptionService(
|
||||
}
|
||||
|
||||
override suspend fun doesBackupExistOnServer(): Result<Boolean> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.backupExistsOnServer()
|
||||
}
|
||||
}
|
||||
|
||||
override fun waitForBackupUploadSteadyState(): Flow<BackupUploadState> {
|
||||
return callbackFlow {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.waitForBackupUploadSteadyState(
|
||||
progressListener = object : BackupSteadyStateListener {
|
||||
override fun onUpdate(status: RustBackupUploadState) {
|
||||
@@ -155,7 +156,7 @@ internal class RustEncryptionService(
|
||||
}
|
||||
|
||||
override suspend fun disableRecovery(): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.disableRecovery()
|
||||
}.mapFailure {
|
||||
it.mapRecoveryException()
|
||||
@@ -163,7 +164,7 @@ internal class RustEncryptionService(
|
||||
}
|
||||
|
||||
private suspend fun isLastDevice(): Result<Boolean> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.isLastDevice()
|
||||
}.mapFailure {
|
||||
it.mapRecoveryException()
|
||||
@@ -171,7 +172,7 @@ internal class RustEncryptionService(
|
||||
}
|
||||
|
||||
override suspend fun resetRecoveryKey(): Result<String> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.resetRecoveryKey()
|
||||
}.mapFailure {
|
||||
it.mapRecoveryException()
|
||||
@@ -179,7 +180,7 @@ internal class RustEncryptionService(
|
||||
}
|
||||
|
||||
override suspend fun recover(recoveryKey: String): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
service.recover(recoveryKey)
|
||||
}.mapFailure {
|
||||
it.mapRecoveryException()
|
||||
@@ -187,34 +188,34 @@ internal class RustEncryptionService(
|
||||
}
|
||||
|
||||
override suspend fun deviceCurve25519(): String? {
|
||||
return runCatching { service.curve25519Key() }.getOrNull()
|
||||
return runCatchingExceptions { service.curve25519Key() }.getOrNull()
|
||||
}
|
||||
|
||||
override suspend fun deviceEd25519(): String? {
|
||||
return runCatching { service.ed25519Key() }.getOrNull()
|
||||
return runCatchingExceptions { service.ed25519Key() }.getOrNull()
|
||||
}
|
||||
|
||||
override suspend fun startIdentityReset(): Result<IdentityResetHandle?> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
service.resetIdentity()
|
||||
}.flatMap { handle ->
|
||||
RustIdentityResetHandleFactory.create(sessionId, handle)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isUserVerified(userId: UserId): Result<Boolean> = runCatching {
|
||||
override suspend fun isUserVerified(userId: UserId): Result<Boolean> = runCatchingExceptions {
|
||||
getUserIdentityInternal(userId).isVerified()
|
||||
}
|
||||
|
||||
override suspend fun pinUserIdentity(userId: UserId): Result<Unit> = runCatching {
|
||||
override suspend fun pinUserIdentity(userId: UserId): Result<Unit> = runCatchingExceptions {
|
||||
getUserIdentityInternal(userId).pin()
|
||||
}
|
||||
|
||||
override suspend fun withdrawVerification(userId: UserId): Result<Unit> = runCatching {
|
||||
override suspend fun withdrawVerification(userId: UserId): Result<Unit> = runCatchingExceptions {
|
||||
getUserIdentityInternal(userId).withdrawVerification()
|
||||
}
|
||||
|
||||
override suspend fun getUserIdentity(userId: UserId): Result<IdentityState?> = runCatching {
|
||||
override suspend fun getUserIdentity(userId: UserId): Result<IdentityState?> = runCatchingExceptions {
|
||||
val identity = getUserIdentityInternal(userId)
|
||||
val isVerified = identity.isVerified()
|
||||
when {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.encryption
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.encryption.IdentityOidcResetHandle
|
||||
import io.element.android.libraries.matrix.api.encryption.IdentityPasswordResetHandle
|
||||
@@ -20,7 +21,7 @@ object RustIdentityResetHandleFactory {
|
||||
userId: UserId,
|
||||
identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle?
|
||||
): Result<IdentityResetHandle?> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
identityResetHandle?.let {
|
||||
when (val authType = identityResetHandle.authType()) {
|
||||
is CrossSigningResetAuthType.Oidc -> RustOidcIdentityResetHandle(identityResetHandle, authType.info.approvalUrl)
|
||||
@@ -37,7 +38,7 @@ class RustPasswordIdentityResetHandle(
|
||||
private val identityResetHandle: org.matrix.rustcomponents.sdk.IdentityResetHandle,
|
||||
) : IdentityPasswordResetHandle {
|
||||
override suspend fun resetPassword(password: String): Result<Unit> {
|
||||
return runCatching { identityResetHandle.reset(AuthData.Password(AuthDataPasswordDetails(userId.value, password))) }
|
||||
return runCatchingExceptions { identityResetHandle.reset(AuthData.Password(AuthDataPasswordDetails(userId.value, password))) }
|
||||
}
|
||||
|
||||
override suspend fun cancel() {
|
||||
@@ -50,7 +51,7 @@ class RustOidcIdentityResetHandle(
|
||||
override val url: String,
|
||||
) : IdentityOidcResetHandle {
|
||||
override suspend fun resetOidc(): Result<Unit> {
|
||||
return runCatching { identityResetHandle.reset(null) }
|
||||
return runCatchingExceptions { identityResetHandle.reset(null) }
|
||||
}
|
||||
|
||||
override suspend fun cancel() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.media
|
||||
|
||||
import io.element.android.libraries.androidutils.file.safeDelete
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.media.MediaUploadHandler
|
||||
import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle
|
||||
import java.io.File
|
||||
@@ -17,7 +18,7 @@ class MediaUploadHandlerImpl(
|
||||
private val sendAttachmentJoinHandle: SendAttachmentJoinHandle,
|
||||
) : MediaUploadHandler {
|
||||
override suspend fun await(): Result<Unit> =
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
sendAttachmentJoinHandle.join()
|
||||
}
|
||||
.also { cleanUpFiles() }
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.media
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||
import io.element.android.libraries.matrix.api.media.MediaFile
|
||||
@@ -34,7 +35,7 @@ class RustMediaLoader(
|
||||
@OptIn(ExperimentalUnsignedTypes::class)
|
||||
override suspend fun loadMediaContent(source: MediaSource): Result<ByteArray> =
|
||||
withContext(mediaDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
source.toRustMediaSource().use { source ->
|
||||
innerClient.getMediaContent(source)
|
||||
}
|
||||
@@ -48,7 +49,7 @@ class RustMediaLoader(
|
||||
height: Long
|
||||
): Result<ByteArray> =
|
||||
withContext(mediaDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
source.toRustMediaSource().use { mediaSource ->
|
||||
innerClient.getMediaThumbnail(
|
||||
mediaSource = mediaSource,
|
||||
@@ -66,7 +67,7 @@ class RustMediaLoader(
|
||||
useCache: Boolean,
|
||||
): Result<MediaFile> =
|
||||
withContext(mediaDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
source.toRustMediaSource().use { mediaSource ->
|
||||
val mediaFile = innerClient.getMediaFile(
|
||||
mediaSource = mediaSource,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.notification
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
@@ -30,7 +31,7 @@ class RustNotificationService(
|
||||
override suspend fun getNotifications(
|
||||
ids: Map<RoomId, List<EventId>>
|
||||
): Result<Map<EventId, NotificationData>> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val requests = ids.map { (roomId, eventIds) ->
|
||||
NotificationItemsRequest(
|
||||
roomId = roomId.value,
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.notificationsettings
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.coroutine.suspendLazy
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||
@@ -48,12 +49,12 @@ class RustNotificationSettingsService(
|
||||
}
|
||||
|
||||
override suspend fun getRoomNotificationSettings(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean): Result<RoomNotificationSettings> =
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().getRoomNotificationSettings(roomId.value, isEncrypted, isOneToOne).let(RoomNotificationSettingsMapper::map)
|
||||
}
|
||||
|
||||
override suspend fun getDefaultRoomNotificationMode(isEncrypted: Boolean, isOneToOne: Boolean): Result<RoomNotificationMode> =
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().getDefaultRoomNotificationMode(isEncrypted, isOneToOne).let(RoomNotificationSettingsMapper::mapMode)
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ class RustNotificationSettingsService(
|
||||
mode: RoomNotificationMode,
|
||||
isOneToOne: Boolean
|
||||
): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
try {
|
||||
notificationSettings.await().setDefaultRoomNotificationMode(isEncrypted, isOneToOne, mode.let(RoomNotificationSettingsMapper::mapMode))
|
||||
} catch (exception: NotificationSettingsException.RuleNotFound) {
|
||||
@@ -74,13 +75,13 @@ class RustNotificationSettingsService(
|
||||
}
|
||||
|
||||
override suspend fun setRoomNotificationMode(roomId: RoomId, mode: RoomNotificationMode): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().setRoomNotificationMode(roomId.value, mode.let(RoomNotificationSettingsMapper::mapMode))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun restoreDefaultRoomNotificationMode(roomId: RoomId): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().restoreDefaultRoomNotificationMode(roomId.value)
|
||||
}
|
||||
}
|
||||
@@ -88,54 +89,54 @@ class RustNotificationSettingsService(
|
||||
override suspend fun muteRoom(roomId: RoomId): Result<Unit> = setRoomNotificationMode(roomId, RoomNotificationMode.MUTE)
|
||||
|
||||
override suspend fun unmuteRoom(roomId: RoomId, isEncrypted: Boolean, isOneToOne: Boolean) = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().unmuteRoom(roomId.value, isEncrypted, isOneToOne)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isRoomMentionEnabled(): Result<Boolean> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().isRoomMentionEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setRoomMentionEnabled(enabled: Boolean): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().setRoomMentionEnabled(enabled)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isCallEnabled(): Result<Boolean> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().isCallEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setCallEnabled(enabled: Boolean): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().setCallEnabled(enabled)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isInviteForMeEnabled(): Result<Boolean> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().isInviteForMeEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setInviteForMeEnabled(enabled: Boolean): Result<Unit> = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().setInviteForMeEnabled(enabled)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getRoomsWithUserDefinedRules(): Result<List<String>> =
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().getRoomsWithUserDefinedRules(enabled = true)
|
||||
}
|
||||
|
||||
override suspend fun canHomeServerPushEncryptedEventsToDevice(): Result<Boolean> =
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
notificationSettings.await().canPushEncryptedEventToDevice()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.permalink
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.core.MatrixPatterns
|
||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||
@@ -24,7 +25,7 @@ class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder {
|
||||
if (!MatrixPatterns.isUserId(userId.value)) {
|
||||
return Result.failure(PermalinkBuilderError.InvalidData)
|
||||
}
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
matrixToUserPermalink(userId.value)
|
||||
}
|
||||
}
|
||||
@@ -33,7 +34,7 @@ class DefaultPermalinkBuilder @Inject constructor() : PermalinkBuilder {
|
||||
if (!MatrixPatterns.isRoomAlias(roomAlias.value)) {
|
||||
return Result.failure(PermalinkBuilderError.InvalidData)
|
||||
}
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
matrixToRoomAliasPermalink(roomAlias.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.permalink
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||
@@ -44,7 +45,7 @@ class DefaultPermalinkParser @Inject constructor(
|
||||
// so convert URI to matrix.to to simplify parsing process
|
||||
val matrixToUri = matrixToConverter.convert(uri) ?: return PermalinkData.FallbackLink(uri)
|
||||
|
||||
val result = runCatching {
|
||||
val result = runCatchingExceptions {
|
||||
parseMatrixEntityFrom(matrixToUri.toString())
|
||||
}.getOrNull()
|
||||
return if (result == null) {
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.pushers
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.extensions.mapFailure
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.pusher.PushersService
|
||||
import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData
|
||||
import io.element.android.libraries.matrix.api.pusher.UnsetHttpPusherData
|
||||
@@ -26,7 +27,7 @@ class RustPushersService(
|
||||
) : PushersService {
|
||||
override suspend fun setHttpPusher(setHttpPusherData: SetHttpPusherData): Result<Unit> {
|
||||
return withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
client.setPusher(
|
||||
identifiers = PusherIdentifiers(
|
||||
pushkey = setHttpPusherData.pushKey,
|
||||
@@ -51,7 +52,7 @@ class RustPushersService(
|
||||
|
||||
override suspend fun unsetHttpPusher(unsetHttpPusherData: UnsetHttpPusherData): Result<Unit> {
|
||||
return withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
client.deletePusher(
|
||||
identifiers = PusherIdentifiers(
|
||||
pushkey = unsetHttpPusherData.pushKey,
|
||||
|
||||
@@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.room
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.coroutine.childScope
|
||||
import io.element.android.libraries.core.extensions.mapFailure
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.matrix.api.core.DeviceId
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
@@ -204,7 +205,7 @@ class JoinedRustRoom(
|
||||
// Track read receipts only for focused timeline for performance optimization
|
||||
val trackReadReceipts = createTimelineParams is CreateTimelineParams.Focused
|
||||
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.timelineWithConfiguration(
|
||||
configuration = TimelineConfiguration(
|
||||
focus = focus,
|
||||
@@ -243,7 +244,7 @@ class JoinedRustRoom(
|
||||
htmlBody: String?,
|
||||
intentionalMentions: List<IntentionalMention>
|
||||
): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
MessageEventContent.from(body, htmlBody, intentionalMentions).use { newContent ->
|
||||
innerRoom.edit(eventId.value, newContent)
|
||||
}
|
||||
@@ -251,43 +252,43 @@ class JoinedRustRoom(
|
||||
}
|
||||
|
||||
override suspend fun typingNotice(isTyping: Boolean) = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.typingNotice(isTyping)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun inviteUserById(id: UserId): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.inviteUserById(id.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateAvatar(mimeType: String, data: ByteArray): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.uploadAvatar(mimeType, data, null)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeAvatar(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.removeAvatar()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setName(name: String): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.setName(name)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setTopic(topic: String): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.setTopic(topic)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reportContent(eventId: EventId, reason: String, blockUserId: UserId?): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.reportContent(eventId = eventId.value, score = null, reason = reason)
|
||||
if (blockUserId != null) {
|
||||
innerRoom.ignoreUser(blockUserId.value)
|
||||
@@ -299,7 +300,7 @@ class JoinedRustRoom(
|
||||
val currentState = roomNotificationSettingsStateFlow.value
|
||||
val currentRoomNotificationSettings = currentState.roomNotificationSettings()
|
||||
roomNotificationSettingsStateFlow.value = RoomNotificationSettingsState.Pending(prevRoomNotificationSettings = currentRoomNotificationSettings)
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val isEncrypted = roomInfoFlow.value.isEncrypted ?: getUpdatedIsEncrypted().getOrThrow()
|
||||
notificationSettingsService.getRoomNotificationSettings(roomId, isEncrypted, isOneToOne).getOrThrow()
|
||||
}.map {
|
||||
@@ -313,56 +314,56 @@ class JoinedRustRoom(
|
||||
}
|
||||
|
||||
override suspend fun updateCanonicalAlias(canonicalAlias: RoomAlias?, alternativeAliases: List<RoomAlias>): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.updateCanonicalAlias(canonicalAlias?.value, alternativeAliases.map { it.value })
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun publishRoomAliasInRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.publishRoomAliasInRoomDirectory(roomAlias.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun removeRoomAliasFromRoomDirectory(roomAlias: RoomAlias): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.removeRoomAliasFromRoomDirectory(roomAlias.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateRoomVisibility(roomVisibility: RoomVisibility): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.updateRoomVisibility(roomVisibility.map())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateHistoryVisibility(historyVisibility: RoomHistoryVisibility): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.updateHistoryVisibility(historyVisibility.map())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun enableEncryption(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.enableEncryption()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateJoinRule(joinRule: JoinRule): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.updateJoinRules(joinRule.map())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updateUsersRoles(changes: List<UserRoleChange>): Result<Unit> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
val powerLevelChanges = changes.map { UserPowerLevelUpdate(it.userId.value, it.powerLevel) }
|
||||
innerRoom.updatePowerLevelsForUsers(powerLevelChanges)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun updatePowerLevels(roomPowerLevels: RoomPowerLevels): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val changes = RoomPowerLevelChanges(
|
||||
ban = roomPowerLevels.ban,
|
||||
invite = roomPowerLevels.invite,
|
||||
@@ -378,25 +379,25 @@ class JoinedRustRoom(
|
||||
}
|
||||
|
||||
override suspend fun resetPowerLevels(): Result<RoomPowerLevels> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
RoomPowerLevelsMapper.map(innerRoom.resetPowerLevels())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun kickUser(userId: UserId, reason: String?): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.kickUser(userId.value, reason)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun banUser(userId: UserId, reason: String?): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.banUser(userId.value, reason)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun unbanUser(userId: UserId, reason: String?): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.unbanUser(userId.value, reason)
|
||||
}
|
||||
}
|
||||
@@ -407,13 +408,13 @@ class JoinedRustRoom(
|
||||
languageTag: String?,
|
||||
theme: String?,
|
||||
) = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
widgetSettings.generateWidgetWebViewUrl(innerRoom, clientId, languageTag, theme)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
RustWidgetDriver(
|
||||
widgetSettings = widgetSettings,
|
||||
room = innerRoom,
|
||||
@@ -427,7 +428,7 @@ class JoinedRustRoom(
|
||||
}
|
||||
|
||||
override suspend fun sendCallNotificationIfNeeded(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.sendCallNotificationIfNeeded()
|
||||
}
|
||||
}
|
||||
@@ -435,14 +436,14 @@ class JoinedRustRoom(
|
||||
override suspend fun setSendQueueEnabled(enabled: Boolean) {
|
||||
withContext(roomDispatcher) {
|
||||
Timber.d("setSendQueuesEnabled: $enabled")
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.enableSendQueue(enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun ignoreDeviceTrustAndResend(devices: Map<UserId, List<DeviceId>>, sendHandle: SendHandle) = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.ignoreDeviceTrustAndResend(
|
||||
devices = devices.entries.associate { entry ->
|
||||
entry.key.value to entry.value.map { it.value }
|
||||
@@ -453,7 +454,7 @@ class JoinedRustRoom(
|
||||
}
|
||||
|
||||
override suspend fun withdrawVerificationAndResend(userIds: List<UserId>, sendHandle: SendHandle) = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.withdrawVerificationAndResend(
|
||||
userIds = userIds.map { it.value },
|
||||
sendHandle = (sendHandle as RustSendHandle).inner,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.room
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.room.NotJoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
|
||||
@@ -20,8 +21,8 @@ class NotJoinedRustRoom(
|
||||
override val localRoom: RustBaseRoom?,
|
||||
override val previewInfo: RoomPreviewInfo,
|
||||
) : NotJoinedRoom {
|
||||
override suspend fun membershipDetails(): Result<RoomMembershipDetails?> = runCatching {
|
||||
val room = localRoom?.innerRoom ?: return@runCatching null
|
||||
override suspend fun membershipDetails(): Result<RoomMembershipDetails?> = runCatchingExceptions {
|
||||
val room = localRoom?.innerRoom ?: return@runCatchingExceptions null
|
||||
val (ownMember, senderInfo) = room.memberWithSenderInfo(sessionId.value)
|
||||
RoomMembershipDetails(
|
||||
currentUserMember = RoomMemberMapper.map(ownMember),
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.room
|
||||
|
||||
import io.element.android.libraries.core.coroutine.parallelMap
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.room.ForwardEventException
|
||||
@@ -52,7 +53,7 @@ class RoomContentForwarder(
|
||||
val failedForwardingTo = mutableSetOf<RoomId>()
|
||||
targetRooms.parallelMap { room ->
|
||||
room.use { targetRoom ->
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
// Sending a message requires a registered timeline listener
|
||||
targetRoom.timeline().runWithTimelineListenerRegistered {
|
||||
withTimeout(timeoutMs.milliseconds) {
|
||||
|
||||
@@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.room
|
||||
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.coroutine.childScope
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.DeviceId
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
@@ -90,7 +91,7 @@ class RustBaseRoom(
|
||||
}
|
||||
|
||||
override suspend fun getMembers(limit: Int) = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.members().use {
|
||||
it.nextChunk(limit.toUInt()).orEmpty().map { roomMember ->
|
||||
RoomMemberMapper.map(roomMember)
|
||||
@@ -100,7 +101,7 @@ class RustBaseRoom(
|
||||
}
|
||||
|
||||
override suspend fun getUpdatedMember(userId: UserId): Result<RoomMember> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
RoomMemberMapper.map(innerRoom.member(userId.value))
|
||||
}
|
||||
}
|
||||
@@ -113,32 +114,32 @@ class RustBaseRoom(
|
||||
}
|
||||
|
||||
override suspend fun userDisplayName(userId: UserId): Result<String?> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.memberDisplayName(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun userRole(userId: UserId): Result<RoomMember.Role> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
RoomMemberMapper.mapRole(innerRoom.suggestedRoleForUser(userId.value))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun powerLevels(): Result<RoomPowerLevels> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
RoomPowerLevelsMapper.map(innerRoom.getPowerLevels())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun userAvatarUrl(userId: UserId): Result<String?> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.memberAvatarUrl(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun leave(): Result<Unit> = withContext(roomDispatcher) {
|
||||
val membershipBeforeLeft = roomInfoFlow.value.currentUserMembership
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.leave()
|
||||
}.onSuccess {
|
||||
roomMembershipObserver.notifyUserLeftRoom(roomId, membershipBeforeLeft)
|
||||
@@ -146,142 +147,142 @@ class RustBaseRoom(
|
||||
}
|
||||
|
||||
override suspend fun join(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.join()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun forget(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.forget()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserInvite(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserInvite(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserKick(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserKick(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserBan(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserBan(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserRedactOwn(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserRedactOwn(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserRedactOther(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserRedactOther(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserSendState(userId: UserId, type: StateEventType): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserSendState(userId.value, type.map())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserSendMessage(userId: UserId, type: MessageEventType): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserSendMessage(userId.value, type.map())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserTriggerRoomNotification(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserTriggerRoomNotification(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun canUserPinUnpin(userId: UserId): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.canUserPinUnpin(userId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun clearEventCacheStorage(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.clearEventCacheStorage()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setIsFavorite(isFavorite: Boolean): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.setIsFavourite(isFavorite, null)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun markAsRead(receiptType: ReceiptType): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.markAsRead(receiptType.toRustReceiptType())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setUnreadFlag(isUnread: Boolean): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.setUnreadFlag(isUnread)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPermalink(): Result<String> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.matrixToPermalink()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPermalinkFor(eventId: EventId): Result<String> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.matrixToEventPermalink(eventId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getRoomVisibility(): Result<RoomVisibility> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.getRoomVisibility().map()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getUpdatedIsEncrypted(): Result<Boolean> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
innerRoom.latestEncryptionState() == EncryptionState.ENCRYPTED
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun saveComposerDraft(composerDraft: ComposerDraft): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
Timber.d("saveComposerDraft: $composerDraft into $roomId")
|
||||
innerRoom.saveComposerDraft(composerDraft.into())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadComposerDraft(): Result<ComposerDraft?> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
Timber.d("loadComposerDraft for $roomId")
|
||||
innerRoom.loadComposerDraft()?.into()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun clearComposerDraft(): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
Timber.d("clearComposerDraft for $roomId")
|
||||
innerRoom.clearComposerDraft()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reportRoom(reason: String?): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
Timber.d("reportRoom $roomId")
|
||||
innerRoom.reportRoom(reason)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.room.knock
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.knock.KnockRequest
|
||||
@@ -23,19 +24,19 @@ class RustKnockRequest(
|
||||
override val timestamp: Long? = inner.timestamp?.toLong()
|
||||
override val isSeen: Boolean = inner.isSeen
|
||||
|
||||
override suspend fun accept(): Result<Unit> = runCatching {
|
||||
override suspend fun accept(): Result<Unit> = runCatchingExceptions {
|
||||
inner.actions.accept()
|
||||
}
|
||||
|
||||
override suspend fun decline(reason: String?): Result<Unit> = runCatching {
|
||||
override suspend fun decline(reason: String?): Result<Unit> = runCatchingExceptions {
|
||||
inner.actions.decline(reason)
|
||||
}
|
||||
|
||||
override suspend fun declineAndBan(reason: String?): Result<Unit> = runCatching {
|
||||
override suspend fun declineAndBan(reason: String?): Result<Unit> = runCatchingExceptions {
|
||||
inner.actions.declineAndBan(reason)
|
||||
}
|
||||
|
||||
override suspend fun markAsSeen(): Result<Unit> = runCatching {
|
||||
override suspend fun markAsSeen(): Result<Unit> = runCatchingExceptions {
|
||||
inner.actions.markAsSeen()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ internal fun RoomListServiceInterface.syncIndicator(): Flow<RoomListServiceSyncI
|
||||
|
||||
internal fun RoomListServiceInterface.roomOrNull(roomId: String): Room? {
|
||||
return tryOrNull(
|
||||
onError = { Timber.e(it, "Failed finding room with id=$roomId.") }
|
||||
onException = { Timber.e(it, "Failed finding room with id=$roomId.") }
|
||||
) {
|
||||
room(roomId)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
package io.element.android.libraries.matrix.impl.sync
|
||||
|
||||
import io.element.android.libraries.core.coroutine.mapState
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.matrix.api.sync.SyncService
|
||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
@@ -33,10 +34,10 @@ class RustSyncService(
|
||||
private val isServiceReady = AtomicBoolean(true)
|
||||
|
||||
override suspend fun startSync() = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
if (!isServiceReady.get()) {
|
||||
Timber.d("Can't start sync: service is not ready")
|
||||
return@runCatching
|
||||
return@runCatchingExceptions
|
||||
}
|
||||
Timber.i("Start sync")
|
||||
inner.start()
|
||||
@@ -46,10 +47,10 @@ class RustSyncService(
|
||||
}
|
||||
|
||||
override suspend fun stopSync() = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
if (!isServiceReady.get()) {
|
||||
Timber.d("Can't stop sync: service is not ready")
|
||||
return@runCatching
|
||||
return@runCatchingExceptions
|
||||
}
|
||||
Timber.i("Stop sync")
|
||||
inner.stop()
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
package io.element.android.libraries.matrix.impl.timeline
|
||||
|
||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
@@ -165,7 +166,7 @@ class RustTimeline(
|
||||
override val membershipChangeEventReceived: Flow<Unit> = timelineDiffProcessor.membershipChangeEventReceived
|
||||
|
||||
override suspend fun sendReadReceipt(eventId: EventId, receiptType: ReceiptType): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.sendReadReceipt(receiptType.toRustReceiptType(), eventId.value)
|
||||
}
|
||||
}
|
||||
@@ -181,7 +182,7 @@ class RustTimeline(
|
||||
override suspend fun paginate(direction: Timeline.PaginationDirection): Result<Boolean> = withContext(NonCancellable) {
|
||||
withContext(dispatcher) {
|
||||
initLatch.await()
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
if (!canPaginate(direction)) throw TimelineException.CannotPaginate
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = true) }
|
||||
when (direction) {
|
||||
@@ -275,14 +276,14 @@ class RustTimeline(
|
||||
intentionalMentions: List<IntentionalMention>,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
MessageEventContent.from(body, htmlBody, intentionalMentions).use { content ->
|
||||
runCatching<Unit> {
|
||||
runCatchingExceptions<Unit> {
|
||||
inner.send(content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun redactEvent(eventOrTransactionId: EventOrTransactionId, reason: String?): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.redactEvent(
|
||||
eventOrTransactionId = eventOrTransactionId.toRustEventOrTransactionId(),
|
||||
reason = reason,
|
||||
@@ -296,7 +297,7 @@ class RustTimeline(
|
||||
htmlBody: String?,
|
||||
intentionalMentions: List<IntentionalMention>,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val editedContent = EditedContent.RoomMessage(
|
||||
content = MessageEventContent.from(
|
||||
body = body,
|
||||
@@ -316,7 +317,7 @@ class RustTimeline(
|
||||
caption: String?,
|
||||
formattedCaption: String?,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching<Unit> {
|
||||
runCatchingExceptions<Unit> {
|
||||
val editedContent = EditedContent.MediaCaption(
|
||||
caption = caption,
|
||||
formattedCaption = formattedCaption?.let {
|
||||
@@ -340,7 +341,7 @@ class RustTimeline(
|
||||
intentionalMentions: List<IntentionalMention>,
|
||||
fromNotification: Boolean,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val msg = MessageEventContent.from(body, htmlBody, intentionalMentions)
|
||||
inner.sendReply(
|
||||
msg = msg,
|
||||
@@ -462,7 +463,7 @@ class RustTimeline(
|
||||
}
|
||||
|
||||
override suspend fun toggleReaction(emoji: String, eventOrTransactionId: EventOrTransactionId): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.toggleReaction(
|
||||
key = emoji,
|
||||
itemId = eventOrTransactionId.toRustEventOrTransactionId(),
|
||||
@@ -471,7 +472,7 @@ class RustTimeline(
|
||||
}
|
||||
|
||||
override suspend fun forwardEvent(eventId: EventId, roomIds: List<RoomId>): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
roomContentForwarder.forward(fromTimeline = inner, eventId = eventId, toRoomIds = roomIds)
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
@@ -485,7 +486,7 @@ class RustTimeline(
|
||||
zoomLevel: Int?,
|
||||
assetType: AssetType?,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.sendLocation(
|
||||
body = body,
|
||||
geoUri = geoUri,
|
||||
@@ -528,7 +529,7 @@ class RustTimeline(
|
||||
maxSelections: Int,
|
||||
pollKind: PollKind,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.createPoll(
|
||||
question = question,
|
||||
answers = answers,
|
||||
@@ -545,7 +546,7 @@ class RustTimeline(
|
||||
maxSelections: Int,
|
||||
pollKind: PollKind,
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
val editedContent = EditedContent.PollStart(
|
||||
pollData = PollData(
|
||||
question = question,
|
||||
@@ -565,7 +566,7 @@ class RustTimeline(
|
||||
pollStartId: EventId,
|
||||
answers: List<String>
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.sendPollResponse(
|
||||
pollStartEventId = pollStartId.value,
|
||||
answers = answers,
|
||||
@@ -577,7 +578,7 @@ class RustTimeline(
|
||||
pollStartId: EventId,
|
||||
text: String
|
||||
): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.endPoll(
|
||||
pollStartEventId = pollStartId.value,
|
||||
text = text,
|
||||
@@ -586,7 +587,7 @@ class RustTimeline(
|
||||
}
|
||||
|
||||
private fun sendAttachment(files: List<File>, handle: () -> SendAttachmentJoinHandle): Result<MediaUploadHandler> {
|
||||
return runCatching {
|
||||
return runCatchingExceptions {
|
||||
MediaUploadHandlerImpl(files, handle())
|
||||
}
|
||||
}
|
||||
@@ -609,19 +610,19 @@ class RustTimeline(
|
||||
}
|
||||
|
||||
override suspend fun pinEvent(eventId: EventId): Result<Boolean> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.pinEvent(eventId = eventId.value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun unpinEvent(eventId: EventId): Result<Boolean> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.unpinEvent(eventId = eventId.value)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchDetailsForEvent(eventId: EventId): Result<Unit> = withContext(dispatcher) {
|
||||
runCatching {
|
||||
runCatchingExceptions {
|
||||
inner.fetchDetailsForEvent(eventId.value)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user