session-ios/Signal/src/view controllers/CodeVerificationViewController.m
Michael Kirk c2aa17e362 Changed Safety numbers no longer block communication
When your partner changes their identity key (e.g. by reinstalling),
you'll see a notice alongside their message, but it will no longer
prevent the message from showing. aka "non blocking".

Existing users will be opted into the previous blocking behavior.

This is configurable for all users in Settings > Privacy.

// FREEBIE
2016-11-11 09:13:38 -05:00

283 lines
10 KiB
Objective-C

//
// CodeVerificationViewController.m
// Signal
//
// Created by Dylan Bourgeois on 13/11/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "CodeVerificationViewController.h"
#import "AppDelegate.h"
#import "RPAccountManager.h"
#import "Signal-Swift.h"
#import "SignalsNavigationController.h"
#import "SignalsViewController.h"
#import <PromiseKit/AnyPromise.h>
#import <SignalServiceKit/OWSError.h>
#import <SignalServiceKit/TSAccountManager.h>
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>
NS_ASSUME_NONNULL_BEGIN
NSString *const kCompletedRegistrationSegue = @"CompletedRegistration";
@interface CodeVerificationViewController ()
@property (nonatomic, strong, readonly) OWSAccountManager *accountManager;
@end
@implementation CodeVerificationViewController
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self) {
return self;
}
_accountManager = [[OWSAccountManager alloc] initWithTextSecureAccountManager:[TSAccountManager sharedInstance]
redPhoneAccountManager:[RPAccountManager sharedInstance]];
return self;
}
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
_accountManager = [[OWSAccountManager alloc] initWithTextSecureAccountManager:[TSAccountManager sharedInstance]
redPhoneAccountManager:[RPAccountManager sharedInstance]];
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self initializeKeyboardHandlers];
_headerLabel.text = NSLocalizedString(@"VERIFICATION_HEADER", @"Navigation title in the registration flow - during the sms code verification process.");
_challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT",
@"Text field placeholder for SMS verification code during registration");
_challengeTextField.delegate = self;
[_challengeButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", @"button text during registration to submit your SMS verification code")
forState:UIControlStateNormal];
[_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", @"button text during registration to request another SMS code be sent")
forState:UIControlStateNormal];
[_sendCodeViaVoiceButton
setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIAVOICE", @"button text during registration to request phone number verification be done via phone call")]
forState:UIControlStateNormal];
[_changeNumberButton
setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_CHANGE_NUMBER", @"button text during registration to make corrections to your submitted phone number")]
forState:UIControlStateNormal];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self enableServerActions:YES];
[_phoneNumberEntered setText:
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:[TSAccountManager localNumber]]];
[self adjustScreenSizes];
}
- (void)startActivityIndicator
{
[self.submitCodeSpinner startAnimating];
[self enableServerActions:NO];
[self.challengeTextField resignFirstResponder];
}
- (void)stopActivityIndicator
{
[self enableServerActions:YES];
[self.submitCodeSpinner stopAnimating];
}
- (IBAction)verifyChallengeAction:(id)sender
{
[self startActivityIndicator];
[self.accountManager registerWithVerificationCode:[self validationCodeFromTextField]]
.then(^{
DDLogInfo(@"%@ Successfully registered Signal account.", self.tag);
dispatch_async(dispatch_get_main_queue(), ^{
[self stopActivityIndicator];
[self performSegueWithIdentifier:kCompletedRegistrationSegue sender:nil];
});
})
.catch(^(NSError *_Nonnull error) {
DDLogError(@"%@ error verifying challenge: %@", self.tag, error);
dispatch_async(dispatch_get_main_queue(), ^{
[self stopActivityIndicator];
[self presentAlertWithVerificationError:error];
});
});
}
- (void)presentAlertWithVerificationError:(NSError *)error
{
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:NSLocalizedString(@"REGISTRATION_VERIFICATION_FAILED_TITLE", @"Alert view title")
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"DISMISS_BUTTON_TEXT", nil)
style:UIAlertActionStyleDefault
handler:nil];
[alertController addAction:dismissAction];
[self presentViewController:alertController animated:YES completion:nil];
}
- (NSString *)validationCodeFromTextField {
return [self.challengeTextField.text stringByReplacingOccurrencesOfString:@"-" withString:@""];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender
{
DDLogInfo(@"%@ preparing for CompletedRegistrationSeque", self.tag);
if ([segue.identifier isEqualToString:kCompletedRegistrationSegue]) {
if (![segue.destinationViewController isKindOfClass:[SignalsNavigationController class]]) {
DDLogError(@"%@ Unexpected destination view controller: %@", self.tag, segue.destinationViewController);
return;
}
SignalsNavigationController *snc = (SignalsNavigationController *)segue.destinationViewController;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.window.rootViewController = snc;
if (![snc.topViewController isKindOfClass:[SignalsViewController class]]) {
DDLogError(@"%@ Unexpected top view controller: %@", self.tag, snc.topViewController);
return;
}
DDLogDebug(@"%@ notifying signals view controller of new user.", self.tag);
SignalsViewController *signalsViewController = (SignalsViewController *)snc.topViewController;
signalsViewController.newlyRegisteredUser = YES;
}
}
#pragma mark - Send codes again
- (IBAction)sendCodeSMSAction:(id)sender {
[self enableServerActions:NO];
[_requestCodeAgainSpinner startAnimating];
[TSAccountManager rerequestSMSWithSuccess:^{
DDLogInfo(@"%@ Successfully requested SMS code", self.tag);
[self enableServerActions:YES];
[_requestCodeAgainSpinner stopAnimating];
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to request SMS code with error: %@", self.tag, error);
[self showRegistrationErrorMessage:error];
[self enableServerActions:YES];
[_requestCodeAgainSpinner stopAnimating];
}];
}
- (IBAction)sendCodeVoiceAction:(id)sender {
[self enableServerActions:NO];
[_requestCallSpinner startAnimating];
[TSAccountManager rerequestVoiceWithSuccess:^{
DDLogInfo(@"%@ Successfully requested voice code", self.tag);
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating];
}
failure:^(NSError *error) {
DDLogError(@"%@ Failed to request voice code with error: %@", self.tag, error);
[self showRegistrationErrorMessage:error];
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating];
}];
}
- (void)showRegistrationErrorMessage:(NSError *)registrationError {
UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:registrationError.localizedDescription
message:registrationError.localizedRecoverySuggestion
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", @"")
otherButtonTitles:nil, nil];
[registrationErrorAV show];
}
- (void)enableServerActions:(BOOL)enabled {
[_challengeButton setEnabled:enabled];
[_sendCodeViaSMSAgainButton setEnabled:enabled];
[_sendCodeViaVoiceButton setEnabled:enabled];
}
#pragma mark - Keyboard notifications
- (void)initializeKeyboardHandlers {
UITapGestureRecognizer *outsideTabRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)];
[self.view addGestureRecognizer:outsideTabRecognizer];
}
- (void)dismissKeyboardFromAppropriateSubView {
[self.view endEditing:NO];
}
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string {
if (range.location == 7) {
return NO;
}
if (range.length == 0 &&
![[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[string characterAtIndex:0]]) {
return NO;
}
if (range.length == 0 && range.location == 2) {
textField.text = [NSString stringWithFormat:@"%@%@-", textField.text, string];
return NO;
}
if (range.length == 1 && range.location == 3) {
range.location--;
range.length = 2;
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:@""];
return NO;
}
return YES;
}
- (void)adjustScreenSizes {
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat blueHeaderHeight;
if (screenHeight < 667) {
self.signalLogo.hidden = YES;
blueHeaderHeight = screenHeight - 400;
} else {
blueHeaderHeight = screenHeight - 410;
}
_headerConstraint.constant = blueHeaderHeight;
}
#pragma mark - Logging
+ (NSString *)tag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)tag
{
return self.class.tag;
}
@end
NS_ASSUME_NONNULL_END