diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift index 704c0b614..ea0d2b549 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift @@ -57,11 +57,16 @@ final class KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordin // MARK: - KeyBackupSetupPassphraseViewModelCoordinatorDelegate extension KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseViewModelCoordinatorDelegate { + + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) { + self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCreateBackupFromPassphraseWithResultingRecoveryKey: recoveryKey) + } + + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromRecoveryKey recoveryKey: String) { + self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCreateBackupFromRecoveryKey: recoveryKey) + } + func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) { self.delegate?.keyBackupSetupPassphraseCoordinatorDidCancel(self) } - - func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { - self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCompleteWithMegolmBackupCreationInfo: megolmBackupCreationInfo) - } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift index 889be08f5..f94722adb 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift @@ -17,7 +17,8 @@ import Foundation protocol KeyBackupSetupPassphraseCoordinatorDelegate: class { - func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseCoordinatorDidCancel(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType) } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift index 9f74ae331..b6919a730 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift @@ -19,6 +19,7 @@ import Foundation /// KeyBackupSetupPassphraseViewController view actions exposed to view model enum KeyBackupSetupPassphraseViewAction { case setupPassphrase + case setupRecoveryKey case skip case skipAlertSkip case skipAlertContinue diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard index a72291f90..2e7a05579 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard @@ -22,22 +22,28 @@ - + - + + - + @@ -46,13 +52,13 @@ You’ll need it if you log out, or lose access to this device. - + @@ -103,7 +109,7 @@ You’ll need it if you log out, or lose access to this device. @@ -140,13 +146,13 @@ You’ll need it if you log out, or lose access to this device. - + @@ -176,7 +182,7 @@ You’ll need it if you log out, or lose access to this device. @@ -208,15 +214,15 @@ You’ll need it if you log out, or lose access to this device. - + - - + - + + + + + + - - + + + + + + + @@ -296,6 +333,9 @@ You’ll need it if you log out, or lose access to this device. + + + diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift index ac074b90a..c9d51ff90 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift @@ -29,6 +29,8 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { // MARK: Outlets @IBOutlet private weak var scrollView: UIScrollView! + + @IBOutlet private weak var titleLabel: UILabel! @IBOutlet private weak var informationLabel: UILabel! @IBOutlet private weak var formBackgroundView: UIView! @@ -51,6 +53,9 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { @IBOutlet private weak var setPassphraseButtonBackgroundView: UIView! @IBOutlet private weak var setPassphraseButton: UIButton! + @IBOutlet private weak var setUpRecoveryKeyInfoLabel: UILabel! + @IBOutlet private weak var setUpRecoveryKeyButton: UIButton! + // MARK: Private private var isFirstViewAppearing: Bool = true @@ -138,6 +143,7 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { theme.applyStyle(onNavigationBar: navigationBar) } + self.titleLabel.textColor = theme.textPrimaryColor self.informationLabel.textColor = theme.textPrimaryColor self.formBackgroundView.backgroundColor = theme.backgroundColor @@ -157,6 +163,9 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { self.setPassphraseButton.backgroundColor = theme.backgroundColor theme.applyStyle(onButton: self.setPassphraseButton) + + self.setUpRecoveryKeyInfoLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onButton: self.setUpRecoveryKeyButton) } private func registerThemeServiceDidChangeThemeNotification() { @@ -168,14 +177,15 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { } private func setupViews() { - let skipBarButtonItem = MXKBarButtonItem(title: VectorL10n.keyBackupSetupSkipAction, style: .plain) { [weak self] in - self?.skipButtonAction() + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.cancelButtonAction() } - self.navigationItem.rightBarButtonItem = skipBarButtonItem + self.navigationItem.rightBarButtonItem = cancelBarButtonItem self.scrollView.keyboardDismissMode = .interactive + self.titleLabel.text = VectorL10n.keyBackupSetupPassphraseTitle self.informationLabel.text = VectorL10n.keyBackupSetupPassphraseInfo self.passphraseTitleLabel.text = VectorL10n.keyBackupSetupPassphrasePassphraseTitle @@ -360,7 +370,11 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { self.viewModel.process(viewAction: .setupPassphrase) } - private func skipButtonAction() { + @IBAction private func setUpRecoveryKeyButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .setupRecoveryKey) + } + + private func cancelButtonAction() { self.viewModel.process(viewAction: .skip) } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift index 06bc6f0df..ea2fd4752 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift @@ -26,6 +26,7 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel private let passwordStrengthManager: PasswordStrengthManager private let keyBackup: MXKeyBackup private let coordinatorDelegateQueue: OperationQueue + private var createKeyBackupOperation: MXHTTPOperation? // MARK: Public @@ -63,12 +64,18 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel self.coordinatorDelegateQueue = OperationQueue.vc_createSerialOperationQueue(name: "\(type(of: self)).coordinatorDelegateQueue") } + deinit { + self.createKeyBackupOperation?.cancel() + } + // MARK: - Public func process(viewAction: KeyBackupSetupPassphraseViewAction) { switch viewAction { case .setupPassphrase: self.setupPassphrase() + case .setupRecoveryKey: + self.setupRecoveryKey() case .skip: self.coordinatorDelegateQueue.vc_pause() self.viewDelegate?.keyBackupSetupPassphraseViewModelShowSkipAlert(self) @@ -82,30 +89,58 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel // MARK: - Private - func setupPassphrase() { + private func setupPassphrase() { guard let passphrase = self.passphrase else { return } - self.viewDelegate?.keyBackupSetupPassphraseViewModel(self, didUpdateViewState: .loading) + self.update(viewState: .loading) self.keyBackup.prepareKeyBackupVersion(withPassword: passphrase, success: { [weak self] (megolmBackupCreationInfo) in guard let sself = self else { return } - sself.viewDelegate?.keyBackupSetupPassphraseViewModel(sself, didUpdateViewState: .loaded) - - sself.coordinatorDelegateQueue.addOperation { - DispatchQueue.main.async { - sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCompleteWithMegolmBackupCreationInfo: megolmBackupCreationInfo) + sself.createKeyBackupOperation = sself.keyBackup.createKeyBackupVersion(megolmBackupCreationInfo, success: { (_) in + + sself.update(viewState: .loaded) + + sself.coordinatorDelegateQueue.addOperation { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCreateBackupFromPassphraseWithResultingRecoveryKey: megolmBackupCreationInfo.recoveryKey) + } } - } + + }, failure: { (error) in + self?.update(viewState: .error(error)) + }) }, failure: { [weak self] error in + self?.update(viewState: .error(error)) + }) + } + + private func setupRecoveryKey() { + self.update(viewState: .loading) + + self.keyBackup.prepareKeyBackupVersion(withPassword: nil, success: { [weak self] (megolmBackupCreationInfo) in guard let sself = self else { return - } - sself.viewDelegate?.keyBackupSetupPassphraseViewModel(sself, didUpdateViewState: .error(error)) + } + + sself.createKeyBackupOperation = sself.keyBackup.createKeyBackupVersion(megolmBackupCreationInfo, success: { (_) in + + sself.update(viewState: .loaded) + + sself.coordinatorDelegateQueue.addOperation { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCreateBackupFromRecoveryKey: megolmBackupCreationInfo.recoveryKey) + } + } + }, failure: { (error) in + self?.update(viewState: .error(error)) + }) + }, failure: { [weak self] error in + self?.update(viewState: .error(error)) }) } @@ -119,4 +154,8 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel } return self.passwordStrengthManager.passwordStrength(for: password) } + + private func update(viewState: KeyBackupSetupPassphraseViewState) { + self.viewDelegate?.keyBackupSetupPassphraseViewModel(self, didUpdateViewState: viewState) + } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift index 40d94da38..2f4b2dfaa 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift @@ -22,7 +22,8 @@ protocol KeyBackupSetupPassphraseViewModelViewDelegate: class { } protocol KeyBackupSetupPassphraseViewModelCoordinatorDelegate: class { - func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift index aa498124f..e7931e50e 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift @@ -19,6 +19,16 @@ import Reusable final class PasswordStrengthView: UIView, NibOwnerLoadable { + // MARK: - Constants + + private enum StrengthColors { + static let gray = UIColor(rgb: 0x9E9E9E) + static let red = UIColor(rgb: 0xF56679) + static let orange = UIColor(rgb: 0xFFC666) + static let yellow = UIColor(rgb: 0xF8E71C) + static let green = UIColor(rgb: 0x7AC9A1) + } + // MARK: - Properties // MARK: Outlets @@ -32,15 +42,6 @@ final class PasswordStrengthView: UIView, NibOwnerLoadable { private var strengthViews: [UIView] = [] - private let strengthViewDefaultColor = UIColor(rgb: 0x9E9E9E) - - private var strengthViewColors: [Int: UIColor] = [ - 0: UIColor(rgb: 0xF56679), - 1: UIColor(rgb: 0xFFC666), - 2: UIColor(rgb: 0xF8E71C), - 3: UIColor(rgb: 0x7AC9A1) - ] - // MARK: Public var strength: PasswordStrength = .tooGuessable { @@ -88,44 +89,42 @@ final class PasswordStrengthView: UIView, NibOwnerLoadable { private func updateStrengthColors() { let strengthViewIndex: Int + let color: UIColor switch self.strength { case .tooGuessable, .veryGuessable: strengthViewIndex = 0 + color = StrengthColors.red case .somewhatGuessable: strengthViewIndex = 1 + color = StrengthColors.orange case .safelyUnguessable: strengthViewIndex = 2 + color = StrengthColors.yellow case .veryUnguessable: strengthViewIndex = 3 + color = StrengthColors.green } - self.color(until: strengthViewIndex) + self.color(until: strengthViewIndex, with: color) } - private func color(until strengthViewIndex: Int) { + private func color(until strengthViewIndex: Int, with color: UIColor) { var index: Int = 0 for strenghView in self.strengthViews { - let color: UIColor + let strenghViewBackgroundColor: UIColor if index <= strengthViewIndex { - color = self.color(for: index) + strenghViewBackgroundColor = color } else { - color = self.strengthViewDefaultColor + strenghViewBackgroundColor = StrengthColors.gray } - strenghView.backgroundColor = color + strenghView.backgroundColor = strenghViewBackgroundColor index+=1 } } - - private func color(for index: Int) -> UIColor { - guard let color = self.strengthViewColors[index] else { - return self.strengthViewDefaultColor - } - return color - } }