Skip to content

Commit

Permalink
Ensure multiple mandatory verification flows can be ran consecutively…
Browse files Browse the repository at this point in the history
… (e.g. following encryption resets) (#3722)

* Ensure multiple mandatory verification flows can be ran consecutively (e.g. following encryption resets)

* Disabled the back button on the verification screen only when verified and waiting for the security state publisher
  • Loading branch information
stefanceriu authored Jan 31, 2025
1 parent 4856ffd commit 9706985
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 10 deletions.
25 changes: 17 additions & 8 deletions ElementX/Sources/FlowCoordinators/OnboardingFlowCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {

enum Event: EventType {
case next
case nextSkippingIdentityConfimed
case nextSkippingIdentityConfirmed
}

private let stateMachine: StateMachine<State, Event>
Expand Down Expand Up @@ -79,22 +79,23 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {

stateMachine = .init(state: .initial)

configureStateMachine()

// Verification can change as part of the onboarding flow by verifying with
// another device, using a recovery key or by resetting one's crypto identity.
// It can also happen that onboarding started before it had a chance to update,
// usually seen when registering a new account.
// Handle all those cases here instead of spreading them throughout the code.
verificationStateCancellable = userSession.sessionSecurityStatePublisher
.map(\.verificationState)
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink { [weak self] value in
guard let self,
value == .verified,
stateMachine.state == .identityConfirmation else { return }

appSettings.hasRunIdentityConfirmationOnboarding = true
stateMachine.tryEvent(.nextSkippingIdentityConfimed)
self.verificationStateCancellable = nil
stateMachine.tryEvent(.nextSkippingIdentityConfirmed)
}
}

Expand All @@ -111,8 +112,6 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
fatalError("This flow coordinator shouldn't have been started")
}

configureStateMachine()

rootNavigationStackCoordinator.setFullScreenCoverCoordinator(navigationStackCoordinator, animated: !isNewLogin)

stateMachine.tryEvent(.next)
Expand Down Expand Up @@ -146,6 +145,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
}

private func configureStateMachine() {
stateMachine.addRoute(.init(fromState: .finished, toState: .initial))
stateMachine.addRouteMapping { [weak self] event, fromState, _ in
guard let self else {
return nil
Expand All @@ -164,7 +164,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
return .finished

case (.identityConfirmation, _, _, _, _):
if event == .nextSkippingIdentityConfimed {
if event == .nextSkippingIdentityConfirmed {
// Used when the verification state has updated to verified
// after starting the onboarding flow
switch (requiresAppLockSetup, requiresAnalyticsSetup, requiresNotificationsSetup) {
Expand Down Expand Up @@ -225,9 +225,18 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
presentNotificationPermissionsScreen()
case (_, _, .finished):
rootNavigationStackCoordinator.setFullScreenCoverCoordinator(nil)
stateMachine.tryState(.initial)
case (.finished, _, .initial):
break
default:
fatalError("Unknown transition: \(context)")
}

if let event = context.event {
MXLog.info("Transitioning from `\(context.fromState)` to `\(context.toState)` with event `\(event)`")
} else {
MXLog.info("Transitioning from \(context.fromState)` to `\(context.toState)`")
}
}

stateMachine.addErrorHandler { context in
Expand All @@ -251,7 +260,7 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
presentRecoveryKeyScreen()
case .skip:
appSettings.hasRunIdentityConfirmationOnboarding = true
stateMachine.tryEvent(.nextSkippingIdentityConfimed)
stateMachine.tryEvent(.nextSkippingIdentityConfirmed)
case .reset:
startEncryptionResetFlow()
case .logout:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
}

func attemptStartingOnboarding() {
MXLog.info("Attempting to start onboarding")

if onboardingFlowCoordinator.shouldStart {
clearRoute(animated: false)
onboardingFlowCoordinator.start()
Expand Down Expand Up @@ -340,7 +342,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
userSession.sessionSecurityStatePublisher
.map(\.verificationState)
.filter { $0 != .unknown }
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
guard let self else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct SessionVerificationScreen: View {
.background()
.backgroundStyle(.compound.bgCanvasDefault)
.interactiveDismissDisabled()
.navigationBarBackButtonHidden(context.viewState.verificationState == .verified)
}

// MARK: - Private
Expand Down
1 change: 0 additions & 1 deletion ElementX/Sources/Services/Session/UserSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class UserSession: UserSessionProtocol {
MXLog.info("Session security state changed, verificationState: \($0), recoveryState: \($1)")
return SessionSecurityState(verificationState: $0, recoveryState: $1)
}
.removeDuplicates()
.receive(on: DispatchQueue.main)
.sink { [weak self] value in
self?.sessionSecurityStateSubject.send(value)
Expand Down

0 comments on commit 9706985

Please sign in to comment.