From 3e8b6567c1c066471ec14e8dff05942c708477f7 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 09:33:53 +0200 Subject: [PATCH 1/8] Email binding: SettingsVC: Made the user settings section rows dynamic --- .../ViewController/SettingsViewController.m | 77 +++++++++---------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index 9a5c6cba4..334f4ef34 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -33,32 +33,6 @@ #define SETTINGS_SECTION_OTHER_INDEX 3 #define SETTINGS_SECTION_COUNT 4 -/* -#define USER_SETTINGS_PROFILE_PICTURE_INDEX 0 -#define USER_SETTINGS_DISPLAY_NAME_INDEX 1 -#define USER_SETTINGS_FIRST_NAME_INDEX 2 -#define USER_SETTINGS_SURNAME_INDEX 3 -#define USER_SETTINGS_EMAIL_ADDRESS_INDEX 4 -#define USER_SETTINGS_CHANGE_PASSWORD_INDEX 5 -#define USER_SETTINGS_PHONE_NUMBER_INDEX 6 -#define USER_SETTINGS_NIGHT_MODE_SEP_INDEX 7 -#define USER_SETTINGS_NIGHT_MODE_INDEX 8 -#define USER_SETTINGS_COUNT 9 - */ - -#define USER_SETTINGS_PROFILE_PICTURE_INDEX 0 -#define USER_SETTINGS_DISPLAY_NAME_INDEX 1 -#define USER_SETTINGS_CHANGE_PASSWORD_INDEX 2 -#define USER_SETTINGS_COUNT 3 - -// hide some unsupported account settings. -#define USER_SETTINGS_PHONE_NUMBER_INDEX -1 -#define USER_SETTINGS_NIGHT_MODE_SEP_INDEX -1 -#define USER_SETTINGS_NIGHT_MODE_INDEX -1 -#define USER_SETTINGS_FIRST_NAME_INDEX -1 -#define USER_SETTINGS_SURNAME_INDEX -1 -#define USER_SETTINGS_EMAIL_ADDRESS_INDEX -1 - #define NOTIFICATION_SETTINGS_ENABLE_PUSH_INDEX 0 #define NOTIFICATION_SETTINGS_GLOBAL_SETTINGS_INDEX 1 //#define NOTIFICATION_SETTINGS_CONTAINING_MY_USER_NAME_INDEX 1 @@ -107,6 +81,18 @@ UITextField* newPasswordTextField1; UITextField* newPasswordTextField2; UIAlertAction* savePasswordAction; + + // Dynamic rows in the user settings section + NSInteger userSettingsProfilePictureIndex; + NSInteger userSettingsDisplayNameIndex; + NSInteger userSettingsFirstNameIndex; + NSInteger userSettingsSurnameIndex; + NSInteger userSettingsEmailStartIndex; + NSInteger userSettingsNewEmailIndex; + NSInteger userSettingsChangePasswordIndex; + NSInteger userSettingsPhoneNumberIndex; + NSInteger userSettingsNightModeSepIndex; + NSInteger userSettingsNightModeIndex; } @end @@ -344,7 +330,20 @@ } else if (section == SETTINGS_SECTION_USER_SETTINGS_INDEX) { - count = USER_SETTINGS_COUNT; + userSettingsProfilePictureIndex = 0; + userSettingsDisplayNameIndex = 1; + userSettingsChangePasswordIndex = 2; + + // Hide some unsupported account settings + userSettingsFirstNameIndex = -1; + userSettingsSurnameIndex = -1; + userSettingsEmailStartIndex = -1; + userSettingsNewEmailIndex = -1; + userSettingsPhoneNumberIndex = -1; + userSettingsNightModeSepIndex = -1; + userSettingsNightModeIndex = -1; + count = 3; + } else if (section == SETTINGS_SECTION_NOTIFICATIONS_SETTINGS_INDEX) { @@ -435,7 +434,7 @@ { MXMyUser* myUser = session.myUser; - if (row == USER_SETTINGS_PROFILE_PICTURE_INDEX) + if (row == userSettingsProfilePictureIndex) { MXKTableViewCellWithLabelAndMXKImageView *profileCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithLabelAndMXKImageView defaultReuseIdentifier]]; @@ -472,7 +471,7 @@ cell = profileCell; } - else if (row == USER_SETTINGS_DISPLAY_NAME_INDEX) + else if (row == userSettingsDisplayNameIndex) { MXKTableViewCellWithLabelAndTextField *displaynameCell = [self getLabelAndTextFieldCell:tableView]; @@ -488,7 +487,7 @@ cell = displaynameCell; } - else if (row == USER_SETTINGS_FIRST_NAME_INDEX) + else if (row == userSettingsFirstNameIndex) { MXKTableViewCellWithLabelAndTextField *firstCell = [self getLabelAndTextFieldCell:tableView]; @@ -497,7 +496,7 @@ cell = firstCell; } - else if (row == USER_SETTINGS_SURNAME_INDEX) + else if (row == userSettingsSurnameIndex) { MXKTableViewCellWithLabelAndTextField *surnameCell = [self getLabelAndTextFieldCell:tableView]; @@ -506,7 +505,7 @@ cell = surnameCell; } - else if (row == USER_SETTINGS_EMAIL_ADDRESS_INDEX) + else if (row == userSettingsEmailStartIndex) { MXKTableViewCellWithLabelAndTextField *emailCell = [self getLabelAndTextFieldCell:tableView]; @@ -515,7 +514,7 @@ cell = emailCell; } - else if (row == USER_SETTINGS_CHANGE_PASSWORD_INDEX) + else if (row == userSettingsChangePasswordIndex) { MXKTableViewCellWithLabelAndTextField *passwordCell = [self getLabelAndTextFieldCell:tableView]; @@ -525,7 +524,7 @@ cell = passwordCell; } - else if (row == USER_SETTINGS_PHONE_NUMBER_INDEX) + else if (row == userSettingsPhoneNumberIndex) { MXKTableViewCellWithLabelAndTextField *phonenumberCell = [self getLabelAndTextFieldCell:tableView]; @@ -534,14 +533,14 @@ cell = phonenumberCell; } - else if (row == USER_SETTINGS_NIGHT_MODE_SEP_INDEX) + else if (row == userSettingsNightModeSepIndex) { UITableViewCell *sepCell = [[UITableViewCell alloc] init]; sepCell.backgroundColor = kVectorColorLightGrey; cell = sepCell; } - else if (row == USER_SETTINGS_NIGHT_MODE_INDEX) + else if (row == userSettingsNightModeIndex) { MXKTableViewCellWithLabelAndTextField *nightModeCell = [self getLabelAndTextFieldCell:tableView]; @@ -768,7 +767,7 @@ } else if (section == SETTINGS_SECTION_USER_SETTINGS_INDEX) { - if (row == USER_SETTINGS_PROFILE_PICTURE_INDEX) + if (row == userSettingsProfilePictureIndex) { mediaPicker = [MediaPickerViewController mediaPickerViewController]; mediaPicker.mediaTypes = @[(NSString *)kUTTypeImage]; @@ -778,7 +777,7 @@ [self presentViewController:navigationController animated:YES completion:nil]; } - else if (row == USER_SETTINGS_CHANGE_PASSWORD_INDEX) + else if (row == userSettingsChangePasswordIndex) { [self displayPasswordAlert]; } @@ -1015,7 +1014,7 @@ { UITextField* textField = (UITextField*)sender; - if (textField.tag == USER_SETTINGS_DISPLAY_NAME_INDEX) + if (textField.tag == userSettingsDisplayNameIndex) { newDisplayName = textField.text; [self updateSaveButtonStatus]; From 1f8c5146afd440438244c6b572706e00e375cf8a Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 10:40:03 +0200 Subject: [PATCH 2/8] Email binding: SettingsVC: Replace "Email Address" by "Email" which lets more room for displaying user email addresses --- Vector/Assets/en.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vector/Assets/en.lproj/Vector.strings b/Vector/Assets/en.lproj/Vector.strings index 4505fb5a5..cc39ae495 100644 --- a/Vector/Assets/en.lproj/Vector.strings +++ b/Vector/Assets/en.lproj/Vector.strings @@ -165,7 +165,7 @@ "settings_display_name" = "Display Name"; "settings_first_name" = "First Name"; "settings_surname" = "Surname"; -"settings_email_address" = "Email Address"; +"settings_email_address" = "Email"; "settings_change_password" = "Change password"; "settings_phone_number" = "Phone Number"; "settings_night_mode" = "Night Mode"; From 7eeb341daaece07c45afc56d6d3dc2756d0a9eff Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 10:44:22 +0200 Subject: [PATCH 3/8] Email binding: SettingsVC: Display users linked emails --- .../ViewController/SettingsViewController.m | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index 334f4ef34..d16a1e22d 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -87,8 +87,8 @@ NSInteger userSettingsDisplayNameIndex; NSInteger userSettingsFirstNameIndex; NSInteger userSettingsSurnameIndex; - NSInteger userSettingsEmailStartIndex; - NSInteger userSettingsNewEmailIndex; + NSInteger userSettingsEmailStartIndex; // The user can have several linked emails. Hence, the dynamic section items count + NSInteger userSettingsNewEmailIndex; // This index also marks the end of the emails list NSInteger userSettingsChangePasswordIndex; NSInteger userSettingsPhoneNumberIndex; NSInteger userSettingsNightModeSepIndex; @@ -231,9 +231,14 @@ }]; } - // Refresh display [self.tableView reloadData]; + + // Refresh linked emails in parallel + MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; + [account load3PIDs:^{ + [self.tableView reloadData]; + } failure:nil]; } - (void)viewWillDisappear:(BOOL)animated @@ -330,20 +335,22 @@ } else if (section == SETTINGS_SECTION_USER_SETTINGS_INDEX) { + MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; + userSettingsProfilePictureIndex = 0; userSettingsDisplayNameIndex = 1; userSettingsChangePasswordIndex = 2; + userSettingsEmailStartIndex = 3; + userSettingsNewEmailIndex = userSettingsEmailStartIndex + account.linkedEmails.count; // Hide some unsupported account settings userSettingsFirstNameIndex = -1; userSettingsSurnameIndex = -1; - userSettingsEmailStartIndex = -1; - userSettingsNewEmailIndex = -1; userSettingsPhoneNumberIndex = -1; userSettingsNightModeSepIndex = -1; userSettingsNightModeIndex = -1; - count = 3; + count = userSettingsNewEmailIndex; } else if (section == SETTINGS_SECTION_NOTIFICATIONS_SETTINGS_INDEX) { @@ -505,11 +512,12 @@ cell = surnameCell; } - else if (row == userSettingsEmailStartIndex) + else if (userSettingsEmailStartIndex <= row && row < userSettingsNewEmailIndex) { MXKTableViewCellWithLabelAndTextField *emailCell = [self getLabelAndTextFieldCell:tableView]; emailCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_email_address", @"Vector", nil); + emailCell.mxkTextField.text = account.linkedEmails[row - userSettingsEmailStartIndex]; emailCell.mxkTextField.userInteractionEnabled = NO; cell = emailCell; From e4726eeef9d2fbbc2f1b3a5cde544c6bd8946f8e Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 14:53:01 +0200 Subject: [PATCH 4/8] SettingsVC: BF: Removed the firstResponder thing. I believe it was here to hide the keyboard on tableview scroll but this feature is already enabled in the storyboard. The bug was that it unexpectly hides the keyboard when editing the displayname in landscape. --- .../ViewController/SettingsViewController.m | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index d16a1e22d..1ebae3d8d 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -64,9 +64,6 @@ // picker MediaPickerViewController* mediaPicker; - // the first responder - UIView* firstResponder; - // profile updates // avatar UIImage* newAvatarImage; @@ -301,20 +298,6 @@ // FIXME add night mode } -#pragma mark - UIScrollView delegate - -- (void)scrollViewDidScroll:(UIScrollView *)scrollView -{ - if (scrollView == self.tableView) - { - if ([firstResponder isFirstResponder]) - { - [firstResponder resignFirstResponder]; - firstResponder = nil; - } - } -} - #pragma mark - UITableView data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView @@ -489,9 +472,6 @@ [displaynameCell.mxkTextField removeTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; [displaynameCell.mxkTextField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; - [displaynameCell.mxkTextField removeTarget:self action:@selector(textFieldDidBegin:) forControlEvents:UIControlEventEditingDidBegin]; - [displaynameCell.mxkTextField addTarget:self action:@selector(textFieldDidBegin:) forControlEvents:UIControlEventEditingDidBegin]; - cell = displaynameCell; } else if (row == userSettingsFirstNameIndex) @@ -790,12 +770,6 @@ [self displayPasswordAlert]; } } - - if ([firstResponder isFirstResponder]) - { - [firstResponder resignFirstResponder]; - firstResponder = nil; - } [aTableView deselectRowAtIndexPath:indexPath animated:YES]; } @@ -1029,11 +1003,6 @@ } } -- (IBAction)textFieldDidBegin:(id)sender -{ - firstResponder = (UIView*)sender; -} - #pragma password update management - (IBAction)passwordTextFieldDidChange:(id)sender From 891fb3cb6bc218495c416319f8a978b5ac1fea48 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 17:44:02 +0200 Subject: [PATCH 5/8] Email binding: SettingsVC: Added binding of a new email --- Vector/Assets/en.lproj/Vector.strings | 1 + .../ViewController/SettingsViewController.h | 2 +- .../ViewController/SettingsViewController.m | 226 +++++++++++++++++- 3 files changed, 215 insertions(+), 14 deletions(-) diff --git a/Vector/Assets/en.lproj/Vector.strings b/Vector/Assets/en.lproj/Vector.strings index cc39ae495..32ebca3c6 100644 --- a/Vector/Assets/en.lproj/Vector.strings +++ b/Vector/Assets/en.lproj/Vector.strings @@ -166,6 +166,7 @@ "settings_first_name" = "First Name"; "settings_surname" = "Surname"; "settings_email_address" = "Email"; +"settings_add_email_address" = "Add email address"; "settings_change_password" = "Change password"; "settings_phone_number" = "Phone Number"; "settings_night_mode" = "Night Mode"; diff --git a/Vector/ViewController/SettingsViewController.h b/Vector/ViewController/SettingsViewController.h index 6dd75c1a5..e6699ed97 100644 --- a/Vector/ViewController/SettingsViewController.h +++ b/Vector/ViewController/SettingsViewController.h @@ -18,7 +18,7 @@ #import "MediaPickerViewController.h" -@interface SettingsViewController : MXKTableViewController +@interface SettingsViewController : MXKTableViewController @end diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index 1ebae3d8d..c09c5ea90 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -79,6 +79,9 @@ UITextField* newPasswordTextField2; UIAlertAction* savePasswordAction; + // New email address to bind + NSString* newEmail; + // Dynamic rows in the user settings section NSInteger userSettingsProfilePictureIndex; NSInteger userSettingsDisplayNameIndex; @@ -92,6 +95,11 @@ NSInteger userSettingsNightModeIndex; } +/** + Flag indicating whether the user is typing an email to bind. + */ +@property (nonatomic) BOOL newEmailEditingEnabled; + @end @implementation SettingsViewController @@ -232,10 +240,7 @@ [self.tableView reloadData]; // Refresh linked emails in parallel - MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; - [account load3PIDs:^{ - [self.tableView reloadData]; - } failure:nil]; + [self loadLinkedEmails]; } - (void)viewWillDisappear:(BOOL)animated @@ -288,6 +293,91 @@ [[NSNotificationCenter defaultCenter] removeObserver:self]; } +-(void)setNewEmailEditingEnabled:(BOOL)newEmailEditingEnabled +{ + if (newEmailEditingEnabled != _newEmailEditingEnabled) + { + // Update the flag + _newEmailEditingEnabled = newEmailEditingEnabled; + + // Update the top-rigth corner button + if (!_newEmailEditingEnabled) + { + newEmail = nil; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(onSave:)]; + } + else + { + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(onAddNewEmail:)]; + } + + // And refresh the corresponding table view cell with animation + [self.tableView reloadRowsAtIndexPaths:@[ + [NSIndexPath indexPathForRow:userSettingsNewEmailIndex inSection:SETTINGS_SECTION_USER_SETTINGS_INDEX] + ] + withRowAnimation:UITableViewRowAnimationFade]; + } +} + +- (void)showValidationEmailDialogWithMessage:(NSString*)message for3PID:(MXK3PID*)threePID +{ + MXKAlert *alert = [[MXKAlert alloc] initWithTitle:[NSBundle mxk_localizedStringForKey:@"account_email_validation_title"] + message:message + style:MXKAlertStyleAlert]; + + alert.cancelButtonIndex = [alert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"abort"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert){ + // Reset new email adding + self.newEmailEditingEnabled = NO; + }]; + + __strong __typeof(threePID)strongThreePID = threePID; + + [alert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"continue"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) { + + // We always bind emails when registering, so let's do the same here + [threePID add3PIDToUser:YES success:^{ + + // Reset new email adding + self.newEmailEditingEnabled = NO; + + // Update linked emails + [self loadLinkedEmails]; + + } failure:^(NSError *error) { + + NSLog(@"[SettingsViewController] Failed to bind email: %@", error); + + // Display the same popup again if the error is M_THREEPID_AUTH_FAILED + MXError *mxError = [[MXError alloc] initWithNSError:error]; + if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringThreePIDAuthFailed]) + { + [self showValidationEmailDialogWithMessage:[NSBundle mxk_localizedStringForKey:@"account_email_validation_error"] for3PID:strongThreePID]; + } + else + { + // Notify MatrixKit user + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error]; + } + }]; + }]; + + [alert showInViewController:self]; +} + +- (void)loadLinkedEmails +{ + // Refresh the account 3PIDs list + MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; + [account load3PIDs:^{ + + [self.tableView reloadData]; + + } failure:^(NSError *error) { + // Display the data that has been loaded last time + [self.tableView reloadData]; + }]; +} + #pragma mark - Segues - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender @@ -333,7 +423,7 @@ userSettingsNightModeSepIndex = -1; userSettingsNightModeIndex = -1; - count = userSettingsNewEmailIndex; + count = userSettingsNewEmailIndex + 1; } else if (section == SETTINGS_SECTION_NOTIFICATIONS_SETTINGS_INDEX) { @@ -362,6 +452,7 @@ cell.mxkTextField.textColor = [UIColor lightGrayColor]; cell.accessoryType = UITableViewCellAccessoryNone; + cell.accessoryView = nil; cell.alpha = 1.0f; cell.userInteractionEnabled = YES; @@ -502,6 +593,45 @@ cell = emailCell; } + else if (row == userSettingsNewEmailIndex) + { + MXKTableViewCellWithLabelAndTextField *newEmailCell = [self getLabelAndTextFieldCell:tableView]; + + // Render the cell according to the `newEmailEditingEnabled` property + if (!_newEmailEditingEnabled) + { + newEmailCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_add_email_address", @"Vector", nil); + newEmailCell.mxkTextField.text = nil; + newEmailCell.mxkTextField.userInteractionEnabled = NO; + newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"plus_icon"]]; + } + else + { + newEmailCell.mxkLabel.text = nil; + newEmailCell.mxkTextField.text = newEmail; + newEmailCell.mxkTextField.userInteractionEnabled = YES; + newEmailCell.mxkTextField.keyboardType = UIKeyboardTypeEmailAddress; + newEmailCell.mxkTextField.delegate = self; + + [newEmailCell.mxkTextField removeTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; + [newEmailCell.mxkTextField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; + + [newEmailCell.mxkTextField removeTarget:self action:@selector(textFieldDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; + [newEmailCell.mxkTextField addTarget:self action:@selector(textFieldDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; + + // Display the keyboard if this is the first time we render this cell + if (!newEmail) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [newEmailCell.mxkTextField becomeFirstResponder]; + }); + } + } + + newEmailCell.mxkTextField.tag = row; + + cell = newEmailCell; + } else if (row == userSettingsChangePasswordIndex) { MXKTableViewCellWithLabelAndTextField *passwordCell = [self getLabelAndTextFieldCell:tableView]; @@ -769,6 +899,11 @@ { [self displayPasswordAlert]; } + else if (row == userSettingsNewEmailIndex) + { + // Enable the new email text field + self.newEmailEditingEnabled = YES; + } } [aTableView deselectRowAtIndexPath:indexPath animated:YES]; @@ -944,22 +1079,64 @@ [self.tableView reloadData]; } +- (IBAction)onAddNewEmail:(id)sender +{ + // Email check + if (![MXTools isEmailAddress:newEmail]) + { + MXKAlert *alert = [[MXKAlert alloc] initWithTitle:[NSBundle mxk_localizedStringForKey:@"account_error_email_wrong_title"] message:[NSBundle mxk_localizedStringForKey:@"account_error_email_wrong_description"] style:MXKAlertStyleAlert]; + + alert.cancelButtonIndex = [alert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) { + }]; + [alert showInViewController:self]; + + return; + } + + if ([sender isKindOfClass:UITextField.class]) + { + [sender resignFirstResponder]; + } + + MXK3PID *new3PID = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:newEmail]; + [new3PID requestValidationTokenWithMatrixRestClient:self.mainSession.matrixRestClient success:^{ + + [self showValidationEmailDialogWithMessage:[NSBundle mxk_localizedStringForKey:@"account_email_validation_message"] for3PID:new3PID]; + + } failure:^(NSError *error) { + + NSLog(@"[SettingsViewController] Failed to request email token: %@", error); + + // Notify MatrixKit user + [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error]; + + }]; +} + - (void)updateSaveButtonStatus { if ([AppDelegate theDelegate].mxSessions.count > 0) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; - MXMyUser* myUser = session.myUser; - - BOOL saveButtonEnabled = (nil != newAvatarImage); - - if (!saveButtonEnabled) + BOOL saveButtonEnabled; + if (!_newEmailEditingEnabled) { - if (newDisplayName) + MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXMyUser* myUser = session.myUser; + + saveButtonEnabled = (nil != newAvatarImage); + + if (!saveButtonEnabled) { - saveButtonEnabled = ![myUser.displayname isEqualToString:newDisplayName]; + if (newDisplayName) + { + saveButtonEnabled = ![myUser.displayname isEqualToString:newDisplayName]; + } } } + else + { + saveButtonEnabled = (0 != newEmail.length); + } self.navigationItem.rightBarButtonItem.enabled = saveButtonEnabled; } @@ -1001,6 +1178,29 @@ newDisplayName = textField.text; [self updateSaveButtonStatus]; } + else if (textField.tag == userSettingsNewEmailIndex) + { + newEmail = textField.text; + [self updateSaveButtonStatus]; + } +} + +- (IBAction)textFieldDidEnd:(id)sender +{ + UITextField* textField = (UITextField*)sender; + + // Disable the new email edition if the user leaves the text field empty + if (textField.tag == userSettingsNewEmailIndex && textField.text.length == 0) + { + self.newEmailEditingEnabled = NO; + } +} + +#pragma mark - UITextField delegate +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + [self onAddNewEmail:textField]; + return YES; } #pragma password update management From 6d54098423c59ba0e5026bd1643bd7c930add438 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 17:53:43 +0200 Subject: [PATCH 6/8] Email binding: SettingsVC binding email: dismiss the keyboard when the user click on the + button in the nav bar --- .../ViewController/SettingsViewController.m | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index c09c5ea90..5e273d5f5 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -80,7 +80,7 @@ UIAlertAction* savePasswordAction; // New email address to bind - NSString* newEmail; + UITextField* newEmailTextField; // Dynamic rows in the user settings section NSInteger userSettingsProfilePictureIndex; @@ -303,7 +303,7 @@ // Update the top-rigth corner button if (!_newEmailEditingEnabled) { - newEmail = nil; + newEmailTextField = nil; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(onSave:)]; } else @@ -608,7 +608,8 @@ else { newEmailCell.mxkLabel.text = nil; - newEmailCell.mxkTextField.text = newEmail; + newEmailCell.mxkTextField.text = newEmailTextField.text; + newEmailTextField = newEmailCell.mxkTextField; newEmailCell.mxkTextField.userInteractionEnabled = YES; newEmailCell.mxkTextField.keyboardType = UIKeyboardTypeEmailAddress; newEmailCell.mxkTextField.delegate = self; @@ -619,13 +620,10 @@ [newEmailCell.mxkTextField removeTarget:self action:@selector(textFieldDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; [newEmailCell.mxkTextField addTarget:self action:@selector(textFieldDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; - // Display the keyboard if this is the first time we render this cell - if (!newEmail) - { - dispatch_async(dispatch_get_main_queue(), ^{ - [newEmailCell.mxkTextField becomeFirstResponder]; - }); - } + // Display the keyboard right now + dispatch_async(dispatch_get_main_queue(), ^{ + [newEmailCell.mxkTextField becomeFirstResponder]; + }); } newEmailCell.mxkTextField.tag = row; @@ -1082,7 +1080,7 @@ - (IBAction)onAddNewEmail:(id)sender { // Email check - if (![MXTools isEmailAddress:newEmail]) + if (![MXTools isEmailAddress:newEmailTextField.text]) { MXKAlert *alert = [[MXKAlert alloc] initWithTitle:[NSBundle mxk_localizedStringForKey:@"account_error_email_wrong_title"] message:[NSBundle mxk_localizedStringForKey:@"account_error_email_wrong_description"] style:MXKAlertStyleAlert]; @@ -1093,12 +1091,10 @@ return; } - if ([sender isKindOfClass:UITextField.class]) - { - [sender resignFirstResponder]; - } + // Dismiss the keyboard + [newEmailTextField resignFirstResponder]; - MXK3PID *new3PID = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:newEmail]; + MXK3PID *new3PID = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:newEmailTextField.text]; [new3PID requestValidationTokenWithMatrixRestClient:self.mainSession.matrixRestClient success:^{ [self showValidationEmailDialogWithMessage:[NSBundle mxk_localizedStringForKey:@"account_email_validation_message"] for3PID:new3PID]; @@ -1135,7 +1131,7 @@ } else { - saveButtonEnabled = (0 != newEmail.length); + saveButtonEnabled = (0 != newEmailTextField.text.length); } self.navigationItem.rightBarButtonItem.enabled = saveButtonEnabled; @@ -1180,7 +1176,6 @@ } else if (textField.tag == userSettingsNewEmailIndex) { - newEmail = textField.text; [self updateSaveButtonStatus]; } } From eec411f876f015daf96d22c31a7a39d1e6b56c39 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 5 Apr 2016 18:12:55 +0200 Subject: [PATCH 7/8] Email binding: SettingsVC binding email: Added loading wheel --- Vector/ViewController/SettingsViewController.m | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index 5e273d5f5..53427596b 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -326,6 +326,9 @@ style:MXKAlertStyleAlert]; alert.cancelButtonIndex = [alert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"abort"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert){ + + [self stopActivityIndicator]; + // Reset new email adding self.newEmailEditingEnabled = NO; }]; @@ -337,6 +340,8 @@ // We always bind emails when registering, so let's do the same here [threePID add3PIDToUser:YES success:^{ + [self stopActivityIndicator]; + // Reset new email adding self.newEmailEditingEnabled = NO; @@ -355,6 +360,8 @@ } else { + [self stopActivityIndicator]; + // Notify MatrixKit user [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error]; } @@ -370,11 +377,13 @@ MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; [account load3PIDs:^{ - [self.tableView reloadData]; + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(SETTINGS_SECTION_USER_SETTINGS_INDEX, 1)]; + [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone]; } failure:^(NSError *error) { // Display the data that has been loaded last time - [self.tableView reloadData]; + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(SETTINGS_SECTION_USER_SETTINGS_INDEX, 1)]; + [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone]; }]; } @@ -1091,6 +1100,8 @@ return; } + [self startActivityIndicator]; + // Dismiss the keyboard [newEmailTextField resignFirstResponder]; @@ -1101,6 +1112,8 @@ } failure:^(NSError *error) { + [self stopActivityIndicator]; + NSLog(@"[SettingsViewController] Failed to request email token: %@", error); // Notify MatrixKit user From 0b1f7d7572a2634728a78a4d46275919d9976ac1 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 6 Apr 2016 10:55:16 +0200 Subject: [PATCH 8/8] Email binding: Keep ref to the MXKAlert to be able to dismiss it viewWillDisappear (incoming call) --- .../ViewController/SettingsViewController.m | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/Vector/ViewController/SettingsViewController.m b/Vector/ViewController/SettingsViewController.m index 53427596b..d3127d6aa 100644 --- a/Vector/ViewController/SettingsViewController.m +++ b/Vector/ViewController/SettingsViewController.m @@ -52,6 +52,9 @@ @interface SettingsViewController () { + // Current alert (if any). + MXKAlert *currentAlert; + // listener id removedAccountObserver; id accountUserInfoObserver; @@ -246,7 +249,13 @@ - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - + + if (currentAlert) + { + [currentAlert dismiss:NO]; + currentAlert = nil; + } + if (notificationCenterWillUpdateObserver) { [[NSNotificationCenter defaultCenter] removeObserver:notificationCenterWillUpdateObserver]; @@ -321,46 +330,57 @@ - (void)showValidationEmailDialogWithMessage:(NSString*)message for3PID:(MXK3PID*)threePID { - MXKAlert *alert = [[MXKAlert alloc] initWithTitle:[NSBundle mxk_localizedStringForKey:@"account_email_validation_title"] + __weak typeof(self) weakSelf = self; + + currentAlert = [[MXKAlert alloc] initWithTitle:[NSBundle mxk_localizedStringForKey:@"account_email_validation_title"] message:message style:MXKAlertStyleAlert]; - alert.cancelButtonIndex = [alert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"abort"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert){ + currentAlert.cancelButtonIndex = [currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"abort"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert){ - [self stopActivityIndicator]; + __strong __typeof(weakSelf)strongSelf = weakSelf; + strongSelf->currentAlert = nil; + + [strongSelf stopActivityIndicator]; // Reset new email adding - self.newEmailEditingEnabled = NO; + strongSelf.newEmailEditingEnabled = NO; }]; __strong __typeof(threePID)strongThreePID = threePID; - [alert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"continue"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) { + [currentAlert addActionWithTitle:[NSBundle mxk_localizedStringForKey:@"continue"] style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) { // We always bind emails when registering, so let's do the same here [threePID add3PIDToUser:YES success:^{ - [self stopActivityIndicator]; + __strong __typeof(weakSelf)strongSelf = weakSelf; + strongSelf->currentAlert = nil; + + [strongSelf stopActivityIndicator]; // Reset new email adding - self.newEmailEditingEnabled = NO; + strongSelf.newEmailEditingEnabled = NO; // Update linked emails - [self loadLinkedEmails]; + [strongSelf loadLinkedEmails]; } failure:^(NSError *error) { + __strong __typeof(weakSelf)strongSelf = weakSelf; + strongSelf->currentAlert = nil; + NSLog(@"[SettingsViewController] Failed to bind email: %@", error); // Display the same popup again if the error is M_THREEPID_AUTH_FAILED MXError *mxError = [[MXError alloc] initWithNSError:error]; if (mxError && [mxError.errcode isEqualToString:kMXErrCodeStringThreePIDAuthFailed]) { - [self showValidationEmailDialogWithMessage:[NSBundle mxk_localizedStringForKey:@"account_email_validation_error"] for3PID:strongThreePID]; + [strongSelf showValidationEmailDialogWithMessage:[NSBundle mxk_localizedStringForKey:@"account_email_validation_error"] for3PID:strongThreePID]; } else { - [self stopActivityIndicator]; + [strongSelf stopActivityIndicator]; // Notify MatrixKit user [[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error]; @@ -368,7 +388,7 @@ }]; }]; - [alert showInViewController:self]; + [currentAlert showInViewController:self]; } - (void)loadLinkedEmails @@ -618,7 +638,6 @@ { newEmailCell.mxkLabel.text = nil; newEmailCell.mxkTextField.text = newEmailTextField.text; - newEmailTextField = newEmailCell.mxkTextField; newEmailCell.mxkTextField.userInteractionEnabled = YES; newEmailCell.mxkTextField.keyboardType = UIKeyboardTypeEmailAddress; newEmailCell.mxkTextField.delegate = self; @@ -629,10 +648,14 @@ [newEmailCell.mxkTextField removeTarget:self action:@selector(textFieldDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; [newEmailCell.mxkTextField addTarget:self action:@selector(textFieldDidEnd:) forControlEvents:UIControlEventEditingDidEnd]; - // Display the keyboard right now - dispatch_async(dispatch_get_main_queue(), ^{ - [newEmailCell.mxkTextField becomeFirstResponder]; - }); + // When displaying the textfield the 1st time, open the keyboard + if (!newEmailTextField) + { + dispatch_async(dispatch_get_main_queue(), ^{ + [newEmailCell.mxkTextField becomeFirstResponder]; + }); + } + newEmailTextField = newEmailCell.mxkTextField; } newEmailCell.mxkTextField.tag = row; @@ -1105,8 +1128,10 @@ // Dismiss the keyboard [newEmailTextField resignFirstResponder]; + MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXK3PID *new3PID = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:newEmailTextField.text]; - [new3PID requestValidationTokenWithMatrixRestClient:self.mainSession.matrixRestClient success:^{ + [new3PID requestValidationTokenWithMatrixRestClient:session.matrixRestClient success:^{ [self showValidationEmailDialogWithMessage:[NSBundle mxk_localizedStringForKey:@"account_email_validation_message"] for3PID:new3PID];