mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:33:26 +00:00
Encryption Flow Coordinators. (#3471)
* Manage the secure backup screens with flow coordinators.
* Add UI tests for the EncryptionSettingsFlowCoordinator.
* Realise that the settings flow can't reset anymore and remove the sub-flow 🤦♂️
* Add UI tests for the EncryptionResetFlowCoordinator.
This commit is contained in:
+6
-86
@@ -11,12 +11,12 @@ import SwiftUI
|
||||
struct SecureBackupScreenCoordinatorParameters {
|
||||
let appSettings: AppSettings
|
||||
let clientProxy: ClientProxyProtocol
|
||||
weak var navigationStackCoordinator: NavigationStackCoordinator?
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
}
|
||||
|
||||
enum SecureBackupScreenCoordinatorAction {
|
||||
case requestOIDCAuthorisation(URL)
|
||||
case manageRecoveryKey
|
||||
case disableKeyBackup
|
||||
}
|
||||
|
||||
final class SecureBackupScreenCoordinator: CoordinatorProtocol {
|
||||
@@ -43,53 +43,10 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .recoveryKey:
|
||||
let recoveryNavigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let recoveryKeyCoordinator = SecureBackupRecoveryKeyScreenCoordinator(parameters: .init(secureBackupController: parameters.clientProxy.secureBackupController,
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
isModallyPresented: true))
|
||||
|
||||
recoveryKeyCoordinator.actions.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
switch action {
|
||||
case .cancel:
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
case .recoverySetUp:
|
||||
showSuccessIndicator(title: L10n.screenRecoveryKeySetupSuccess)
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
case .recoveryChanged:
|
||||
showSuccessIndicator(title: L10n.screenRecoveryKeyChangeSuccess)
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
case .recoveryFixed:
|
||||
showSuccessIndicator(title: L10n.screenRecoveryKeyConfirmSuccess)
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
case .resetEncryption:
|
||||
showEncryptionReset(recoveryNavigationStackCoordinator: recoveryNavigationStackCoordinator)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
recoveryNavigationStackCoordinator.setRootCoordinator(recoveryKeyCoordinator, animated: true)
|
||||
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(recoveryNavigationStackCoordinator)
|
||||
case .keyBackup:
|
||||
let navigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let keyBackupCoordinator = SecureBackupKeyBackupScreenCoordinator(parameters: .init(secureBackupController: parameters.clientProxy.secureBackupController,
|
||||
userIndicatorController: parameters.userIndicatorController))
|
||||
|
||||
keyBackupCoordinator.actions.sink { [weak self] action in
|
||||
switch action {
|
||||
case .done:
|
||||
self?.parameters.navigationStackCoordinator?.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
navigationStackCoordinator.setRootCoordinator(keyBackupCoordinator, animated: true)
|
||||
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(navigationStackCoordinator)
|
||||
case .manageRecoveryKey:
|
||||
actionsSubject.send(.manageRecoveryKey)
|
||||
case .disableKeyBackup:
|
||||
actionsSubject.send(.disableKeyBackup)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
@@ -98,41 +55,4 @@ final class SecureBackupScreenCoordinator: CoordinatorProtocol {
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(SecureBackupScreen(context: viewModel.context))
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private func showSuccessIndicator(title: String) {
|
||||
parameters.userIndicatorController.submitIndicator(.init(id: .init(),
|
||||
type: .modal(progress: .none, interactiveDismissDisabled: false, allowsInteraction: false),
|
||||
title: title,
|
||||
iconName: "checkmark",
|
||||
persistent: false))
|
||||
}
|
||||
|
||||
private func showEncryptionReset(recoveryNavigationStackCoordinator: NavigationStackCoordinator) {
|
||||
let resetNavigationStackCoordinator = NavigationStackCoordinator()
|
||||
|
||||
let coordinator = EncryptionResetScreenCoordinator(parameters: .init(clientProxy: parameters.clientProxy,
|
||||
navigationStackCoordinator: resetNavigationStackCoordinator,
|
||||
userIndicatorController: parameters.userIndicatorController))
|
||||
|
||||
coordinator.actionsPublisher.sink { [weak self] action in
|
||||
guard let self else { return }
|
||||
|
||||
switch action {
|
||||
case .cancel:
|
||||
recoveryNavigationStackCoordinator.setSheetCoordinator(nil)
|
||||
case .requestOIDCAuthorisation(let url):
|
||||
actionsSubject.send(.requestOIDCAuthorisation(url))
|
||||
case .resetFinished:
|
||||
parameters.navigationStackCoordinator?.setSheetCoordinator(nil) // Dismiss the recovery screen
|
||||
recoveryNavigationStackCoordinator.setSheetCoordinator(nil)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
resetNavigationStackCoordinator.setRootCoordinator(coordinator)
|
||||
|
||||
recoveryNavigationStackCoordinator.setSheetCoordinator(resetNavigationStackCoordinator)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,8 +8,8 @@
|
||||
import Foundation
|
||||
|
||||
enum SecureBackupScreenViewModelAction {
|
||||
case recoveryKey
|
||||
case keyBackup
|
||||
case manageRecoveryKey
|
||||
case disableKeyBackup
|
||||
}
|
||||
|
||||
struct SecureBackupScreenViewState: BindableState {
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ class SecureBackupScreenViewModel: SecureBackupScreenViewModelType, SecureBackup
|
||||
override func process(viewAction: SecureBackupScreenViewAction) {
|
||||
switch viewAction {
|
||||
case .recoveryKey:
|
||||
actionsSubject.send(.recoveryKey)
|
||||
actionsSubject.send(.manageRecoveryKey)
|
||||
case .keyStorageToggled(let enable):
|
||||
let keyBackupState = secureBackupController.keyBackupState.value
|
||||
switch (keyBackupState, enable) {
|
||||
@@ -57,7 +57,7 @@ class SecureBackupScreenViewModel: SecureBackupScreenViewModelType, SecureBackup
|
||||
enableBackup()
|
||||
case (.enabled, false):
|
||||
state.bindings.keyStorageEnabled = keyBackupState.keyStorageToggleState // Reset the toggle in case the user cancels
|
||||
actionsSubject.send(.keyBackup)
|
||||
actionsSubject.send(.disableKeyBackup)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
+10
-10
@@ -53,7 +53,13 @@ struct SecureBackupScreen: View {
|
||||
.accessibilityElement(children: .combine)
|
||||
})
|
||||
|
||||
keyStorageToggle
|
||||
ListRow(label: .plain(title: L10n.screenChatBackupKeyStorageToggleTitle,
|
||||
description: context.viewState.keyStorageToggleDescription),
|
||||
kind: .toggle($context.keyStorageEnabled))
|
||||
.onChange(of: context.keyStorageEnabled) { _, newValue in
|
||||
context.send(viewAction: .keyStorageToggled(newValue))
|
||||
}
|
||||
.accessibilityIdentifier(A11yIdentifiers.secureBackupScreen.keyStorage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,15 +73,6 @@ struct SecureBackupScreen: View {
|
||||
return description
|
||||
}
|
||||
|
||||
private var keyStorageToggle: some View {
|
||||
ListRow(label: .plain(title: L10n.screenChatBackupKeyStorageToggleTitle,
|
||||
description: context.viewState.keyStorageToggleDescription),
|
||||
kind: .toggle($context.keyStorageEnabled))
|
||||
.onChange(of: context.keyStorageEnabled) { _, newValue in
|
||||
context.send(viewAction: .keyStorageToggled(newValue))
|
||||
}
|
||||
}
|
||||
|
||||
private var recoveryKeySection: some View {
|
||||
Section {
|
||||
switch context.viewState.recoveryState {
|
||||
@@ -85,6 +82,7 @@ struct SecureBackupScreen: View {
|
||||
icon: \.key,
|
||||
iconAlignment: .top),
|
||||
kind: .navigationLink { context.send(viewAction: .recoveryKey) })
|
||||
.accessibilityIdentifier(A11yIdentifiers.secureBackupScreen.recoveryKey)
|
||||
case .disabled:
|
||||
ListRow(label: .default(title: L10n.screenChatBackupRecoveryActionSetup,
|
||||
description: L10n.screenChatBackupRecoveryActionChangeDescription,
|
||||
@@ -92,10 +90,12 @@ struct SecureBackupScreen: View {
|
||||
iconAlignment: .top),
|
||||
details: .icon(BadgeView(size: 10)),
|
||||
kind: .navigationLink { context.send(viewAction: .recoveryKey) })
|
||||
.accessibilityIdentifier(A11yIdentifiers.secureBackupScreen.recoveryKey)
|
||||
case .incomplete:
|
||||
ListRow(label: .plain(title: L10n.screenChatBackupRecoveryActionConfirm),
|
||||
details: .icon(BadgeView(size: 10)),
|
||||
kind: .navigationLink { context.send(viewAction: .recoveryKey) })
|
||||
.accessibilityIdentifier(A11yIdentifiers.secureBackupScreen.recoveryKey)
|
||||
default:
|
||||
ListRow(label: .plain(title: L10n.commonLoading), details: .isWaiting(true), kind: .label)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user