Fixes issues with registration in iOS simulator.

This commit is contained in:
Frederic Jacobs 2015-04-10 22:35:26 +02:00
parent dceb1c9976
commit abc63eca27
2 changed files with 232 additions and 177 deletions

View file

@ -22,145 +22,173 @@
@implementation PushManager @implementation PushManager
+ (instancetype)sharedManager { + (instancetype)sharedManager
{
static PushManager *sharedManager = nil; static PushManager *sharedManager = nil;
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
sharedManager = [self new]; sharedManager = [self new];
}); });
return sharedManager; return sharedManager;
} }
- (instancetype)init{ - (instancetype)init
{
self = [super init]; self = [super init];
if (self) { if (self) {
self.missingPermissionsAlertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") self.missingPermissionsAlertView =
message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"")
delegate:nil message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"")
cancelButtonTitle:NSLocalizedString(@"OK", @"") delegate:nil
otherButtonTitles:nil, nil]; cancelButtonTitle:NSLocalizedString(@"OK", @"")
otherButtonTitles:nil, nil];
} }
return self; return self;
} }
#pragma mark Register device for Push Notification locally #pragma mark Register device for Push Notification locally
-(TOCFuture*)registerPushNotificationFuture{ - (TOCFuture *)registerPushNotificationFuture
{
self.pushNotificationFutureSource = [TOCFutureSource new]; self.pushNotificationFutureSource = [TOCFutureSource new];
[UIApplication.sharedApplication registerForRemoteNotifications]; [UIApplication.sharedApplication registerForRemoteNotifications];
return self.pushNotificationFutureSource.future; return self.pushNotificationFutureSource.future;
} }
- (void)requestPushTokenWithSuccess:(void (^)(NSData* pushToken))success failure:(failedPushRegistrationBlock)failure{ - (void)requestPushTokenWithSuccess:(void (^)(NSData *pushToken))success failure:(failedPushRegistrationBlock)failure
TOCFuture *requestPushTokenFuture = [self registerPushNotificationFuture]; {
TOCFuture *requestPushTokenFuture = [self registerPushNotificationFuture];
[requestPushTokenFuture catchDo:^(id failureObj) { [requestPushTokenFuture catchDo:^(id failureObj) {
[self.missingPermissionsAlertView show]; [self.missingPermissionsAlertView show];
failure(failureObj); failure(failureObj);
DDLogError(@"This should not happen on iOS8. No push token was provided"); DDLogError(@"This should not happen on iOS8. No push token was provided");
}]; }];
[requestPushTokenFuture thenDo:^(NSData* pushToken) { [requestPushTokenFuture thenDo:^(NSData *pushToken) {
TOCFuture *registerPushTokenFuture = [self registerForPushFutureWithToken:pushToken]; TOCFuture *registerPushTokenFuture = [self registerForPushFutureWithToken:pushToken];
[registerPushTokenFuture catchDo:^(id failureObj) { [registerPushTokenFuture catchDo:^(id failureObj) {
failure(failureObj); failure(failureObj);
}]; }];
[registerPushTokenFuture thenDo:^(id value) { [registerPushTokenFuture thenDo:^(id value) {
TOCFuture *userRegistration = [self registerForUserNotificationsFuture]; TOCFuture *userRegistration = [self registerForUserNotificationsFuture];
[userRegistration thenDo:^(UIUserNotificationSettings *userNotificationSettings) { [userRegistration thenDo:^(UIUserNotificationSettings *userNotificationSettings) {
success(pushToken); success(pushToken);
}];
}]; }];
}];
}]; }];
} }
- (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData* pushToken, NSString* signupToken))success failure:(failedPushRegistrationBlock)failure{ - (void)registrationAndRedPhoneTokenRequestWithSuccess:(void (^)(NSData *pushToken, NSString *signupToken))success
failure:(failedPushRegistrationBlock)failure
{
if (!self.wantRemoteNotifications) { if (!self.wantRemoteNotifications) {
success([@"Fake PushToken" dataUsingEncoding:NSUTF8StringEncoding], @""); [self registerTokenWithRedPhoneServer:[@"Fake PushToken" dataUsingEncoding:NSUTF8StringEncoding]
withSuccess:success
failure:failure];
return; return;
} }
[self requestPushTokenWithSuccess:^(NSData* pushToken){ [self requestPushTokenWithSuccess:^(NSData *pushToken) {
[RPServerRequestsManager.sharedInstance performRequest:[RPAPICall requestTextSecureVerificationCode] success:^(NSURLSessionDataTask *task, id responseObject) { [self registerTokenWithRedPhoneServer:pushToken withSuccess:success failure:failure];
NSError *error;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error];
NSString* tsToken = [dictionary objectForKey:@"token"];
if (!tsToken || !pushToken || error) {
failure(error);
return;
}
success(pushToken, tsToken);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
failure(error);
}];
} failure:^(NSError *error) { } failure:^(NSError *error) {
[self.missingPermissionsAlertView show]; [self.missingPermissionsAlertView show];
failure([NSError errorWithDomain:pushManagerDomain code:400 userInfo:@{}]); failure([NSError errorWithDomain:pushManagerDomain code:400 userInfo:@{}]);
}]; }];
} }
-(TOCFuture*)registerForUserNotificationsFuture{ - (void)registerTokenWithRedPhoneServer:(NSData *)pushToken
withSuccess:(void (^)(NSData *pushToken, NSString *signupToken))success
failure:(failedPushRegistrationBlock)failure
{
[RPServerRequestsManager.sharedInstance performRequest:[RPAPICall requestTextSecureVerificationCode]
success:^(NSURLSessionDataTask *task, id responseObject) {
NSError *error;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error];
NSString *tsToken = [dictionary objectForKey:@"token"];
if (!tsToken || !pushToken || error) {
failure(error);
return;
}
success(pushToken, tsToken);
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
failure(error);
}];
}
- (TOCFuture *)registerForUserNotificationsFuture
{
self.userNotificationFutureSource = [TOCFutureSource new]; self.userNotificationFutureSource = [TOCFutureSource new];
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] UIUserNotificationSettings *settings =
categories:nil]; [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes]
categories:nil];
[UIApplication.sharedApplication registerUserNotificationSettings:settings]; [UIApplication.sharedApplication registerUserNotificationSettings:settings];
return self.userNotificationFutureSource.future; return self.userNotificationFutureSource.future;
} }
-(BOOL) needToRegisterForRemoteNotifications { - (BOOL)needToRegisterForRemoteNotifications
{
return self.wantRemoteNotifications && (!UIApplication.sharedApplication.isRegisteredForRemoteNotifications); return self.wantRemoteNotifications && (!UIApplication.sharedApplication.isRegisteredForRemoteNotifications);
} }
-(BOOL) wantRemoteNotifications { - (BOOL)wantRemoteNotifications
{
BOOL isSimulator = [UIDevice.currentDevice.model.lowercaseString rangeOfString:@"simulator"].location != NSNotFound; BOOL isSimulator = [UIDevice.currentDevice.model.lowercaseString rangeOfString:@"simulator"].location != NSNotFound;
if (isSimulator) { if (isSimulator) {
// Simulator is used for debugging but can't receive push notifications, so don't bother trying to get them // Simulator is used for debugging but can't receive push notifications, so don't bother trying to get them
return NO; return NO;
} }
return YES; return YES;
} }
-(int)allNotificationTypes{ - (int)allNotificationTypes
{
return UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge; return UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge;
} }
- (void)validateUserNotificationSettings{ - (void)validateUserNotificationSettings
[[self registerForUserNotificationsFuture] thenDo:^(id value) { {
//Nothing to do, just making sure we are registered for User Notifications. [[self registerForUserNotificationsFuture] thenDo:^(id value){
// Nothing to do, just making sure we are registered for User Notifications.
}]; }];
} }
#pragma mark Register Push Notification Token with RedPhone server #pragma mark Register Push Notification Token with RedPhone server
-(TOCFuture*)registerForPushFutureWithToken:(NSData*)token{ - (TOCFuture *)registerForPushFutureWithToken:(NSData *)token
{
self.registerWithServerFutureSource = [TOCFutureSource new]; self.registerWithServerFutureSource = [TOCFutureSource new];
[RPServerRequestsManager.sharedInstance performRequest:[RPAPICall registerPushNotificationWithPushToken:token] success:^(NSURLSessionDataTask *task, id responseObject) { [RPServerRequestsManager.sharedInstance performRequest:[RPAPICall registerPushNotificationWithPushToken:token]
if ([task.response isKindOfClass: NSHTTPURLResponse.class]){ success:^(NSURLSessionDataTask *task, id responseObject) {
NSInteger statusCode = [(NSHTTPURLResponse*) task.response statusCode]; if ([task.response isKindOfClass:NSHTTPURLResponse.class]) {
if (statusCode == 200) { NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode];
[self.registerWithServerFutureSource trySetResult:@YES]; if (statusCode == 200) {
} else{ [self.registerWithServerFutureSource trySetResult:@YES];
DDLogError(@"The server returned %@ instead of a 200 status code", task.response); } else {
[self.registerWithServerFutureSource trySetFailure:[NSError errorWithDomain:pushManagerDomain code:500 userInfo:nil]]; DDLogError(@"The server returned %@ instead of a 200 status code", task.response);
} [self.registerWithServerFutureSource
} else{ trySetFailure:[NSError errorWithDomain:pushManagerDomain code:500 userInfo:nil]];
[self.registerWithServerFutureSource trySetFailure:task.response]; }
} else {
[self.registerWithServerFutureSource trySetFailure:task.response];
}
} }
failure:^(NSURLSessionDataTask *task, NSError *error) {
} failure:^(NSURLSessionDataTask *task, NSError *error) { [self.registerWithServerFutureSource trySetFailure:error];
[self.registerWithServerFutureSource trySetFailure:error]; }];
}];
return self.registerWithServerFutureSource.future; return self.registerWithServerFutureSource.future;
} }

