diff --git a/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift b/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift index 74b7f967ea..a9a99c2ada 100644 --- a/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift +++ b/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinator.swift @@ -54,7 +54,7 @@ final class CrossSigningSetupCoordinator: CrossSigningSetupCoordinatorType { // MARK: - Private methods - private func setupCrossSigning(with authenticationParameters: [String: Any] = [:]) { + private func setupCrossSigning(with authenticationParameters: [String: Any] = [:], hasAuthenticated: Bool = false) { guard let crossSigning = parameters.session.crypto?.crossSigning else { return } crossSigning.setup(withAuthParams: authenticationParameters) { [weak self] in @@ -64,7 +64,8 @@ final class CrossSigningSetupCoordinator: CrossSigningSetupCoordinatorType { guard let self else { return } if let responseData = (error as NSError).userInfo[MXHTTPClientErrorResponseDataKey] as? [AnyHashable: Any], - let authenticationSession = MXAuthenticationSession(fromJSON: responseData) { + let authenticationSession = MXAuthenticationSession(fromJSON: responseData), + !hasAuthenticated { // Don't re-presenting authentication if the user closes the web view without finishing. showReauthentication(authenticationSession: authenticationSession) } else { delegate?.crossSigningSetupCoordinator(self, didFailWithError: error) @@ -93,7 +94,7 @@ final class CrossSigningSetupCoordinator: CrossSigningSetupCoordinatorType { extension CrossSigningSetupCoordinator: ReauthenticationCoordinatorDelegate { func reauthenticationCoordinatorDidComplete(_ coordinator: ReauthenticationCoordinatorType, withAuthenticationParameters authenticationParameters: [String: Any]?) { - self.setupCrossSigning(with: authenticationParameters ?? [:]) + self.setupCrossSigning(with: authenticationParameters ?? [:], hasAuthenticated: true) } func reauthenticationCoordinatorDidCancel(_ coordinator: ReauthenticationCoordinatorType) { diff --git a/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinator.swift b/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinator.swift index 71220203d2..038e9f5475 100644 --- a/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinator.swift +++ b/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinator.swift @@ -189,6 +189,17 @@ final class KeyVerificationCoordinator: KeyVerificationCoordinatorType { return coordinator } + private func showSecretsReset() { + let coordinator = SecretsResetCoordinator(session: self.session, isCancellable: false) + coordinator.delegate = self + coordinator.start() + + self.add(childCoordinator: coordinator) + self.navigationRouter.push(coordinator.toPresentable(), animated: true, popCompletion: { [weak self] in + self?.remove(childCoordinator: coordinator) + }) + } + private func showSecretsRecovery(with recoveryMode: SecretsRecoveryMode) { let coordinator = SecretsRecoveryCoordinator(session: self.session, recoveryMode: recoveryMode, recoveryGoal: .verifyDevice, navigationRouter: self.navigationRouter, cancellable: self.cancellable) coordinator.delegate = self @@ -436,9 +447,13 @@ extension KeyVerificationCoordinator: KeyVerificationSelfVerifyWaitCoordinatorDe self.didCancel() } - func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode) { + func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode) { self.showSecretsRecovery(with: secretsRecoveryMode) } + + func keyVerificationSelfVerifyWaitCoordinatorWantsToResetSecrets(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType) { + self.showSecretsReset() + } } // MARK: - KeyVerificationScanConfirmationCoordinatorDelegate @@ -466,3 +481,15 @@ extension KeyVerificationCoordinator: SecretsRecoveryCoordinatorDelegate { self.didCancel() } } + +// MARK: - SecretsResetCoordinatorDelegate +extension KeyVerificationCoordinator: SecretsResetCoordinatorDelegate { + + func secretsResetCoordinatorDidResetSecrets(_ coordinator: SecretsResetCoordinatorType) { + self.showVerified(animated: true) + } + + func secretsResetCoordinatorDidCancel(_ coordinator: SecretsResetCoordinatorType) { + // Not used, the cancel button is hidden. + } +} diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift index 68dcab40e7..cc005d0f32 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinator.swift @@ -76,4 +76,8 @@ extension KeyVerificationSelfVerifyWaitCoordinator: KeyVerificationSelfVerifyWai func keyVerificationSelfVerifyWaitViewModel(_ coordinator: KeyVerificationSelfVerifyWaitViewModelType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode) { self.delegate?.keyVerificationSelfVerifyWaitCoordinator(self, wantsToRecoverSecretsWith: secretsRecoveryMode) } + + func keyVerificationSelfVerifyWaitViewModelWantsToResetSecrets(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType) { + self.delegate?.keyVerificationSelfVerifyWaitCoordinatorWantsToResetSecrets(self) + } } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift index 8724493ea2..1a27be1d2a 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift @@ -23,6 +23,7 @@ protocol KeyVerificationSelfVerifyWaitCoordinatorDelegate: AnyObject { func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, didAcceptIncomingSASTransaction incomingSASTransaction: MXSASTransaction) func keyVerificationSelfVerifyWaitCoordinatorDidCancel(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType) func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode) + func keyVerificationSelfVerifyWaitCoordinatorWantsToResetSecrets(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType) } /// `KeyVerificationSelfVerifyWaitCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow. diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewAction.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewAction.swift index 77d80ab707..522d8294ab 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewAction.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewAction.swift @@ -23,4 +23,5 @@ enum KeyVerificationSelfVerifyWaitViewAction { case loadData case cancel case recoverSecrets + case resetSecrets } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard index 0dcf70679f..a031902b69 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.storyboard @@ -1,9 +1,9 @@ - + - + @@ -17,13 +17,13 @@ - + - + - + diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift index 91d3920ba5..c14df526ed 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewController.swift @@ -43,6 +43,9 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { @IBOutlet private weak var recoverSecretsButton: RoundedButton! @IBOutlet private weak var recoverSecretsAdditionalInformationLabel: UILabel! + @IBOutlet private weak var resetSecretsContainerView: UIView! + @IBOutlet private weak var resetSecretsButton: UIButton! + // MARK: Private private var viewModel: KeyVerificationSelfVerifyWaitViewModelType! @@ -101,6 +104,13 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.mobileClientImageView.tintColor = theme.tintColor self.recoverSecretsAvailabilityLoadingLabel.textColor = theme.textSecondaryColor self.recoverSecretsAvailabilityActivityIndicatorView.color = theme.tintColor + + // Reset secrets button + let resetSecretsAttributedString = NSMutableAttributedString(string: VectorL10n.secretsRecoveryResetActionPart1, + attributes: [.foregroundColor: self.theme.textPrimaryColor]) + resetSecretsAttributedString.append(NSAttributedString(string: VectorL10n.secretsRecoveryResetActionPart2, + attributes: [.foregroundColor: self.theme.warningColor])) + self.resetSecretsButton.setAttributedTitle(resetSecretsAttributedString, for: .normal) } private func registerThemeServiceDidChangeThemeNotification() { @@ -121,6 +131,9 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.navigationItem.rightBarButtonItem = cancelBarButtonItem self.cancelBarButtonItem = cancelBarButtonItem + + self.resetSecretsButton.vc_enableMultiLinesTitle() + self.resetSecretsButton.isHidden = !RiotSettings.shared.secretsRecoveryAllowReset } self.titleLabel.text = VectorL10n.deviceVerificationSelfVerifyOpenOnOtherDeviceTitle(AppInfo.current.displayName) @@ -158,22 +171,26 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.recoverSecretsAvailabilityActivityIndicatorView.startAnimating() self.recoverSecretsAvailabilityLoadingContainerView.isHidden = false self.recoverSecretsContainerView.isHidden = true + self.resetSecretsContainerView.isHidden = true } private func renderLoaded(viewData: KeyVerificationSelfVerifyWaitViewData) { self.activityPresenter.removeCurrentActivityIndicator(animated: true) self.cancelBarButtonItem?.title = viewData.isNewSignIn ? VectorL10n.skip : VectorL10n.cancel - + let hideRecoverSecrets: Bool + let hideResetSecrets: Bool let recoverSecretsButtonTitle: String? switch viewData.secretsRecoveryAvailability { case .notAvailable: hideRecoverSecrets = true + hideResetSecrets = false recoverSecretsButtonTitle = nil case .available(let secretsRecoveryMode): hideRecoverSecrets = false + hideResetSecrets = true switch secretsRecoveryMode { case .passphraseOrKey: @@ -187,6 +204,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { self.recoverSecretsAvailabilityActivityIndicatorView.stopAnimating() self.recoverSecretsContainerView.isHidden = hideRecoverSecrets self.recoverSecretsButton.setTitle(recoverSecretsButtonTitle, for: .normal) + + self.resetSecretsContainerView.isHidden = hideResetSecrets } private func renderCancelled(reason: MXTransactionCancelCode) { @@ -223,6 +242,10 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController { @IBAction private func recoverSecretsButtonAction(_ sender: Any) { self.viewModel.process(viewAction: .recoverSecrets) } + + @IBAction private func resetSecretsButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .resetSecrets) + } } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift index 2f1b8a2ce0..a09529cb6b 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModel.swift @@ -80,6 +80,8 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai case .available(let secretsRecoveryMode): self.coordinatorDelegate?.keyVerificationSelfVerifyWaitViewModel(self, wantsToRecoverSecretsWith: secretsRecoveryMode) } + case .resetSecrets: + self.coordinatorDelegate?.keyVerificationSelfVerifyWaitViewModelWantsToResetSecrets(self) } } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift index 66027c9e87..11b63f24ac 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift @@ -27,6 +27,7 @@ protocol KeyVerificationSelfVerifyWaitViewModelCoordinatorDelegate: AnyObject { func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, didAcceptIncomingSASTransaction incomingSASTransaction: MXSASTransaction) func keyVerificationSelfVerifyWaitViewModelDidCancel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType) func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, wantsToRecoverSecretsWith secretsRecoveryMode: SecretsRecoveryMode) + func keyVerificationSelfVerifyWaitViewModelWantsToResetSecrets(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType) } /// Protocol describing the view model used by `KeyVerificationSelfVerifyWaitViewController` diff --git a/Riot/Modules/Reauthentication/ReauthenticationCoordinator.swift b/Riot/Modules/Reauthentication/ReauthenticationCoordinator.swift index 14c7887c30..35c9676b51 100644 --- a/Riot/Modules/Reauthentication/ReauthenticationCoordinator.swift +++ b/Riot/Modules/Reauthentication/ReauthenticationCoordinator.swift @@ -38,6 +38,8 @@ final class ReauthenticationCoordinator: ReauthenticationCoordinatorType { private var authenticationSession: SSOAuthentificationSessionProtocol? + private weak var presentedNavigationController: UINavigationController? + private var presentingViewController: UIViewController { return self.parameters.presenter.toPresentable() } @@ -58,7 +60,7 @@ final class ReauthenticationCoordinator: ReauthenticationCoordinatorType { self.userInteractiveAuthenticationService = UserInteractiveAuthenticationService(session: parameters.session) self.authenticationParametersBuilder = AuthenticationParametersBuilder() self.uiaViewControllerFactory = UserInteractiveAuthenticationViewControllerFactory() - } + } // MARK: - Public methods @@ -143,28 +145,34 @@ final class ReauthenticationCoordinator: ReauthenticationCoordinatorType { reauthFallbackViewController.title = self.parameters.title reauthFallbackViewController.didCancel = { [weak self] in - guard let self = self else { - return - } + guard let self = self else { return } + + self.dismissFallbackAuthentication() self.delegate?.reauthenticationCoordinatorDidCancel(self) } reauthFallbackViewController.didValidate = { [weak self] in - guard let self = self else { - return - } + guard let self = self else { return } guard let sessionId = authenticationSession.session else { + self.dismissFallbackAuthentication() self.delegate?.reauthenticationCoordinator(self, didFailWithError: ReauthenticationCoordinatorError.failToBuildPasswordParameters) return } let authenticationParameters = self.authenticationParametersBuilder.buildOAuthParameters(with: sessionId) + self.dismissFallbackAuthentication() self.delegate?.reauthenticationCoordinatorDidComplete(self, withAuthenticationParameters: authenticationParameters) } let navigationController = RiotNavigationController(rootViewController: reauthFallbackViewController) + self.presentedNavigationController = navigationController self.presentingViewController.present(navigationController, animated: true) } + + private func dismissFallbackAuthentication() { + presentedNavigationController?.dismiss(animated: true) + presentedNavigationController = nil + } } diff --git a/Riot/Modules/Reauthentication/ReauthenticationCoordinatorBridgePresenter.swift b/Riot/Modules/Reauthentication/ReauthenticationCoordinatorBridgePresenter.swift index 79bd562dc6..32497d019f 100644 --- a/Riot/Modules/Reauthentication/ReauthenticationCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Reauthentication/ReauthenticationCoordinatorBridgePresenter.swift @@ -37,6 +37,9 @@ final class ReauthenticationCoordinatorBridgePresenter: NSObject { // MARK: Private private var coordinator: ReauthenticationCoordinator? + /// Re-authentication dismisses itself automatically, so make sure that the dismiss function + /// only takes effect when dismissing an ongoing re-authentication rather than a completed one. + private var hasDismissed: Bool = false // MARK: Public @@ -55,6 +58,7 @@ final class ReauthenticationCoordinatorBridgePresenter: NSObject { self.didComplete = success self.didCancel = cancel self.didFail = failure + self.hasDismissed = false let coordinator = ReauthenticationCoordinator(parameters: parameters) coordinator.delegate = self @@ -69,12 +73,16 @@ final class ReauthenticationCoordinatorBridgePresenter: NSObject { guard let coordinator = self.coordinator else { return } + + guard !hasDismissed else { + self.coordinator = nil + completion?() + return + } + coordinator.toPresentable().dismiss(animated: animated) { self.coordinator = nil - - if let completion = completion { - completion() - } + completion?() } } @@ -90,14 +98,17 @@ final class ReauthenticationCoordinatorBridgePresenter: NSObject { // MARK: - ReauthenticationCoordinatorDelegate extension ReauthenticationCoordinatorBridgePresenter: ReauthenticationCoordinatorDelegate { func reauthenticationCoordinatorDidComplete(_ coordinator: ReauthenticationCoordinatorType, withAuthenticationParameters authenticationParameters: [String: Any]?) { + self.hasDismissed = true self.didComplete?(authenticationParameters) } func reauthenticationCoordinatorDidCancel(_ coordinator: ReauthenticationCoordinatorType) { + self.hasDismissed = true self.didCancel?() } func reauthenticationCoordinator(_ coordinator: ReauthenticationCoordinatorType, didFailWithError error: Error) { + self.hasDismissed = true self.didFail?(error) } } diff --git a/Riot/Modules/Secrets/Reset/SecretsResetCoordinator.swift b/Riot/Modules/Secrets/Reset/SecretsResetCoordinator.swift index bd9740ad59..213b010299 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetCoordinator.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetCoordinator.swift @@ -38,11 +38,11 @@ final class SecretsResetCoordinator: SecretsResetCoordinatorType { // MARK: - Setup - init(session: MXSession) { + init(session: MXSession, isCancellable: Bool = true) { self.session = session let secretsResetViewModel = SecretsResetViewModel(session: self.session) - let secretsResetViewController = SecretsResetViewController.instantiate(with: secretsResetViewModel) + let secretsResetViewController = SecretsResetViewController.instantiate(with: secretsResetViewModel, isCancellable: isCancellable) self.secretsResetViewModel = secretsResetViewModel self.secretsResetViewController = secretsResetViewController } @@ -59,13 +59,13 @@ final class SecretsResetCoordinator: SecretsResetCoordinatorType { // MARK: - Private - private func showAuthentication(with request: AuthenticatedEndpointRequest) { + private func showReauthentication(for session: MXAuthenticationSession) { let reauthenticationCoordinatorParameters = ReauthenticationCoordinatorParameters(session: self.session, presenter: self.toPresentable(), title: nil, message: VectorL10n.secretsResetAuthenticationMessage, - authenticatedEndpointRequest: request) + authenticationSession: session) let coordinator = ReauthenticationCoordinator(parameters: reauthenticationCoordinatorParameters) coordinator.delegate = self @@ -77,8 +77,8 @@ final class SecretsResetCoordinator: SecretsResetCoordinatorType { // MARK: - SecretsResetViewModelCoordinatorDelegate extension SecretsResetCoordinator: SecretsResetViewModelCoordinatorDelegate { - func secretsResetViewModel(_ viewModel: SecretsResetViewModelType, needsToAuthenticateWith request: AuthenticatedEndpointRequest) { - self.showAuthentication(with: request) + func secretsResetViewModel(_ viewModel: SecretsResetViewModelType, needsToAuthenticateFor session: MXAuthenticationSession) { + self.showReauthentication(for: session) } func secretsResetViewModelDidResetSecrets(_ viewModel: SecretsResetViewModelType) { diff --git a/Riot/Modules/Secrets/Reset/SecretsResetViewController.swift b/Riot/Modules/Secrets/Reset/SecretsResetViewController.swift index fccbfb6e35..2d961d0581 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetViewController.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetViewController.swift @@ -40,15 +40,17 @@ final class SecretsResetViewController: UIViewController { // MARK: Private private var viewModel: SecretsResetViewModelType! + private var isCancellable = true private var theme: Theme! private var errorPresenter: MXKErrorPresentation! private var activityPresenter: ActivityIndicatorPresenter! // MARK: - Setup - class func instantiate(with viewModel: SecretsResetViewModelType) -> SecretsResetViewController { + class func instantiate(with viewModel: SecretsResetViewModelType, isCancellable: Bool = true) -> SecretsResetViewController { let viewController = StoryboardScene.SecretsResetViewController.initialScene.instantiate() viewController.viewModel = viewModel + viewController.isCancellable = isCancellable viewController.theme = ThemeService.shared().theme return viewController } @@ -108,12 +110,13 @@ final class SecretsResetViewController: UIViewController { } private func setupViews() { - let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in - self?.cancelButtonAction() + if isCancellable { + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.cancelButtonAction() + } + self.navigationItem.rightBarButtonItem = cancelBarButtonItem } - self.navigationItem.rightBarButtonItem = cancelBarButtonItem - self.title = VectorL10n.secretsResetTitle self.scrollView.keyboardDismissMode = .interactive diff --git a/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift b/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift index 62b0c686fb..b26763bddc 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetViewModel.swift @@ -48,11 +48,11 @@ final class SecretsResetViewModel: SecretsResetViewModelType { case .loadData: break case .reset: - self.askAuthentication() + self.resetSecrets() case .authenticationCancelled: self.authenticationCancelled() case .authenticationInfoEntered(let authParameters): - self.resetSecrets(with: authParameters) + self.resetSecrets(with: authParameters, hasAuthenticated: true) case .cancel: self.coordinatorDelegate?.secretsResetViewModelDidCancel(self) } @@ -64,43 +64,42 @@ final class SecretsResetViewModel: SecretsResetViewModelType { self.viewDelegate?.secretsResetViewModel(self, didUpdateViewState: viewState) } - private func resetSecrets(with authParameters: [String: Any]) { - guard let crossSigning = self.session.crypto?.crossSigning else { - return - } + private func resetSecrets(with authParameters: [String: Any] = [:], hasAuthenticated: Bool = false) { + guard let crossSigning = self.session.crypto?.crossSigning else { return } + MXLog.debug("[SecretsResetViewModel] resetSecrets") + self.update(viewState: .resetting) - crossSigning.setup(withAuthParams: authParameters, success: { [weak self] in - guard let self = self else { - return - } - self.recoveryService.deleteRecovery(withDeleteServicesBackups: true, success: { [weak self] in - guard let self = self else { - return - } + crossSigning.setup(withAuthParams: authParameters) { [weak self] in + guard let self else { return } + + self.recoveryService.deleteRecovery(withDeleteServicesBackups: true) { [weak self] in + guard let self else { return } + self.update(viewState: .resetDone) self.coordinatorDelegate?.secretsResetViewModelDidResetSecrets(self) - }, failure: { [weak self] error in - guard let self = self else { - return - } + } failure: { [weak self] error in + guard let self else { return } self.update(viewState: .error(error)) - }) + } - }, failure: { [weak self] error in - guard let self = self else { - return + } failure: { [weak self] error in + guard let self else { return } + + if let responseData = (error as NSError).userInfo[MXHTTPClientErrorResponseDataKey] as? [AnyHashable: Any], + let authenticationSession = MXAuthenticationSession(fromJSON: responseData), + !hasAuthenticated { // Don't re-presenting authentication if the user closes the web view without finishing. + askAuthentication(session: authenticationSession) + } else { + self.update(viewState: .error(error)) } - self.update(viewState: .error(error)) - }) + } } - private func askAuthentication() { - self.update(viewState: .resetting) - + private func askAuthentication(session: MXAuthenticationSession) { let setupCrossSigningRequest = self.crossSigningService.setupCrossSigningRequest() - self.coordinatorDelegate?.secretsResetViewModel(self, needsToAuthenticateWith: setupCrossSigningRequest) + self.coordinatorDelegate?.secretsResetViewModel(self, needsToAuthenticateFor: session) } private func authenticationCancelled() { diff --git a/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift b/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift index 5a5c880775..8ae7d36474 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift @@ -23,7 +23,7 @@ protocol SecretsResetViewModelViewDelegate: AnyObject { } protocol SecretsResetViewModelCoordinatorDelegate: AnyObject { - func secretsResetViewModel(_ viewModel: SecretsResetViewModelType, needsToAuthenticateWith request: AuthenticatedEndpointRequest) + func secretsResetViewModel(_ viewModel: SecretsResetViewModelType, needsToAuthenticateFor session: MXAuthenticationSession) func secretsResetViewModelDidResetSecrets(_ viewModel: SecretsResetViewModelType) func secretsResetViewModelDidCancel(_ viewModel: SecretsResetViewModelType) } diff --git a/changelog.d/8024.bugfix b/changelog.d/8024.bugfix new file mode 100644 index 0000000000..a2ffc3201d --- /dev/null +++ b/changelog.d/8024.bugfix @@ -0,0 +1 @@ +Hook up the Reset flow to Verification when there is no recovery or other devices. \ No newline at end of file