Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a SignOutFlowPresenter. #6854

Merged
merged 4 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 13 additions & 107 deletions Riot/Modules/Home/AllChats/AllChatsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
}

private var indicators = [UserIndicator]()
private var signOutAlertPresenter = SignOutAlertPresenter()
private var signOutFlowPresenter: SignOutFlowPresenter?

// MARK: Public

Expand Down Expand Up @@ -107,8 +107,6 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {

// If start has been done once do not setup view controllers again
if self.hasStartedOnce == false {
signOutAlertPresenter.delegate = self

let allChatsViewController = AllChatsViewController.instantiate()
allChatsViewController.allChatsDelegate = self
allChatsViewController.userIndicatorStore = UserIndicatorStore(presenter: indicatorPresenter)
Expand Down Expand Up @@ -580,87 +578,16 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
// MARK: Sign out process

private func signOut() {
guard let keyBackup = currentMatrixSession?.crypto.backup else {
return
}

signOutAlertPresenter.present(for: keyBackup.state,
areThereKeysToBackup: keyBackup.hasKeysToBackup,
from: self.allChatsViewController,
sourceView: avatarMenuButton,
animated: true)
}

// MARK: - SecureBackupSetupCoordinatorBridgePresenter

private var secureBackupSetupCoordinatorBridgePresenter: SecureBackupSetupCoordinatorBridgePresenter?
private var crossSigningSetupCoordinatorBridgePresenter: CrossSigningSetupCoordinatorBridgePresenter?

private func showSecureBackupSetupFromSignOutFlow() {
if canSetupSecureBackup {
setupSecureBackup2()
} else {
// Set up cross-signing first
setupCrossSigning(title: VectorL10n.secureKeyBackupSetupIntroTitle,
message: VectorL10n.securitySettingsUserPasswordDescription) { [weak self] result in
switch result {
case .success(let isCompleted):
if isCompleted {
self?.setupSecureBackup2()
}
case .failure:
break
}
}
}
}

private var canSetupSecureBackup: Bool {
return currentMatrixSession?.vc_canSetupSecureBackup() ?? false
}

private func setupSecureBackup2() {
guard let session = currentMatrixSession else {
return
}

let secureBackupSetupCoordinatorBridgePresenter = SecureBackupSetupCoordinatorBridgePresenter(session: session, allowOverwrite: true)
secureBackupSetupCoordinatorBridgePresenter.delegate = self
secureBackupSetupCoordinatorBridgePresenter.present(from: allChatsViewController, animated: true)
self.secureBackupSetupCoordinatorBridgePresenter = secureBackupSetupCoordinatorBridgePresenter
}

private func setupCrossSigning(title: String, message: String, completion: @escaping (Result<Bool, Error>) -> Void) {
guard let session = currentMatrixSession else {
MXLog.warning("[AllChatsCoordinator] Unable to sign out due to missing current session.")
return
}

allChatsViewController.startActivityIndicator()
allChatsViewController.view.isUserInteractionEnabled = false

let dismissAnimation = { [weak self] in
guard let self = self else { return }

self.allChatsViewController.stopActivityIndicator()
self.allChatsViewController.view.isUserInteractionEnabled = true
self.crossSigningSetupCoordinatorBridgePresenter?.dismiss(animated: true, completion: {
self.crossSigningSetupCoordinatorBridgePresenter = nil
})
}
let flowPresenter = SignOutFlowPresenter(session: session, presentingViewController: toPresentable())
flowPresenter.delegate = self

let crossSigningSetupCoordinatorBridgePresenter = CrossSigningSetupCoordinatorBridgePresenter(session: session)
crossSigningSetupCoordinatorBridgePresenter.present(with: title, message: message, from: allChatsViewController, animated: true) {
dismissAnimation()
completion(.success(true))
} cancel: {
dismissAnimation()
completion(.success(false))
} failure: { error in
dismissAnimation()
completion(.failure(error))
}

self.crossSigningSetupCoordinatorBridgePresenter = crossSigningSetupCoordinatorBridgePresenter
flowPresenter.start(sourceView: avatarMenuButton)
self.signOutFlowPresenter = flowPresenter
}

// MARK: - Private methods
Expand Down Expand Up @@ -720,42 +647,21 @@ class AllChatsCoordinator: NSObject, SplitViewMasterCoordinatorProtocol {
viewController.loadViewIfNeeded()
return viewController
}

}

// MARK: - SignOutAlertPresenterDelegate
extension AllChatsCoordinator: SignOutAlertPresenterDelegate {

func signOutAlertPresenterDidTapSignOutAction(_ presenter: SignOutAlertPresenter) {
// Prevent user to perform user interaction in settings when sign out
// TODO: Prevent user interaction in all application (navigation controller and split view controller included)
extension AllChatsCoordinator: SignOutFlowPresenterDelegate {
func signOutFlowPresenterDidStartLoading(_ presenter: SignOutFlowPresenter) {
allChatsViewController.view.isUserInteractionEnabled = false
allChatsViewController.startActivityIndicator()

AppDelegate.theDelegate().logout(withConfirmation: false) { [weak self] isLoggedOut in
self?.allChatsViewController.stopActivityIndicator()
self?.allChatsViewController.view.isUserInteractionEnabled = true
}
}

func signOutAlertPresenterDidTapBackupAction(_ presenter: SignOutAlertPresenter) {
showSecureBackupSetupFromSignOutFlow()
}

}

// MARK: - SecureBackupSetupCoordinatorBridgePresenterDelegate
extension AllChatsCoordinator: SecureBackupSetupCoordinatorBridgePresenterDelegate {
func secureBackupSetupCoordinatorBridgePresenterDelegateDidCancel(_ coordinatorBridgePresenter: SecureBackupSetupCoordinatorBridgePresenter) {
coordinatorBridgePresenter.dismiss(animated: true) {
self.secureBackupSetupCoordinatorBridgePresenter = nil
}
func signOutFlowPresenterDidStopLoading(_ presenter: SignOutFlowPresenter) {
allChatsViewController.view.isUserInteractionEnabled = true
allChatsViewController.stopActivityIndicator()
}

func secureBackupSetupCoordinatorBridgePresenterDelegateDidComplete(_ coordinatorBridgePresenter: SecureBackupSetupCoordinatorBridgePresenter) {
coordinatorBridgePresenter.dismiss(animated: true) {
self.secureBackupSetupCoordinatorBridgePresenter = nil
}
func signOutFlowPresenter(_ presenter: SignOutFlowPresenter, didFailWith error: Error) {
AppDelegate.theDelegate().showError(asAlert: error)
}
}

Expand Down
145 changes: 18 additions & 127 deletions Riot/Modules/Settings/SettingsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,7 @@ typedef NS_ENUM(NSUInteger, SECURITY)

@interface SettingsViewController () <UITextFieldDelegate, MXKCountryPickerViewControllerDelegate, MXKLanguagePickerViewControllerDelegate, DeactivateAccountViewControllerDelegate,
NotificationSettingsCoordinatorBridgePresenterDelegate,
SecureBackupSetupCoordinatorBridgePresenterDelegate,
SignOutAlertPresenterDelegate,
SignOutFlowPresenterDelegate,
SingleImagePickerPresenterDelegate,
SettingsDiscoveryTableViewSectionDelegate, SettingsDiscoveryViewModelCoordinatorDelegate,
SettingsIdentityServerCoordinatorBridgePresenterDelegate,
Expand Down Expand Up @@ -267,20 +266,16 @@ @interface SettingsViewController () <UITextFieldDelegate, MXKCountryPickerViewC

@property (nonatomic, strong) NotificationSettingsCoordinatorBridgePresenter *notificationSettingsBridgePresenter;

@property (nonatomic, strong) SignOutAlertPresenter *signOutAlertPresenter;
@property (nonatomic, strong) SignOutFlowPresenter *signOutFlowPresenter;
@property (nonatomic, weak) UIButton *signOutButton;
@property (nonatomic, strong) SingleImagePickerPresenter *imagePickerPresenter;

@property (nonatomic, strong) SettingsDiscoveryViewModel *settingsDiscoveryViewModel;
@property (nonatomic, strong) SettingsDiscoveryTableViewSection *settingsDiscoveryTableViewSection;
@property (nonatomic, strong) SettingsDiscoveryThreePidDetailsCoordinatorBridgePresenter *discoveryThreePidDetailsPresenter;

@property (nonatomic, strong) SecureBackupSetupCoordinatorBridgePresenter *secureBackupSetupCoordinatorBridgePresenter;

@property (nonatomic, strong) TableViewSections *tableViewSections;

@property (nonatomic, strong) CrossSigningSetupCoordinatorBridgePresenter *crossSigningSetupCoordinatorBridgePresenter;

@property (nonatomic, strong) ReauthenticationCoordinatorBridgePresenter *reauthenticationCoordinatorBridgePresenter;

@property (nonatomic, strong) UserInteractiveAuthenticationService *userInteractiveAuthenticationService;
Expand Down Expand Up @@ -701,9 +696,6 @@ - (void)viewDidLoad
}];
[self userInterfaceThemeDidChange];

self.signOutAlertPresenter = [SignOutAlertPresenter new];
self.signOutAlertPresenter.delegate = self;

_tableViewSections = [TableViewSections new];
_tableViewSections.delegate = self;
[self updateSections];
Expand Down Expand Up @@ -770,8 +762,7 @@ - (void)destroy

[super destroy];
}

_secureBackupSetupCoordinatorBridgePresenter = nil;

identityServerSettingsCoordinatorBridgePresenter = nil;
}

Expand Down Expand Up @@ -2964,13 +2955,11 @@ - (void)onSignout:(id)sender
{
self.signOutButton = (UIButton*)sender;

MXKeyBackup *keyBackup = self.mainSession.crypto.backup;
SignOutFlowPresenter *flowPresenter = [[SignOutFlowPresenter alloc] initWithSession:self.mainSession presentingViewController:self];
flowPresenter.delegate = self;

[self.signOutAlertPresenter presentFor:keyBackup.state
areThereKeysToBackup:keyBackup.hasKeysToBackup
from:self
sourceView:self.signOutButton
animated:YES];
[flowPresenter startWithSourceView:self.signOutButton];
self.signOutFlowPresenter = flowPresenter;
}

- (void)onRemove3PID:(NSIndexPath*)indexPath
Expand Down Expand Up @@ -4181,123 +4170,25 @@ - (void)notificationSettingsCoordinatorBridgePresenterDelegateDidComplete:(Notif
self.notificationSettingsBridgePresenter = nil;
}

#pragma mark - SignOutFlowPresenterDelegate

#pragma mark - SecureBackupSetupCoordinatorBridgePresenter

- (void)showSecureBackupSetupFromSignOutFlow
{
if (self.canSetupSecureBackup)
{
[self setupSecureBackup2];
}
else
{
// Set up cross-signing first
[self setupCrossSigningWithTitle:[VectorL10n secureKeyBackupSetupIntroTitle]
message:[VectorL10n securitySettingsUserPasswordDescription]
success:^{
[self setupSecureBackup2];
} failure:^(NSError *error) {
}];
}
}

- (void)setupSecureBackup2
{
SecureBackupSetupCoordinatorBridgePresenter *secureBackupSetupCoordinatorBridgePresenter = [[SecureBackupSetupCoordinatorBridgePresenter alloc] initWithSession:self.mainSession allowOverwrite:YES];
secureBackupSetupCoordinatorBridgePresenter.delegate = self;

[secureBackupSetupCoordinatorBridgePresenter presentFrom:self animated:YES];

self.secureBackupSetupCoordinatorBridgePresenter = secureBackupSetupCoordinatorBridgePresenter;
}

- (BOOL)canSetupSecureBackup
{
return [self.mainSession vc_canSetupSecureBackup];
}

#pragma mark - SecureBackupSetupCoordinatorBridgePresenterDelegate

- (void)secureBackupSetupCoordinatorBridgePresenterDelegateDidComplete:(SecureBackupSetupCoordinatorBridgePresenter *)coordinatorBridgePresenter
{
[self.secureBackupSetupCoordinatorBridgePresenter dismissWithAnimated:YES completion:nil];
self.secureBackupSetupCoordinatorBridgePresenter = nil;
}

- (void)secureBackupSetupCoordinatorBridgePresenterDelegateDidCancel:(SecureBackupSetupCoordinatorBridgePresenter *)coordinatorBridgePresenter
{
[self.secureBackupSetupCoordinatorBridgePresenter dismissWithAnimated:YES completion:nil];
self.secureBackupSetupCoordinatorBridgePresenter = nil;
}

#pragma mark - SignOutAlertPresenterDelegate

- (void)signOutAlertPresenterDidTapBackupAction:(SignOutAlertPresenter * _Nonnull)presenter
{
[self showSecureBackupSetupFromSignOutFlow];
}

- (void)signOutAlertPresenterDidTapSignOutAction:(SignOutAlertPresenter * _Nonnull)presenter
- (void)signOutFlowPresenterDidStartLoading:(SignOutFlowPresenter *)presenter
{
// Prevent user to perform user interaction in settings when sign out
// TODO: Prevent user interaction in all application (navigation controller and split view controller included)
[self startActivityIndicator];
self.view.userInteractionEnabled = NO;
self.signOutButton.enabled = NO;

[self startActivityIndicator];

MXWeakify(self);

[[AppDelegate theDelegate] logoutWithConfirmation:NO completion:^(BOOL isLoggedOut) {
MXStrongifyAndReturnIfNil(self);

[self stopActivityIndicator];

self.view.userInteractionEnabled = YES;
self.signOutButton.enabled = YES;
}];
}

- (void)setupCrossSigningWithTitle:(NSString*)title
message:(NSString*)message
success:(void (^)(void))success
failure:(void (^)(NSError *error))failure
- (void)signOutFlowPresenterDidStopLoading:(SignOutFlowPresenter *)presenter
{
[self stopActivityIndicator];
self.view.userInteractionEnabled = YES;
self.signOutButton.enabled = YES;
}

- (void)signOutFlowPresenter:(SignOutFlowPresenter *)presenter didFailWith:(NSError *)error
{
[self startActivityIndicator];
self.view.userInteractionEnabled = NO;

MXWeakify(self);

void (^animationCompletion)(void) = ^void () {
MXStrongifyAndReturnIfNil(self);

[self stopActivityIndicator];
self.view.userInteractionEnabled = YES;
[self.crossSigningSetupCoordinatorBridgePresenter dismissWithAnimated:YES completion:^{}];
self.crossSigningSetupCoordinatorBridgePresenter = nil;
};

CrossSigningSetupCoordinatorBridgePresenter *crossSigningSetupCoordinatorBridgePresenter = [[CrossSigningSetupCoordinatorBridgePresenter alloc] initWithSession:self.mainSession];

[crossSigningSetupCoordinatorBridgePresenter presentWith:title
message:message
from:self
animated:YES
success:^{
animationCompletion();
success();
} cancel:^{
animationCompletion();
failure(nil);
} failure:^(NSError * _Nonnull error) {
animationCompletion();
[[AppDelegate theDelegate] showErrorAsAlert:error];
failure(error);
}];

self.crossSigningSetupCoordinatorBridgePresenter = crossSigningSetupCoordinatorBridgePresenter;
[[AppDelegate theDelegate] showErrorAsAlert:error];
}

#pragma mark - SingleImagePickerPresenterDelegate
Expand Down
Loading