Merge pull request #6817 from element-hq/feature/bma/automaticRetry

[Link new device] Rotate QrCode instead of showing an error
This commit is contained in:
Benoit Marty 2026-05-21 10:29:29 +02:00 committed by GitHub
commit 535af93d85
15 changed files with 346 additions and 13 deletions

View file

@ -18,6 +18,7 @@ sealed interface LinkMobileStep {
data object Uninitialized : LinkMobileStep
data object Starting : LinkMobileStep
data class QrReady(val data: String) : LinkMobileStep
data object QrRotating : LinkMobileStep
data class WaitingForAuth(val verificationUri: String) : LinkMobileStep
data class QrScanned(val checkCodeSender: CheckCodeSender) : LinkMobileStep
data class Error(val errorType: ErrorType) : LinkMobileStep

View file

@ -51,6 +51,15 @@ class RustLinkMobileHandler(
)
// We emit Done in case the progress listener was deallocated before generate() sent the Done
_linkMobileStep.emit(LinkMobileStep.Done)
} catch (e: HumanQrGrantLoginException.NotFound) {
Timber.tag(tag.value).w(e, "Error during QR login grant")
// Catch timeout here?
if (_linkMobileStep.value is LinkMobileStep.QrReady) {
Timber.tag(tag.value).d("Emit QrRotating due to HumanQrGrantLoginException.NotFound")
_linkMobileStep.emit(LinkMobileStep.QrRotating)
} else {
_linkMobileStep.emit(LinkMobileStep.Error(e.map()))
}
} catch (e: HumanQrGrantLoginException) {
Timber.tag(tag.value).w(e, "Error during QR login grant")
_linkMobileStep.emit(LinkMobileStep.Error(e.map()))

View file

@ -118,6 +118,35 @@ class RustLinkMobileHandlerTest {
}
}
@Test
fun `when start throws HumanQrGrantLoginException_NotFound when in state QrReady, the handler emits QrRotating step`() = runTest {
val completable = CompletableDeferred<Unit>()
val handler = FakeFfiGrantLoginWithQrCodeHandler(
generateResult = {
completable.await()
throw HumanQrGrantLoginException.NotFound("Timeout")
}
)
val sut = createRustLinkMobileHandler(
handler,
)
sut.linkMobileStep.test {
val initialItem = awaitItem()
assertThat(initialItem).isEqualTo(LinkMobileStep.Uninitialized)
backgroundScope.launch {
sut.start()
}
runCurrent()
handler.emitGenerateProgress(GrantGeneratedQrLoginProgress.QrReady(FakeFfiQrCodeData(toBytesResult = { QR_CODE_DATA_RECIPROCATE })))
val readyState = awaitItem()
assertThat(readyState).isInstanceOf(LinkMobileStep.QrReady::class.java)
// generate returns, error is emitted
completable.complete(Unit)
val qrRotatingState = awaitItem()
assertThat(qrRotatingState).isEqualTo(LinkMobileStep.QrRotating)
}
}
private fun TestScope.createRustLinkMobileHandler(
handler: FakeFfiGrantLoginWithQrCodeHandler = FakeFfiGrantLoginWithQrCodeHandler(),
) = RustLinkMobileHandler(

View file

@ -57,8 +57,8 @@ private fun BitMatrix.toBitmap(
@Composable
fun QrCodeImage(
data: String,
forceMaxBrightness: Boolean = true,
modifier: Modifier = Modifier,
forceMaxBrightness: Boolean = true,
) {
if (forceMaxBrightness) {
ForceMaxBrightness()