From b1b468d6a6859a3681be9cb3302f0f73abe52da3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 8 Jun 2026 15:29:35 +0200 Subject: [PATCH] Ensure that the application rotate the QrCode if one day the SDK emits the `.Expired` error. --- .../linknewdevice/RustLinkMobileHandler.kt | 4 +++ .../RustLinkMobileHandlerTest.kt | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt index cb387a9d21..a44a8d5943 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandler.kt @@ -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? diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt index ad751cc86b..3d84e34f45 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/linknewdevice/RustLinkMobileHandlerTest.kt @@ -147,6 +147,32 @@ class RustLinkMobileHandlerTest { } } + @Test + fun `when start throws HumanQrGrantLoginException_Expired, the handler emits QrRotating step`() = runTest { + val completable = CompletableDeferred() + 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(