Merge branch 'develop' into feature/bma/scroll-to-unread-messages

This commit is contained in:
Benoit Marty
2026-06-16 14:28:44 +02:00
committed by GitHub
382 changed files with 2538 additions and 1947 deletions
@@ -9,6 +9,7 @@
package io.element.android.libraries.matrix.impl.exception
import io.element.android.libraries.matrix.api.exception.ClientException
import io.element.android.libraries.matrix.api.exception.ContentScannerErrorReason
import org.matrix.rustcomponents.sdk.ClientException as RustClientException
fun Throwable.mapClientException(): ClientException {
@@ -23,6 +24,10 @@ fun Throwable.mapClientException(): ClientException {
details = details,
cause = this,
)
is RustClientException.ContentScanner -> ClientException.ContentScanner(
message = message,
reason = ContentScannerErrorReason.fromRust(reason),
)
}
}
else -> ClientException.Other(message ?: "Unknown error", this)
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.exception
import io.element.android.libraries.matrix.api.exception.ContentScannerErrorReason
import uniffi.matrix_sdk_contentscanner.ErrorReason
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_BAD_DECRYPTION
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MALFORMED_JSON
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MEDIA_FAILED_TO_DECRYPT
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MEDIA_NOT_CLEAN
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MEDIA_REQUEST_FAILED
import uniffi.matrix_sdk_contentscanner.ErrorReason.MCS_MIME_TYPE_FORBIDDEN
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_MISSING_TOKEN
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_NOT_FOUND
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_UNKNOWN
import uniffi.matrix_sdk_contentscanner.ErrorReason.M_UNKNOWN_TOKEN
fun ContentScannerErrorReason.Companion.fromRust(reason: ErrorReason) = when (reason) {
M_UNKNOWN -> ContentScannerErrorReason.M_UNKNOWN
M_MISSING_TOKEN -> ContentScannerErrorReason.M_MISSING_TOKEN
M_UNKNOWN_TOKEN -> ContentScannerErrorReason.M_UNKNOWN_TOKEN
MCS_MALFORMED_JSON -> ContentScannerErrorReason.MCS_MALFORMED_JSON
MCS_MEDIA_FAILED_TO_DECRYPT -> ContentScannerErrorReason.MCS_MEDIA_FAILED_TO_DECRYPT
M_NOT_FOUND -> ContentScannerErrorReason.M_NOT_FOUND
MCS_MEDIA_NOT_CLEAN -> ContentScannerErrorReason.MCS_MEDIA_NOT_CLEAN
MCS_MIME_TYPE_FORBIDDEN -> ContentScannerErrorReason.MCS_MIME_TYPE_FORBIDDEN
MCS_BAD_DECRYPTION -> ContentScannerErrorReason.MCS_BAD_DECRYPTION
MCS_MEDIA_REQUEST_FAILED -> ContentScannerErrorReason.MCS_MEDIA_REQUEST_FAILED
}
@@ -51,6 +51,10 @@ class RustLinkMobileHandler(
)
// We emit Done in case the progress listener was deallocated before generate() sent the Done
_linkMobileStep.emit(LinkMobileStep.Done)
} catch (e: HumanQrGrantLoginException.Expired) {
// Note: the SDK does not return this error, but is returning `.NotFound` instead when the QR code expires. We catch both just in case.
Timber.tag(tag.value).w(e, "QR code has expired")
_linkMobileStep.emit(LinkMobileStep.QrRotating)
} catch (e: HumanQrGrantLoginException.NotFound) {
Timber.tag(tag.value).w(e, "Error during QR login grant")
// Catch timeout here?
@@ -147,6 +147,32 @@ class RustLinkMobileHandlerTest {
}
}
@Test
fun `when start throws HumanQrGrantLoginException_Expired, the handler emits QrRotating step`() = runTest {
val completable = CompletableDeferred<Unit>()
val handler = FakeFfiGrantLoginWithQrCodeHandler(
generateResult = {
completable.await()
throw HumanQrGrantLoginException.Expired("Expired")
}
)
val sut = createRustLinkMobileHandler(
handler,
)
sut.linkMobileStep.test {
val initialItem = awaitItem()
assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized)
backgroundScope.launch {
sut.start()
}
runCurrent()
// generate returns, error is emitted
completable.complete(Unit)
val qrRotatingState = awaitItem()
assertThat(qrRotatingState).isEqualTo(LinkMobileStep.QrRotating)
}
}
private fun TestScope.createRustLinkMobileHandler(
handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(),
) = RustLinkMobileHandler(