View file

@ -22,19 +22,26 @@
@implementation CodeVerificationViewController @implementation CodeVerificationViewController
- (void)viewDidLoad { - (void)viewDidLoad
{
[super viewDidLoad]; [super viewDidLoad];
[self initializeKeyboardHandlers]; [self initializeKeyboardHandlers];
_headerLabel.text = NSLocalizedString(@"VERIFICATION_HEADER", @""); _headerLabel.text = NSLocalizedString(@"VERIFICATION_HEADER", @"");
_challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT", @""); _challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT", @"");
[_challengeButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", @"") forState:UIControlStateNormal]; [_challengeButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", @"")
forState:UIControlStateNormal];
[_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", @"") forState:UIControlStateNormal];
[_sendCodeViaVoiceButton setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIAVOICE", @"")] forState:UIControlStateNormal]; [_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", @"")
[_changeNumberButton setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_CHANGE_NUMBER", @"")] forState:UIControlStateNormal]; forState:UIControlStateNormal];
[_sendCodeViaVoiceButton
setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIAVOICE", @"")]
forState:UIControlStateNormal];
[_changeNumberButton
setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_CHANGE_NUMBER", @"")]
forState:UIControlStateNormal];
} }
-(void)viewWillAppear:(BOOL)animated - (void)viewWillAppear:(BOOL)animated
{ {
[super viewWillAppear:animated]; [super viewWillAppear:animated];
[self enableServerActions:YES]; [self enableServerActions:YES];
@ -42,55 +49,64 @@
[self adjustScreenSizes]; [self adjustScreenSizes];
} }
- (void)didReceiveMemoryWarning { - (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning]; [super didReceiveMemoryWarning];
} }
- (IBAction)verifyChallengeAction:(id)sender { - (IBAction)verifyChallengeAction:(id)sender
{
[self enableServerActions:NO]; [self enableServerActions:NO];
[_challengeTextField resignFirstResponder]; [_challengeTextField resignFirstResponder];
[self registerWithSuccess:^{ [self registerWithSuccess:^{
[_submitCodeSpinner stopAnimating]; [_submitCodeSpinner stopAnimating];
[Environment.getCurrent.phoneDirectoryManager forceUpdate]; [Environment.getCurrent.phoneDirectoryManager forceUpdate];
[self.navigationController dismissViewControllerAnimated:YES completion:nil]; [self.navigationController dismissViewControllerAnimated:YES completion:nil];
} failure:^(NSError *error) { } failure:^(NSError *error) {
[self showAlertForError:error]; [self showAlertForError:error];
[self enableServerActions:YES]; [self enableServerActions:YES];
[_submitCodeSpinner stopAnimating]; [_submitCodeSpinner stopAnimating];
}]; }];
} }
- (void)registerWithSuccess:(void(^)())success failure:(void(^)(NSError *))failure{ - (void)registerWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure
{
[_submitCodeSpinner startAnimating]; [_submitCodeSpinner startAnimating];
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall verifyVerificationCode:_challengeTextField.text] success:^(NSURLSessionDataTask *task, id responseObject) { [[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall verifyVerificationCode:_challengeTextField.text]
success:^(NSURLSessionDataTask *task, id responseObject) {
[PushManager.sharedManager registrationAndRedPhoneTokenRequestWithSuccess:^(NSData *pushToken, NSString *signupToken) {
[TSAccountManager registerWithRedPhoneToken:signupToken pushToken:pushToken success:^{ [PushManager.sharedManager registrationAndRedPhoneTokenRequestWithSuccess:^(NSData *pushToken,
success(); NSString *signupToken) {
} failure:^(NSError *error) { [TSAccountManager registerWithRedPhoneToken:signupToken
failure(error); pushToken:pushToken
}]; success:^{
} failure:^(NSError *error) { success();
}
failure:^(NSError *error) {
failure(error);
}];
} failure:^(NSError *error) {
failure(error); failure(error);
[_submitCodeSpinner stopAnimating]; [_submitCodeSpinner stopAnimating];
}]; }];
} failure:^(NSURLSessionDataTask *task, NSError *error) { }
NSHTTPURLResponse* badResponse = (NSHTTPURLResponse*)task.response; failure:^(NSURLSessionDataTask *task, NSError *error) {
NSError *responseError = [self errorForResponse:badResponse]; NSHTTPURLResponse *badResponse = (NSHTTPURLResponse *)task.response;
NSError *responseError = [self errorForResponse:badResponse];
failure(responseError);
[_submitCodeSpinner stopAnimating];
}]; failure(responseError);
[_submitCodeSpinner stopAnimating];
}];
} }
// TODO: If useful, this could possibly go in a less-specific class // TODO: If useful, this could possibly go in a less-specific class
- (void)showAlertForError:(NSError *)error { - (void)showAlertForError:(NSError *)error
{
if (error == nil) { if (error == nil) {
DDLogCError(@"%@: Error condition, but no NSError to display", self.class); DDLogCError(@"%@: Error condition, but no NSError to display", self.class);
return; return;
@ -98,123 +114,134 @@
DDLogCError(@"%@: Unable to display error because localizedDescription was not set: %@", self.class, error); DDLogCError(@"%@: Unable to display error because localizedDescription was not set: %@", self.class, error);
return; return;
} }
NSString *alertBody = nil; NSString *alertBody = nil;
if (error.localizedFailureReason.length > 0) { if (error.localizedFailureReason.length > 0) {
alertBody = error.localizedFailureReason; alertBody = error.localizedFailureReason;
} else if (error.localizedRecoverySuggestion.length > 0) { } else if (error.localizedRecoverySuggestion.length > 0) {
alertBody = error.localizedRecoverySuggestion; alertBody = error.localizedRecoverySuggestion;
} }
SignalAlertView(error.localizedDescription, alertBody); SignalAlertView(error.localizedDescription, alertBody);
} }
- (NSError *)errorForResponse:(NSHTTPURLResponse *)badResponse { - (NSError *)errorForResponse:(NSHTTPURLResponse *)badResponse
{
NSString *description = NSLocalizedString(@"REGISTRATION_ERROR", @""); NSString *description = NSLocalizedString(@"REGISTRATION_ERROR", @"");
NSString *failureReason = nil; NSString *failureReason = nil;
TSRegistrationFailure failureType; TSRegistrationFailure failureType;
if (badResponse.statusCode == 401) { if (badResponse.statusCode == 401) {
failureReason = REGISTER_CHALLENGE_ALERT_VIEW_BODY; failureReason = REGISTER_CHALLENGE_ALERT_VIEW_BODY;
failureType = kTSRegistrationFailureAuthentication; failureType = kTSRegistrationFailureAuthentication;
} else if (badResponse.statusCode == 413){ } else if (badResponse.statusCode == 413) {
failureReason = NSLocalizedString(@"REGISTER_RATE_LIMITING_BODY", @""); failureReason = NSLocalizedString(@"REGISTER_RATE_LIMITING_BODY", @"");
failureType = kTSRegistrationFailureRateLimit; failureType = kTSRegistrationFailureRateLimit;
} else { } else {
failureReason = [NSString stringWithFormat:@"%@ %lu", NSLocalizedString(@"SERVER_CODE", @""),(unsigned long)badResponse.statusCode]; failureReason = [NSString
stringWithFormat:@"%@ %lu", NSLocalizedString(@"SERVER_CODE", @""), (unsigned long)badResponse.statusCode];
failureType = kTSRegistrationFailureNetwork; failureType = kTSRegistrationFailureNetwork;
} }
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description, NSLocalizedFailureReasonErrorKey: failureReason}; NSDictionary *userInfo =
@{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : failureReason};
NSError *error = [NSError errorWithDomain:TSRegistrationErrorDomain code:failureType userInfo:userInfo]; NSError *error = [NSError errorWithDomain:TSRegistrationErrorDomain code:failureType userInfo:userInfo];
return error; return error;
} }
#pragma mark - Send codes again #pragma mark - Send codes again
- (IBAction)sendCodeSMSAction:(id)sender { - (IBAction)sendCodeSMSAction:(id)sender
{
[self enableServerActions:NO]; [self enableServerActions:NO];
[_requestCodeAgainSpinner startAnimating]; [_requestCodeAgainSpinner startAnimating];
[[RPServerRequestsManager sharedInstance]performRequest:[RPAPICall requestVerificationCode] success:^(NSURLSessionDataTask *task, id responseObject) { [[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall requestVerificationCode]
[self enableServerActions:YES]; success:^(NSURLSessionDataTask *task, id responseObject) {
[_requestCodeAgainSpinner stopAnimating]; [self enableServerActions:YES];
[_requestCodeAgainSpinner stopAnimating];
} failure:^(NSURLSessionDataTask *task, NSError *error) { }
failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"Registration failed with information %@", error.description);
DDLogError(@"Registration failed with information %@", error.description);
UIAlertView *registrationErrorAV = [[UIAlertView alloc]initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE
message:REGISTER_ERROR_ALERT_VIEW_BODY UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE
delegate:nil message:REGISTER_ERROR_ALERT_VIEW_BODY
cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS delegate:nil
otherButtonTitles:nil, nil]; cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS
otherButtonTitles:nil, nil];
[registrationErrorAV show];
[registrationErrorAV show];
[self enableServerActions:YES];
[_requestCodeAgainSpinner stopAnimating]; [self enableServerActions:YES];
}]; [_requestCodeAgainSpinner stopAnimating];
}];
} }
- (IBAction)sendCodeVoiceAction:(id)sender { - (IBAction)sendCodeVoiceAction:(id)sender
{
[self enableServerActions:NO]; [self enableServerActions:NO];
[_requestCallSpinner startAnimating];
[[RPServerRequestsManager sharedInstance]performRequest:[RPAPICall requestVerificationCodeWithVoice] success:^(NSURLSessionDataTask *task, id responseObject) {
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating];
} failure:^(NSURLSessionDataTask *task, NSError *error) { [_requestCallSpinner startAnimating];
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall requestVerificationCodeWithVoice]
DDLogError(@"Registration failed with information %@", error.description); success:^(NSURLSessionDataTask *task, id responseObject) {
UIAlertView *registrationErrorAV = [[UIAlertView alloc]initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE [self enableServerActions:YES];
message:REGISTER_ERROR_ALERT_VIEW_BODY [_requestCallSpinner stopAnimating];
delegate:nil
cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS }
otherButtonTitles:nil, nil]; failure:^(NSURLSessionDataTask *task, NSError *error) {
[registrationErrorAV show]; DDLogError(@"Registration failed with information %@", error.description);
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating]; UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE
}]; message:REGISTER_ERROR_ALERT_VIEW_BODY
delegate:nil
cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS
otherButtonTitles:nil, nil];
[registrationErrorAV show];
[self enableServerActions:YES];
[_requestCallSpinner stopAnimating];
}];
} }
-(void)enableServerActions:(BOOL)enabled { - (void)enableServerActions:(BOOL)enabled
{
[_challengeButton setEnabled:enabled]; [_challengeButton setEnabled:enabled];
[_sendCodeViaSMSAgainButton setEnabled:enabled]; [_sendCodeViaSMSAgainButton setEnabled:enabled];
[_sendCodeViaVoiceButton setEnabled:enabled]; [_sendCodeViaVoiceButton setEnabled:enabled];
} }
#pragma mark - Keyboard notifications #pragma mark - Keyboard notifications
- (void)initializeKeyboardHandlers{ - (void)initializeKeyboardHandlers
UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; {
UITapGestureRecognizer *outsideTabRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)];
[self.view addGestureRecognizer:outsideTabRecognizer]; [self.view addGestureRecognizer:outsideTabRecognizer];
} }
- (void)dismissKeyboardFromAppropriateSubView { - (void)dismissKeyboardFromAppropriateSubView
{
[self.view endEditing:NO]; [self.view endEditing:NO];
} }
- (void)adjustScreenSizes { - (void)adjustScreenSizes
{
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat blueHeaderHeight; CGFloat blueHeaderHeight;
if (screenHeight < 667) { if (screenHeight < 667) {
self.signalLogo.hidden = YES; self.signalLogo.hidden = YES;
blueHeaderHeight = screenHeight - 400; blueHeaderHeight = screenHeight - 400;
} else { } else {
blueHeaderHeight = screenHeight - 410; blueHeaderHeight = screenHeight - 410;
} }
_headerConstraint.constant = blueHeaderHeight; _headerConstraint.constant = blueHeaderHeight;
} }