From d19cf861a02295c67412fc54cbcc1cb3228c0a6b Mon Sep 17 00:00:00 2001 From: giomfo Date: Fri, 13 Apr 2018 20:14:44 +0200 Subject: [PATCH 1/4] Bug Fix - Crash on URL like https://riot.im/#/app/register?hs_url=... Fix here the crash Another commit will be done to prevent logging out on unexpected register url https://github.com/vector-im/riot-ios/issues/1838 --- Riot/AppDelegate.m | 20 +++++++++++--------- Riot/ViewController/SettingsViewController.m | 5 +++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index f8a79e326..3069cccd0 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -2587,15 +2587,17 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN #endif // Logout all matrix account - [[MXKAccountManager sharedManager] logout]; - - // Return to authentication screen - [_masterTabBarController showAuthenticationScreen]; - - // Note: Keep App settings - - // Reset the contact manager - [[MXKContactManager sharedManager] reset]; + [[MXKAccountManager sharedManager] logoutWithCompletion:^{ + + // Return to authentication screen + [_masterTabBarController showAuthenticationScreen]; + + // Note: Keep App settings + + // Reset the contact manager + [[MXKContactManager sharedManager] reset]; + + }]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context diff --git a/Riot/ViewController/SettingsViewController.m b/Riot/ViewController/SettingsViewController.m index d196e052d..4ae577344 100644 --- a/Riot/ViewController/SettingsViewController.m +++ b/Riot/ViewController/SettingsViewController.m @@ -1,6 +1,7 @@ /* Copyright 2015 OpenMarket Ltd Copyright 2017 Vector Creations Ltd + Copyright 2018 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -2606,7 +2607,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [[MXKAccountManager sharedManager] logout]; + [[MXKAccountManager sharedManager] logoutWithCompletion:nil]; }); } @@ -2930,7 +2931,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [[MXKAccountManager sharedManager] logout]; + [[MXKAccountManager sharedManager] logoutWithCompletion:nil]; }); } From 4d7de4625ad2157081b5b1f4f70ec1ee216f04b7 Mon Sep 17 00:00:00 2001 From: giomfo Date: Fri, 13 Apr 2018 23:33:53 +0200 Subject: [PATCH 2/4] Bug Fix - Crash on URL like https://riot.im/#/app/register?hs_url=... Ignore register link without session id. vector-im/riot-ios#1838 --- Riot/AppDelegate.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 3069cccd0..c3b026df9 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -2084,7 +2084,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN }]; } } - else if ([pathParams[0] isEqualToString:@"register"]) + // Check whether a session id is provided to finalize a registration, ignore links without session id. + else if ([pathParams[0] isEqualToString:@"register"] && queryParams[@"session_id"]) { NSLog(@"[AppDelegate] Universal link with registration parameters"); continueUserActivity = YES; From bcf3bd9957f9c31c72280aac746e1cf94d1cd2f1 Mon Sep 17 00:00:00 2001 From: giomfo Date: Tue, 17 Apr 2018 21:39:31 +0200 Subject: [PATCH 3/4] Bug Fix - Crash on URL like https://riot.im/#/app/register?hs_url=... Prompt the user before logging out in case of click on register link. vector-im/riot-ios#1838 --- Riot/AppDelegate.h | 9 ++- Riot/AppDelegate.m | 85 ++++++++++++++++++-- Riot/ViewController/MasterTabBarController.m | 12 ++- Riot/ViewController/SettingsViewController.m | 73 ++++------------- 4 files changed, 114 insertions(+), 65 deletions(-) diff --git a/Riot/AppDelegate.h b/Riot/AppDelegate.h index c50209be9..69ae2addd 100644 --- a/Riot/AppDelegate.h +++ b/Riot/AppDelegate.h @@ -101,7 +101,14 @@ extern NSString *const kAppDelegateNetworkStatusDidChangeNotification; // Reload all running matrix sessions - (void)reloadMatrixSessions:(BOOL)clearCache; -- (void)logout; +/** + Log out all the accounts after asking for a potential confirmation. + Show the authentication screen on successful logout. + + @param askConfirmation tell whether a confirmation is required before logging out. + @param completion the block to execute at the end of the operation. + */ +- (void)logoutWithConfirmation:(BOOL)askConfirmation completion:(void (^)(BOOL isLoggedOut))completion; #pragma mark - Matrix Accounts handling diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index c3b026df9..b69c34e84 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -208,6 +208,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN @property (strong, nonatomic) UIAlertController *mxInAppNotification; +@property (strong, nonatomic) UIAlertController *logoutConfirmation; + @property (nonatomic, nullable, copy) void (^registrationForRemoteNotificationsCompletion)(NSError *); @@ -2084,8 +2086,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN }]; } } - // Check whether a session id is provided to finalize a registration, ignore links without session id. - else if ([pathParams[0] isEqualToString:@"register"] && queryParams[@"session_id"]) + // Check whether this is a registration links. + else if ([pathParams[0] isEqualToString:@"register"]) { NSLog(@"[AppDelegate] Universal link with registration parameters"); continueUserActivity = YES; @@ -2396,7 +2398,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // Logout the app when there is no available account if (![MXKAccountManager sharedManager].accounts.count) { - [self logout]; + [self logoutWithConfirmation:NO completion:nil]; } }]; @@ -2568,8 +2570,76 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } } -- (void)logout +- (void)logoutWithConfirmation:(BOOL)askConfirmation completion:(void (^)(BOOL isLoggedOut))completion { + // Check whether we have to ask confirmation before logging out. + if (askConfirmation) + { + if (self.logoutConfirmation) + { + [self.logoutConfirmation dismissViewControllerAnimated:NO completion:nil]; + self.logoutConfirmation = nil; + } + + __weak typeof(self) weakSelf = self; + + NSString *message = NSLocalizedStringFromTable(@"settings_sign_out_confirmation", @"Vector", nil); + + // If the user has encrypted rooms, warn he will lose his e2e keys + MXSession *session = self.mxSessions.firstObject; + for (MXRoom *room in session.rooms) + { + if (room.state.isEncrypted) + { + message = [message stringByAppendingString:[NSString stringWithFormat:@"\n\n%@", NSLocalizedStringFromTable(@"settings_sign_out_e2e_warn", @"Vector", nil)]]; + break; + } + } + + // Ask confirmation + self.logoutConfirmation = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"settings_sign_out", @"Vector", nil) message:message preferredStyle:UIAlertControllerStyleAlert]; + + [self.logoutConfirmation addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_sign_out", @"Vector", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + + if (weakSelf) + { + typeof(self) self = weakSelf; + self.logoutConfirmation = nil; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + + [self logoutWithConfirmation:NO completion:completion]; + + }); + } + + }]]; + + [self.logoutConfirmation addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * action) { + + if (weakSelf) + { + typeof(self) self = weakSelf; + self.logoutConfirmation = nil; + + if (completion) + { + completion(NO); + } + } + + }]]; + + [self.logoutConfirmation mxk_setAccessibilityIdentifier: @"AppDelegateLogoutConfirmationAlert"]; + [self showNotificationAlert:self.logoutConfirmation]; + return; + } + + self.pushRegistry = nil; isPushRegistered = NO; @@ -2590,6 +2660,11 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // Logout all matrix account [[MXKAccountManager sharedManager] logoutWithCompletion:^{ + if (completion) + { + completion (YES); + } + // Return to authentication screen [_masterTabBarController showAuthenticationScreen]; @@ -2920,7 +2995,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN typeof(self) self = weakSelf; self->_errorNotification = nil; - [self logout]; + [self logoutWithConfirmation:NO completion:nil]; } }]]; diff --git a/Riot/ViewController/MasterTabBarController.m b/Riot/ViewController/MasterTabBarController.m index 38f3ba6ad..6a1a6c667 100644 --- a/Riot/ViewController/MasterTabBarController.m +++ b/Riot/ViewController/MasterTabBarController.m @@ -372,13 +372,19 @@ } else { - NSLog(@"[MasterTabBarController] Universal link: Logout current sessions and open AuthViewController to complete the registration"); + NSLog(@"[MasterTabBarController] Universal link: Prompt to logout current sessions and open AuthViewController to complete the registration"); // Keep a ref on the params authViewControllerRegistrationParameters = parameters; - // And do a logout out. It will then display AuthViewController - [[AppDelegate theDelegate] logout]; + // Prompt to logout. It will then display AuthViewController if the user is logged out. + [[AppDelegate theDelegate] logoutWithConfirmation:YES completion:^(BOOL isLoggedOut) { + if (!isLoggedOut) + { + // Reset temporary params + authViewControllerRegistrationParameters = nil; + } + }]; } } diff --git a/Riot/ViewController/SettingsViewController.m b/Riot/ViewController/SettingsViewController.m index 4ae577344..2786b6f0a 100644 --- a/Riot/ViewController/SettingsViewController.m +++ b/Riot/ViewController/SettingsViewController.m @@ -2571,63 +2571,24 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); - (void)onSignout:(id)sender { - [currentAlert dismissViewControllerAnimated:NO completion:nil]; - - __weak typeof(self) weakSelf = self; - - NSString *message = NSLocalizedStringFromTable(@"settings_sign_out_confirmation", @"Vector", nil); - - // If the user has encrypted rooms, warn he will lose his e2e keys - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; - for (MXRoom *room in session.rooms) - { - if (room.state.isEncrypted) + // Feedback: disable button and run activity indicator + UIButton *button = (UIButton*)sender; + button.enabled = NO; + [self startActivityIndicator]; + + __weak typeof(self) weakSelf = self; + + [[AppDelegate theDelegate] logoutWithConfirmation:YES completion:^(BOOL isLoggedOut) { + + if (!isLoggedOut && weakSelf) { - message = [message stringByAppendingString:[NSString stringWithFormat:@"\n\n%@", NSLocalizedStringFromTable(@"settings_sign_out_e2e_warn", @"Vector", nil)]]; - break; + typeof(self) self = weakSelf; + + // Enable the button and stop activity indicator + button.enabled = YES; + [self stopActivityIndicator]; } - } - - // Ask confirmation - currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"settings_sign_out", @"Vector", nil) message:message preferredStyle:UIAlertControllerStyleAlert]; - - [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_sign_out", @"Vector", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - // Feedback: disable button and run activity indicator - UIButton *button = (UIButton*)sender; - button.enabled = NO; - [self startActivityIndicator]; - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - - [[MXKAccountManager sharedManager] logoutWithCompletion:nil]; - - }); - } - - }]]; - - [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] - style:UIAlertActionStyleCancel - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; - - [currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCSignoutAlert"]; - [self presentViewController:currentAlert animated:YES completion:nil]; + }]; } - (void)onRemove3PID:(NSIndexPath*)path @@ -2931,7 +2892,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [[MXKAccountManager sharedManager] logoutWithCompletion:nil]; + [[AppDelegate theDelegate] logoutWithConfirmation:NO completion:nil]; }); } From 5f84015837a46d681e4f283fa6b2760fd1dc4fde Mon Sep 17 00:00:00 2001 From: giomfo Date: Tue, 17 Apr 2018 23:26:26 +0200 Subject: [PATCH 4/4] Bug Fix - Crash on URL like https://riot.im/#/app/register?hs_url=... Display an activity indicator when the logout is in progress vector-im/riot-ios#1838 --- Riot/AppDelegate.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index b69c34e84..2d06f62cb 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -2639,6 +2639,20 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN return; } + // Display a loading wheel during the logout process + id topVC; + if (_masterTabBarController && _masterTabBarController == _masterNavigationController.visibleViewController) + { + topVC = _masterTabBarController.selectedViewController; + } + else + { + topVC = _masterNavigationController.visibleViewController; + } + if (topVC && [topVC respondsToSelector:@selector(startActivityIndicator)]) + { + [topVC startActivityIndicator]; + } self.pushRegistry = nil; isPushRegistered = NO;