Tweak the onboarding flow identity confirmation screen

- hide the recovery key option if recovery wasn't set up beforehand
- add a button to present the reset encryption instructions screen
This commit is contained in:
Stefan Ceriu 2024-05-24 13:57:40 +03:00 committed by Stefan Ceriu
parent f8d094516d
commit 696d599773
9 changed files with 45 additions and 24 deletions

View File

@ -212,6 +212,8 @@ class OnboardingFlowCoordinator: FlowCoordinatorProtocol {
case .skip:
appSettings.hasRunIdentityConfirmationOnboarding = true
stateMachine.tryEvent(.next)
case .reset:
presentResetRecoveryKeyScreen()
}
}
.store(in: &cancellables)

View File

@ -30,6 +30,7 @@ enum IdentityConfirmationScreenCoordinatorAction {
case recoveryKey
/// Only possible in debug builds.
case skip
case reset
}
final class IdentityConfirmationScreenCoordinator: CoordinatorProtocol {
@ -63,6 +64,8 @@ final class IdentityConfirmationScreenCoordinator: CoordinatorProtocol {
actionsSubject.send(.recoveryKey)
case .skip:
actionsSubject.send(.skip)
case .reset:
actionsSubject.send(.reset)
}
}
.store(in: &cancellables)

View File

@ -21,15 +21,16 @@ enum IdentityConfirmationScreenViewModelAction {
case recoveryKey
/// Only possible in debug builds.
case skip
case reset
}
struct IdentityConfirmationScreenViewState: BindableState {
enum Mode {
case recoveryOnly
case recoveryAndVerification
enum AvailableActions {
case recovery
case interactiveVerification
}
var mode = Mode.recoveryOnly
var availableActions: [AvailableActions] = []
let learnMoreURL: URL
}
@ -38,4 +39,5 @@ enum IdentityConfirmationScreenViewAction {
case recoveryKey
/// Only possible in debug builds.
case skip
case reset
}

View File

@ -59,6 +59,8 @@ class IdentityConfirmationScreenViewModel: IdentityConfirmationScreenViewModelTy
actionsSubject.send(.recoveryKey)
case .skip:
actionsSubject.send(.skip)
case .reset:
actionsSubject.send(.reset)
}
}
@ -75,11 +77,18 @@ class IdentityConfirmationScreenViewModel: IdentityConfirmationScreenViewModelTy
return
}
guard case let .success(isOnlyDeviceLeft) = await userSession.clientProxy.isOnlyDeviceLeft() else {
return
var availableActions: [IdentityConfirmationScreenViewState.AvailableActions] = []
if case let .success(isOnlyDeviceLeft) = await userSession.clientProxy.isOnlyDeviceLeft(),
!isOnlyDeviceLeft {
availableActions.append(.interactiveVerification)
}
state.mode = isOnlyDeviceLeft ? .recoveryOnly : .recoveryAndVerification
if sessionSecurityState.recoveryState == .enabled || sessionSecurityState.recoveryState == .incomplete {
availableActions.append(.recovery)
}
state.availableActions = availableActions
}
private static let loadingIndicatorIdentifier = "\(IdentityConfirmationScreenViewModel.self)-Loading"

View File

@ -71,23 +71,23 @@ struct IdentityConfirmationScreen: View {
@ViewBuilder
private var actionButtons: some View {
VStack(spacing: 32) {
switch context.viewState.mode {
case .recoveryOnly:
Button(L10n.screenSessionVerificationEnterRecoveryKey) {
context.send(viewAction: .recoveryKey)
}
.buttonStyle(.compound(.primary))
case .recoveryAndVerification:
if context.viewState.availableActions.contains(.interactiveVerification) {
Button(L10n.actionStartVerification) {
context.send(viewAction: .otherDevice)
}
.buttonStyle(.compound(.primary))
if context.viewState.availableActions.contains(.recovery) {
Button(L10n.screenSessionVerificationEnterRecoveryKey) {
context.send(viewAction: .recoveryKey)
}
.buttonStyle(.compound(.plain))
}
} else if context.viewState.availableActions.contains(.recovery) {
Button(L10n.screenSessionVerificationEnterRecoveryKey) {
context.send(viewAction: .recoveryKey)
}
.buttonStyle(.compound(.plain))
.buttonStyle(.compound(.primary))
}
if shouldShowSkipButton {
@ -96,6 +96,11 @@ struct IdentityConfirmationScreen: View {
}
.buttonStyle(.compound(.plain))
}
Button(L10n.screenRecoveryKeyConfirmLostRecoveryKey, role: .destructive) {
context.send(viewAction: .reset)
}
.buttonStyle(.compound(.plain))
}
}
}