Merge branch 'develop' into feature/fga/user_status_last_pieces

This commit is contained in:
ganfra
2026-08-11 10:04:18 +02:00
56 changed files with 715 additions and 115 deletions
@@ -0,0 +1,36 @@
/*
* 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.linknewdevice
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.matrix.api.linknewdevice.ContinuationMessageSender
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import timber.log.Timber
import org.matrix.rustcomponents.sdk.ContinuationMessageSender as FfiContinuationMessageSender
class RustContinuationMessageSender(
private val inner: FfiContinuationMessageSender,
private val sessionDispatcher: CoroutineDispatcher,
) : ContinuationMessageSender {
override suspend fun cancel(): Result<Unit> = withContext(sessionDispatcher) {
runCatchingExceptions {
inner.cancel()
}.onFailure {
Timber.e(it, "Error cancelling continuation message")
}
}
override suspend fun confirm(): Result<Unit> = withContext(sessionDispatcher) {
runCatchingExceptions {
inner.confirm()
}.onFailure {
Timber.e(it, "Error confirming continuation message")
}
}
}
@@ -75,6 +75,10 @@ class RustLinkDesktopHandler(
GrantQrLoginProgress.SyncingSecrets -> LinkDesktopStep.SyncingSecrets
is GrantQrLoginProgress.WaitingForAuth -> LinkDesktopStep.WaitingForAuth(
verificationUri = verificationUri,
continuationMessageSender = RustContinuationMessageSender(
inner = continuationSender,
sessionDispatcher = sessionDispatcher,
)
)
is GrantQrLoginProgress.EstablishingSecureChannel -> LinkDesktopStep.EstablishingSecureChannel(
checkCode = checkCode,
@@ -84,7 +84,13 @@ class RustLinkMobileHandler(
)
GrantGeneratedQrLoginProgress.Starting -> LinkMobileStep.Starting
GrantGeneratedQrLoginProgress.SyncingSecrets -> LinkMobileStep.SyncingSecrets
is GrantGeneratedQrLoginProgress.WaitingForAuth -> LinkMobileStep.WaitingForAuth(verificationUri)
is GrantGeneratedQrLoginProgress.WaitingForAuth -> LinkMobileStep.WaitingForAuth(
verificationUri = verificationUri,
continuationMessageSender = RustContinuationMessageSender(
inner = continuationSender,
sessionDispatcher = sessionDispatcher,
)
)
}
}
}
@@ -0,0 +1,25 @@
/*
* 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.linknewdevice
import io.element.android.libraries.matrix.api.linknewdevice.ContinuationMessageSender
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask
class FakeContinuationMessageSender(
private val cancelResult: () -> Result<Unit> = { lambdaError() },
private val confirmResult: () -> Result<Unit> = { lambdaError() },
) : ContinuationMessageSender {
override suspend fun cancel(): Result<Unit> = simulateLongTask {
cancelResult()
}
override suspend fun confirm(): Result<Unit> = simulateLongTask {
confirmResult()
}
}
@@ -16,6 +16,8 @@ import io.element.android.libraries.matrix.api.linknewdevice.LinkDesktopStep
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiContinuationMessageSender
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler
import io.element.android.libraries.matrix.test.QR_CODE_DATA
import io.element.android.tests.testutils.ExpectedResult
import io.element.android.tests.testutils.match
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
@@ -50,16 +52,18 @@ class RustLinkDesktopHandlerTest {
runCurrent()
// progress from the handler is mapped and emitted
listOf(
GrantQrLoginProgress.Starting to LinkDesktopStep.Starting,
GrantQrLoginProgress.SyncingSecrets to LinkDesktopStep.SyncingSecrets,
GrantQrLoginProgress.Starting to ExpectedResult(LinkDesktopStep.Starting),
GrantQrLoginProgress.SyncingSecrets to ExpectedResult(LinkDesktopStep.SyncingSecrets),
GrantQrLoginProgress.WaitingForAuth("aVerificationUri", FakeFfiContinuationMessageSender())
to LinkDesktopStep.WaitingForAuth("aVerificationUri"),
to ExpectedResult(
resultClass = LinkDesktopStep.WaitingForAuth::class.java,
),
GrantQrLoginProgress.EstablishingSecureChannel(1.toUByte(), "1")
to LinkDesktopStep.EstablishingSecureChannel(1.toUByte(), "1"),
GrantQrLoginProgress.Done to LinkDesktopStep.Done,
).forEach { (progress, expectedStep) ->
to ExpectedResult(LinkDesktopStep.EstablishingSecureChannel(1.toUByte(), "1")),
GrantQrLoginProgress.Done to ExpectedResult(LinkDesktopStep.Done),
).forEach { (progress, expectedResult) ->
handler.emitScanProgress(progress)
assertThat(awaitItem()).isEqualTo(expectedStep)
assertThat(awaitItem()).match(expectedResult)
}
// scan returns, no new event is emitted
completable.complete(Unit)
@@ -18,6 +18,8 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiContinuati
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiGrantLoginWithQrCodeHandler
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData
import io.element.android.libraries.matrix.test.QR_CODE_DATA_RECIPROCATE
import io.element.android.tests.testutils.ExpectedResult
import io.element.android.tests.testutils.match
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
@@ -51,18 +53,18 @@ class RustLinkMobileHandlerTest {
runCurrent()
// progress from the handler is mapped and emitted
listOf(
GrantGeneratedQrLoginProgress.Starting to LinkMobileStep.Starting::class.java,
GrantGeneratedQrLoginProgress.SyncingSecrets to LinkMobileStep.SyncingSecrets::class.java,
GrantGeneratedQrLoginProgress.Starting to ExpectedResult(LinkMobileStep.Starting),
GrantGeneratedQrLoginProgress.SyncingSecrets to ExpectedResult(LinkMobileStep.SyncingSecrets),
GrantGeneratedQrLoginProgress.WaitingForAuth("aVerificationUri", FakeFfiContinuationMessageSender())
to LinkMobileStep.WaitingForAuth::class.java,
to ExpectedResult(LinkMobileStep.WaitingForAuth::class.java),
GrantGeneratedQrLoginProgress.QrScanned(FakeFfiCheckCodeSender())
to LinkMobileStep.QrScanned::class.java,
to ExpectedResult(LinkMobileStep.QrScanned::class.java),
GrantGeneratedQrLoginProgress.QrReady(FakeFfiQrCodeData(toBytesResult = { QR_CODE_DATA_RECIPROCATE }))
to LinkMobileStep.QrReady::class.java,
GrantGeneratedQrLoginProgress.Done to LinkMobileStep.Done::class.java,
).forEach { (progress, expectedStepClass) ->
to ExpectedResult(LinkMobileStep.QrReady::class.java),
GrantGeneratedQrLoginProgress.Done to ExpectedResult(LinkMobileStep.Done),
).forEach { (progress, expectedResult) ->
handler.emitGenerateProgress(progress)
assertThat(awaitItem()).isInstanceOf(expectedStepClass)
assertThat(awaitItem()).match(expectedResult)
}
// generate returns, no new event is emitted
completable.complete(Unit)