diff --git a/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift index 053e20e9d..fb5c0ec26 100644 --- a/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift @@ -43,6 +43,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { enum Event: EventType { case next + case nextSkippingIdentityConfimed } private let stateMachine: StateMachine @@ -123,7 +124,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { } private func configureStateMachine() { - stateMachine.addRouteMapping { [weak self] _, fromState, _ in + stateMachine.addRouteMapping { [weak self] event, fromState, _ in guard let self else { return nil } @@ -141,8 +142,22 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { return .finished case (.identityConfirmation, _, _, _, _): - return .identityConfirmed - + if event == .nextSkippingIdentityConfimed { + // Used when the verification state has updated to verified + // after starting the onboarding flow + switch (requiresAppLockSetup, requiresAnalyticsSetup, requiresNotificationsSetup) { + case (true, _, _): + return .appLockSetup + case (false, true, _): + return .analyticsPrompt + case (false, false, true): + return .notificationPermissions + case (false, false, false): + return .finished + } + } else { + return .identityConfirmed + } case (.identityConfirmed, _, true, _, _): return .appLockSetup case (.identityConfirmed, _, false, true, _): @@ -216,14 +231,36 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { presentRecoveryKeyScreen() case .skip: appSettings.hasRunIdentityConfirmationOnboarding = true - stateMachine.tryEvent(.next) + stateMachine.tryEvent(.nextSkippingIdentityConfimed) case .reset: presentEncryptionResetScreen() } } .store(in: &cancellables) - presentCoordinator(coordinator) + // If the verification state is still unknown wait for it to resolve + // and just move on to the next steps if verified + var verificationStateCancellable: AnyCancellable? + if userSession.sessionSecurityStatePublisher.value.verificationState == .unknown { + verificationStateCancellable = userSession.sessionSecurityStatePublisher + .map(\.verificationState) + .removeDuplicates() + .sink { [weak self] value in + guard let self else { return } + + if value == .verified { + appSettings.hasRunIdentityConfirmationOnboarding = true + stateMachine.tryEvent(.nextSkippingIdentityConfimed) + } else { + // Captured by the block below, nil-ing it wouldn't work + verificationStateCancellable?.cancel() + } + } + } + + presentCoordinator(coordinator) { [verificationStateCancellable] in + verificationStateCancellable?.cancel() + } } private func presentSessionVerificationScreen() async { @@ -373,11 +410,11 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol { presentCoordinator(coordinator) } - private func presentCoordinator(_ coordinator: CoordinatorProtocol) { + private func presentCoordinator(_ coordinator: CoordinatorProtocol, dismissalCallback: (() -> Void)? = nil) { if navigationStackCoordinator.rootCoordinator == nil { - navigationStackCoordinator.setRootCoordinator(coordinator) + navigationStackCoordinator.setRootCoordinator(coordinator, dismissalCallback: dismissalCallback) } else { - navigationStackCoordinator.push(coordinator) + navigationStackCoordinator.push(coordinator, dismissalCallback: dismissalCallback) } }