diff --git a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift index fb245dc12..3e6dc3f81 100644 --- a/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift +++ b/ElementX/Sources/Screens/QRCodeLoginScreen/QRCodeLoginScreenViewModel.swift @@ -224,12 +224,10 @@ class QRCodeLoginScreenViewModel: QRCodeLoginScreenViewModelType, QRCodeLoginScr case .waitingForAuthorisation(let url): requestOIDCAuthorization(url: url) case .syncingSecrets: - // break // Nothing to do. - // .done is rarely received at the moment, so lets consider linking to be done here. + break // Nothing to do. + case .done: MXLog.info("Link with QR code completed.") actionsSubject.send(.linkedDevice) - case .done: - break // Not necessary right now with the workaround above in place. } } } diff --git a/ElementX/Sources/Services/Authentication/LinkNewDeviceService.swift b/ElementX/Sources/Services/Authentication/LinkNewDeviceService.swift index b8f8af515..c3aba5255 100644 --- a/ElementX/Sources/Services/Authentication/LinkNewDeviceService.swift +++ b/ElementX/Sources/Services/Authentication/LinkNewDeviceService.swift @@ -65,6 +65,8 @@ class LinkNewDeviceService: LinkNewDeviceServiceProtocol { do { // Note: The SDK doesn't provide us with a way to cancel the grant if the user hit the cancel button 🤷‍♂️ try await grantLoginHandler.generate(progressListener: listener) // The success state is handled by the listener. + // We send the .done progress in case the listener didn't get a chance to pass it on from the SDK before being deallocated + progressSubject.send(LinkMobileProgress.done) } catch let error as HumanQrGrantLoginError { MXLog.error("QR code reciprocate error: \(error)") progressSubject.send(completion: .failure(.init(rustError: error))) @@ -105,6 +107,8 @@ class LinkNewDeviceService: LinkNewDeviceServiceProtocol { do { // Note: The SDK doesn't provide us with a way to cancel the grant if the user hit the cancel button 🤷‍♂️ try await grantLoginHandler.scan(qrCodeData: qrCodeData, progressListener: listener) // The success state is handled by the listener. + // We send the .done progress in case the listener didn't get a chance to pass it on from the SDK before being deallocated + progressSubject.send(LinkDesktopProgress.done) } catch let error as HumanQrGrantLoginError { MXLog.error("QR code reciprocate error: \(error)") progressSubject.send(completion: .failure(.init(rustError: error))) diff --git a/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift b/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift index 132852a0a..122a979b7 100644 --- a/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift +++ b/UnitTests/Sources/QRCodeLoginScreenViewModelTests.swift @@ -189,18 +189,17 @@ struct QRCodeLoginScreenViewModelTests { linkMobileProgressSubject.send(.waitingForAuthorisation(verificationURL: .homeDirectory)) try await deferredAction.fulfill() - // Note: The SDK rarely sends the done action, so this test has been updated for the workaround of finishing early. + let currentState = context.viewState.state + let deferredFailure = deferFailure(context.$viewState, timeout: .seconds(1)) { $0.state != currentState } + linkMobileProgressSubject.send(.syncingSecrets) + try await deferredFailure.fulfill() + deferredAction = deferFulfillment(viewModel.actionsPublisher) { action in guard case .linkedDevice = action else { return false } return true } - linkMobileProgressSubject.send(.syncingSecrets) - try await deferredAction.fulfill() - - let currentState = context.viewState.state - let deferredFailure = deferFailure(context.$viewState, timeout: .seconds(1)) { $0.state != currentState } linkMobileProgressSubject.send(.done) - try await deferredFailure.fulfill() + try await deferredAction.fulfill() } // MARK: - Helpers