Remove old registration views.

pull/2/head
Matthew Chen 6 years ago
parent 88dcd83852
commit aa8fd9e69c

@ -12,8 +12,6 @@
34074F61203D0CBE004596AE /* OWSSounds.m in Sources */ = {isa = PBXBuildFile; fileRef = 34074F5F203D0CBD004596AE /* OWSSounds.m */; };
34074F62203D0CBE004596AE /* OWSSounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 34074F60203D0CBE004596AE /* OWSSounds.h */; settings = {ATTRIBUTES = (Public, ); }; };
340B02BA1FA0D6C700F9CFEC /* ConversationViewItemTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */; };
340FC8A7204DAC8D007AEB0F /* RegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC876204DAC8C007AEB0F /* RegistrationViewController.m */; };
340FC8A8204DAC8D007AEB0F /* CodeVerificationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */; };
340FC8A9204DAC8D007AEB0F /* NotificationSettingsOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */; };
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */; };
340FC8AB204DAC8D007AEB0F /* DomainFrontingCountryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */; };
@ -168,7 +166,6 @@
349ED990221B0194008045B0 /* Onboarding2FAViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */; };
34A4C61E221613D00042EF2E /* OnboardingVerificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */; };
34A4C62022175C5C0042EF2E /* OnboardingProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */; };
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */; };
34A6C28021E503E700B5B12E /* OWSImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */; };
34A8B3512190A40E00218A25 /* MediaAlbumCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A8B3502190A40E00218A25 /* MediaAlbumCellView.swift */; };
34ABB2C42090C59700C727A6 /* OWSResaveCollectionDBMigration.m in Sources */ = {isa = PBXBuildFile; fileRef = 34ABB2C22090C59600C727A6 /* OWSResaveCollectionDBMigration.m */; };
@ -639,10 +636,6 @@
34074F60203D0CBE004596AE /* OWSSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSounds.h; sourceTree = "<group>"; };
340B02B61F9FD31800F9CFEC /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = translations/he.lproj/Localizable.strings; sourceTree = "<group>"; };
340B02B91FA0D6C700F9CFEC /* ConversationViewItemTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConversationViewItemTest.m; sourceTree = "<group>"; };
340FC876204DAC8C007AEB0F /* RegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RegistrationViewController.m; sourceTree = "<group>"; };
340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodeVerificationViewController.m; sourceTree = "<group>"; };
340FC878204DAC8C007AEB0F /* RegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegistrationViewController.h; sourceTree = "<group>"; };
340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeVerificationViewController.h; sourceTree = "<group>"; };
340FC87B204DAC8C007AEB0F /* NotificationSettingsOptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsOptionsViewController.m; sourceTree = "<group>"; };
340FC87C204DAC8C007AEB0F /* NotificationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsViewController.m; sourceTree = "<group>"; };
340FC87D204DAC8C007AEB0F /* DomainFrontingCountryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DomainFrontingCountryViewController.m; sourceTree = "<group>"; };
@ -852,8 +845,6 @@
349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Onboarding2FAViewController.swift; sourceTree = "<group>"; };
34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingVerificationViewController.swift; sourceTree = "<group>"; };
34A4C61F22175C5C0042EF2E /* OnboardingProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingProfileViewController.swift; sourceTree = "<group>"; };
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWS2FARegistrationViewController.m; sourceTree = "<group>"; };
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWS2FARegistrationViewController.h; sourceTree = "<group>"; };
34A6C27F21E503E600B5B12E /* OWSImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OWSImagePickerController.swift; sourceTree = "<group>"; };
34A8B3502190A40E00218A25 /* MediaAlbumCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaAlbumCellView.swift; sourceTree = "<group>"; };
34ABB2C22090C59600C727A6 /* OWSResaveCollectionDBMigration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSResaveCollectionDBMigration.m; sourceTree = "<group>"; };
@ -1471,8 +1462,6 @@
isa = PBXGroup;
children = (
3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */,
340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */,
340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */,
349ED98F221B0194008045B0 /* Onboarding2FAViewController.swift */,
3448E1612213585C004B052E /* OnboardingBaseViewController.swift */,
3448E1652215B313004B052E /* OnboardingCaptchaViewController.swift */,
@ -1483,8 +1472,6 @@
3448E15F22134C88004B052E /* OnboardingSplashViewController.swift */,
34A4C61D221613D00042EF2E /* OnboardingVerificationViewController.swift */,
346E9D5321B040B600562252 /* RegistrationController.swift */,
340FC878204DAC8C007AEB0F /* RegistrationViewController.h */,
340FC876204DAC8C007AEB0F /* RegistrationViewController.m */,
);
path = Registration;
sourceTree = "<group>";
@ -1871,8 +1858,6 @@
34B3F8501E8DF1700035BE1A /* NewContactThreadViewController.m */,
34B3F8541E8DF1700035BE1A /* NewGroupViewController.h */,
34B3F8551E8DF1700035BE1A /* NewGroupViewController.m */,
34A55F3620485464002CC6DE /* OWS2FARegistrationViewController.h */,
34A55F3520485464002CC6DE /* OWS2FARegistrationViewController.m */,
45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */,
345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */,
345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */,
@ -3515,7 +3500,6 @@
3430FE181F7751D4000EC51B /* GiphyAPI.swift in Sources */,
4C2F454F214C00E1004871FF /* AvatarTableViewCell.swift in Sources */,
346E9D5421B040B700562252 /* RegistrationController.swift in Sources */,
34A55F3720485465002CC6DE /* OWS2FARegistrationViewController.m in Sources */,
340FC8AD204DAC8D007AEB0F /* OWSLinkedDevicesTableViewController.m in Sources */,
340FC8AA204DAC8D007AEB0F /* NotificationSettingsViewController.m in Sources */,
4C090A1B210FD9C7001FD7F9 /* HapticFeedback.swift in Sources */,
@ -3607,7 +3591,6 @@
45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */,
340FC8BB204DAC8D007AEB0F /* OWSAddToContactViewController.m in Sources */,
45F32C232057297A00A300D5 /* MediaPageViewController.swift in Sources */,
340FC8A7204DAC8D007AEB0F /* RegistrationViewController.m in Sources */,
452C468F1E427E200087B011 /* OutboundCallInitiator.swift in Sources */,
34D2CCDA2062E7D000CB1A14 /* OWSScreenLockUI.m in Sources */,
45F170BB1E2FC5D3003FC1F2 /* CallAudioService.swift in Sources */,
@ -3640,7 +3623,6 @@
340FC8B9204DAC8D007AEB0F /* UpdateGroupViewController.m in Sources */,
3448E1662215B313004B052E /* OnboardingCaptchaViewController.swift in Sources */,
4574A5D61DD6704700C6B692 /* CallService.swift in Sources */,
340FC8A8204DAC8D007AEB0F /* CodeVerificationViewController.m in Sources */,
4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */,
34D2CCDF206939B400CB1A14 /* DebugUIMessagesAction.m in Sources */,
340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */,

@ -3,7 +3,6 @@
//
#import "AppDelegate.h"
#import "CodeVerificationViewController.h"
#import "DebugLogger.h"
#import "HomeViewController.h"
#import "MainAppContext.h"
@ -12,7 +11,6 @@
#import "OWSOrphanDataCleaner.h"
#import "OWSScreenLockUI.h"
#import "Pastelog.h"
#import "RegistrationViewController.h"
#import "Signal-Swift.h"
#import "SignalApp.h"
#import "SignalsNavigationController.h"
@ -632,10 +630,11 @@ static NSTimeInterval launchStartedAt;
if ([signupController isKindOfClass:[OWSNavigationController class]]) {
OWSNavigationController *navController = (OWSNavigationController *)signupController;
UIViewController *controller = [navController.childViewControllers lastObject];
if ([controller isKindOfClass:[CodeVerificationViewController class]]) {
CodeVerificationViewController *cvvc = (CodeVerificationViewController *)controller;
if ([controller isKindOfClass:[OnboardingVerificationViewController class]]) {
OnboardingVerificationViewController *verificationView
= (OnboardingVerificationViewController *)controller;
NSString *verificationCode = [url.path substringFromIndex:1];
[cvvc setVerificationCodeAndTryToVerify:verificationCode];
[verificationView setVerificationCodeAndTryToVerify:verificationCode];
return YES;
} else {
OWSLogWarn(@"Not the verification view controller we expected. Got %@ instead",

@ -41,7 +41,6 @@
#import "PinEntryView.h"
#import "PrivacySettingsTableViewController.h"
#import "ProfileViewController.h"
#import "RegistrationViewController.h"
#import "RemoteVideoView.h"
#import "SignalApp.h"
#import "UIViewController+Permissions.h"

@ -7,7 +7,6 @@
#import "OWSBackup.h"
#import "OWSCountryMetadata.h"
#import "OWSTableViewController.h"
#import "RegistrationViewController.h"
#import "Signal-Swift.h"
#import "ThreadUtil.h"
#import <AxolotlKit/PreKeyBundle.h>
@ -168,7 +167,7 @@ NS_ASSUME_NONNULL_BEGIN
[Environment.shared.preferences unsetRecordedAPNSTokens];
RegistrationViewController *viewController = [RegistrationViewController new];
UIViewController *viewController = [[OnboardingController new] initialViewController];
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:viewController];
navigationController.navigationBarHidden = YES;

@ -7,7 +7,6 @@
#import "AppSettingsViewController.h"
#import "HomeViewCell.h"
#import "NewContactThreadViewController.h"
#import "OWS2FARegistrationViewController.h"
#import "OWSNavigationController.h"
#import "OWSPrimaryStorage.h"
#import "ProfileViewController.h"

@ -1,15 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalMessaging/OWSViewController.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWS2FARegistrationViewController : OWSViewController
@property (nonatomic) NSString *verificationCode;
@end
NS_ASSUME_NONNULL_END

@ -1,161 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "OWS2FARegistrationViewController.h"
#import "PinEntryView.h"
#import "ProfileViewController.h"
#import "Signal-Swift.h"
#import <PromiseKit/AnyPromise.h>
#import <SignalMessaging/SignalMessaging-Swift.h>
#import <SignalMessaging/UIViewController+OWS.h>
#import <SignalServiceKit/OWS2FAManager.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWS2FARegistrationViewController () <PinEntryViewDelegate>
@property (nonatomic) PinEntryView *entryView;
@end
#pragma mark -
@implementation OWS2FARegistrationViewController
#pragma mark - Dependencies
- (AccountManager *)accountManager
{
return AppEnvironment.shared.accountManager;
}
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// The navigation bar is hidden in the registration workflow.
if (self.navigationController.navigationBarHidden) {
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
self.navigationItem.hidesBackButton = YES;
self.title = NSLocalizedString(@"REGISTRATION_ENTER_LOCK_PIN_NAV_TITLE",
@"Navigation title shown when user is re-registering after having enabled registration lock");
self.view.backgroundColor = [Theme backgroundColor];
PinEntryView *entryView = [PinEntryView new];
self.entryView = entryView;
entryView.delegate = self;
[self.view addSubview:entryView];
entryView.instructionsText = NSLocalizedString(
@"REGISTER_2FA_INSTRUCTIONS", @"Instructions to enter the 'two-factor auth pin' in the 2FA registration view.");
// Layout
[entryView autoPinToTopLayoutGuideOfViewController:self withInset:0];
[entryView autoPinEdgeToSuperviewMargin:ALEdgeLeft];
[entryView autoPinEdgeToSuperviewMargin:ALEdgeRight];
[entryView autoPinToBottomLayoutGuideOfViewController:self withInset:0];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.entryView makePinTextFieldFirstResponder];
}
#pragma mark - PinEntryViewDelegate
- (void)pinEntryView:(PinEntryView *)entryView submittedPinCode:(NSString *)pinCode
{
OWSAssertDebug(self.entryView.hasValidPin);
[self tryToRegisterWithPinCode:pinCode];
}
- (void)pinEntryViewForgotPinLinkTapped:(PinEntryView *)entryView
{
NSString *alertBody = NSLocalizedString(@"REGISTER_2FA_FORGOT_PIN_ALERT_MESSAGE",
@"Alert message explaining what happens if you forget your 'two-factor auth pin'.");
[OWSAlerts showAlertWithTitle:nil message:alertBody];
}
#pragma mark - Registration
- (void)tryToRegisterWithPinCode:(NSString *)pinCode
{
OWSAssertDebug(self.entryView.hasValidPin);
OWSAssertDebug(self.verificationCode.length > 0);
OWSAssertDebug(pinCode.length > 0);
OWSLogInfo(@"");
__weak OWS2FARegistrationViewController *weakSelf = self;
[ModalActivityIndicatorViewController
presentFromViewController:self
canCancel:NO
backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) {
OWSProdInfo([OWSAnalyticsEvents registrationRegisteringCode]);
[[self.accountManager registerObjcWithVerificationCode:self.verificationCode pin:pinCode]
.then(^{
OWSAssertIsOnMainThread();
OWSProdInfo([OWSAnalyticsEvents registrationRegisteringSubmittedCode]);
[[OWS2FAManager sharedManager] mark2FAAsEnabledWithPin:pinCode];
OWSLogInfo(@"Successfully registered Signal account.");
dispatch_async(dispatch_get_main_queue(), ^{
[modalActivityIndicator dismissWithCompletion:^{
OWSAssertIsOnMainThread();
[weakSelf verificationWasCompleted];
}];
});
})
.catch(^(NSError *error) {
OWSAssertIsOnMainThread();
OWSProdInfo([OWSAnalyticsEvents registrationRegistrationFailed]);
OWSLogError(@"error verifying challenge: %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
[modalActivityIndicator dismissWithCompletion:^{
OWSAssertIsOnMainThread();
[OWSAlerts
showAlertWithTitle:NSLocalizedString(
@"REGISTER_2FA_REGISTRATION_FAILED_ALERT_TITLE",
@"Title for alert indicating that attempt to "
@"register with 'two-factor auth' failed.")
message:error.localizedDescription];
[weakSelf.entryView makePinTextFieldFirstResponder];
}];
});
}) retainUntilComplete];
}];
}
- (void)verificationWasCompleted
{
[RegistrationController verificationWasCompletedFromView:self];
}
#pragma mark - Orientation
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
@end
NS_ASSUME_NONNULL_END

@ -1,15 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalMessaging/OWSViewController.h>
NS_ASSUME_NONNULL_BEGIN
@interface CodeVerificationViewController : OWSViewController
- (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode;
@end
NS_ASSUME_NONNULL_END

@ -1,509 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "CodeVerificationViewController.h"
#import "OWS2FARegistrationViewController.h"
#import "ProfileViewController.h"
#import "Signal-Swift.h"
#import <PromiseKit/AnyPromise.h>
#import <SignalMessaging/UIViewController+OWS.h>
#import <SignalServiceKit/OWSError.h>
#import <SignalServiceKit/TSAccountManager.h>
#import <SignalServiceKit/TSNetworkManager.h>
NS_ASSUME_NONNULL_BEGIN
@interface CodeVerificationViewController () <UITextFieldDelegate>
// Where the user enters the verification code they wish to document
@property (nonatomic) UITextField *challengeTextField;
@property (nonatomic) UILabel *phoneNumberLabel;
//// User action buttons
@property (nonatomic) OWSFlatButton *submitButton;
@property (nonatomic) UIButton *sendCodeViaSMSAgainButton;
@property (nonatomic) UIButton *sendCodeViaVoiceButton;
@property (nonatomic) UIActivityIndicatorView *submitCodeSpinner;
@property (nonatomic) UIActivityIndicatorView *requestCodeAgainSpinner;
@property (nonatomic) UIActivityIndicatorView *requestCallSpinner;
@end
#pragma mark -
@implementation CodeVerificationViewController
#pragma mark - Dependencies
- (TSAccountManager *)tsAccountManager
{
OWSAssertDebug(SSKEnvironment.shared.tsAccountManager);
return SSKEnvironment.shared.tsAccountManager;
}
- (AccountManager *)accountManager
{
return AppEnvironment.shared.accountManager;
}
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.shouldUseTheme = NO;
[self createViews];
[self initializeKeyboardHandlers];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self enableServerActions:YES];
[self updatePhoneNumberLabel];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[_challengeTextField becomeFirstResponder];
}
#pragma mark -
- (void)createViews
{
self.view.backgroundColor = [UIColor whiteColor];
self.view.opaque = YES;
UIColor *signalBlueColor = [UIColor ows_signalBrandBlueColor];
UIView *header = [UIView new];
header.backgroundColor = signalBlueColor;
[self.view addSubview:header];
[header autoPinWidthToSuperview];
[header autoPinEdgeToSuperviewEdge:ALEdgeTop];
// The header will grow to accomodate the titleLabel's height.
UILabel *titleLabel = [UILabel new];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.text = [self phoneNumberText];
titleLabel.font = [UIFont ows_mediumFontWithSize:20.f];
[header addSubview:titleLabel];
[titleLabel autoPinToTopLayoutGuideOfViewController:self withInset:0];
[titleLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[titleLabel autoSetDimension:ALDimensionHeight toSize:40];
[titleLabel autoHCenterInSuperview];
// This view is used in more than one context.
//
// * Usually, it is pushed atop RegistrationViewController in which
// case we want a "back" button.
// * It can also be used to re-register from the app's "de-registration"
// views, in which case RegistrationViewController is not used and we
// do _not_ want a "back" button.
if (self.navigationController.viewControllers.count > 1) {
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton
setTitle:NSLocalizedString(@"VERIFICATION_BACK_BUTTON", @"button text for back button on verification view")
forState:UIControlStateNormal];
[backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
backButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f];
[header addSubview:backButton];
[backButton autoPinLeadingToSuperviewMarginWithInset:10.f];
[backButton autoAlignAxis:ALAxisHorizontal toSameAxisOfView:titleLabel];
[backButton addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
}
_phoneNumberLabel = [UILabel new];
_phoneNumberLabel.textColor = [UIColor ows_darkGrayColor];
_phoneNumberLabel.font = [UIFont ows_regularFontWithSize:20.f];
_phoneNumberLabel.numberOfLines = 2;
_phoneNumberLabel.adjustsFontSizeToFitWidth = YES;
_phoneNumberLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:_phoneNumberLabel];
[_phoneNumberLabel autoPinWidthToSuperviewWithMargin:ScaleFromIPhone5(32)];
[_phoneNumberLabel autoPinEdge:ALEdgeTop
toEdge:ALEdgeBottom
ofView:header
withOffset:ScaleFromIPhone5To7Plus(30, 100)];
const CGFloat kHMargin = 36;
if (UIDevice.currentDevice.isShorterThanIPhone5) {
_challengeTextField = [DismissableTextField new];
} else {
_challengeTextField = [OWSTextField new];
}
_challengeTextField.textColor = [UIColor blackColor];
_challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT",
@"Text field placeholder for SMS verification code during registration");
_challengeTextField.font = [UIFont ows_lightFontWithSize:21.f];
_challengeTextField.textAlignment = NSTextAlignmentCenter;
_challengeTextField.keyboardType = UIKeyboardTypeNumberPad;
_challengeTextField.delegate = self;
[self.view addSubview:_challengeTextField];
[_challengeTextField autoPinWidthToSuperviewWithMargin:kHMargin];
[_challengeTextField autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_phoneNumberLabel withOffset:25];
UIView *underscoreView = [UIView new];
underscoreView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1.f];
[self.view addSubview:underscoreView];
[underscoreView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_challengeTextField withOffset:3];
[underscoreView autoPinWidthToSuperviewWithMargin:kHMargin];
[underscoreView autoSetDimension:ALDimensionHeight toSize:1.f];
const CGFloat kSubmitButtonHeight = 47.f;
// NOTE: We use ows_signalBrandBlueColor instead of ows_materialBlueColor
// throughout the onboarding flow to be consistent with the headers.
OWSFlatButton *submitButton =
[OWSFlatButton buttonWithTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE",
@"button text during registration to submit your SMS verification code.")
font:[OWSFlatButton fontForHeight:kSubmitButtonHeight]
titleColor:[UIColor whiteColor]
backgroundColor:[UIColor ows_signalBrandBlueColor]
target:self
selector:@selector(submitVerificationCode)];
self.submitButton = submitButton;
[self.view addSubview:_submitButton];
[_submitButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:underscoreView withOffset:15];
[_submitButton autoPinWidthToSuperviewWithMargin:kHMargin];
[_submitButton autoSetDimension:ALDimensionHeight toSize:kSubmitButtonHeight];
const CGFloat kSpinnerSize = 20;
const CGFloat kSpinnerSpacing = ScaleFromIPhone5To7Plus(5, 15);
_submitCodeSpinner =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[_submitButton addSubview:_submitCodeSpinner];
[_submitCodeSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize];
[_submitCodeSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize];
[_submitCodeSpinner autoVCenterInSuperview];
[_submitCodeSpinner autoPinTrailingToSuperviewMarginWithInset:kSpinnerSpacing];
_sendCodeViaSMSAgainButton = [UIButton buttonWithType:UIButtonTypeCustom];
_sendCodeViaSMSAgainButton.backgroundColor = [UIColor whiteColor];
[_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN",
@"button text during registration to request another SMS code be sent")
forState:UIControlStateNormal];
[_sendCodeViaSMSAgainButton setTitleColor:signalBlueColor forState:UIControlStateNormal];
_sendCodeViaSMSAgainButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f];
[_sendCodeViaSMSAgainButton addTarget:self
action:@selector(sendCodeViaSMSAction:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_sendCodeViaSMSAgainButton];
[_sendCodeViaSMSAgainButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_submitButton withOffset:10];
[_sendCodeViaSMSAgainButton autoPinWidthToSuperviewWithMargin:kHMargin];
[_sendCodeViaSMSAgainButton autoSetDimension:ALDimensionHeight toSize:35];
_requestCodeAgainSpinner =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[_sendCodeViaSMSAgainButton addSubview:_requestCodeAgainSpinner];
[_requestCodeAgainSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize];
[_requestCodeAgainSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize];
[_requestCodeAgainSpinner autoVCenterInSuperview];
[_requestCodeAgainSpinner autoPinTrailingToSuperviewMarginWithInset:kSpinnerSpacing];
_sendCodeViaVoiceButton = [UIButton buttonWithType:UIButtonTypeCustom];
_sendCodeViaVoiceButton.backgroundColor = [UIColor whiteColor];
[_sendCodeViaVoiceButton
setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIA_VOICE",
@"button text during registration to request phone number verification be done via phone call")
forState:UIControlStateNormal];
[_sendCodeViaVoiceButton setTitleColor:signalBlueColor forState:UIControlStateNormal];
_sendCodeViaVoiceButton.titleLabel.font = [UIFont ows_mediumFontWithSize:14.f];
[_sendCodeViaVoiceButton addTarget:self
action:@selector(sendCodeViaVoiceAction:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_sendCodeViaVoiceButton];
[_sendCodeViaVoiceButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:_sendCodeViaSMSAgainButton];
[_sendCodeViaVoiceButton autoPinWidthToSuperviewWithMargin:kHMargin];
[_sendCodeViaVoiceButton autoSetDimension:ALDimensionHeight toSize:35];
_requestCallSpinner =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[_sendCodeViaVoiceButton addSubview:_requestCallSpinner];
[_requestCallSpinner autoSetDimension:ALDimensionWidth toSize:kSpinnerSize];
[_requestCallSpinner autoSetDimension:ALDimensionHeight toSize:kSpinnerSize];
[_requestCallSpinner autoVCenterInSuperview];
[_requestCallSpinner autoPinTrailingToSuperviewMarginWithInset:kSpinnerSpacing];
}
- (NSString *)phoneNumberText
{
OWSAssertDebug([TSAccountManager localNumber] != nil);
return [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:[TSAccountManager localNumber]];
}
- (void)updatePhoneNumberLabel
{
_phoneNumberLabel.text =
[NSString stringWithFormat:NSLocalizedString(@"VERIFICATION_PHONE_NUMBER_FORMAT",
@"Label indicating the phone number currently being verified."),
[self phoneNumberText]];
}
- (void)startActivityIndicator
{
[self.submitCodeSpinner startAnimating];
[self enableServerActions:NO];
[self.challengeTextField resignFirstResponder];
}
- (void)stopActivityIndicator
{
[self enableServerActions:YES];
[self.submitCodeSpinner stopAnimating];
}
- (void)submitVerificationCode
{
[self startActivityIndicator];
OWSProdInfo([OWSAnalyticsEvents registrationRegisteringCode]);
__weak CodeVerificationViewController *weakSelf = self;
[[self.accountManager registerObjcWithVerificationCode:[self validationCodeFromTextField] pin:nil]
.then(^{
OWSProdInfo([OWSAnalyticsEvents registrationRegisteringSubmittedCode]);
OWSLogInfo(@"Successfully registered Signal account.");
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf stopActivityIndicator];
[weakSelf verificationWasCompleted];
});
})
.catch(^(NSError *error) {
OWSLogError(@"error: %@, %@, %zd", [error class], error.domain, error.code);
OWSProdInfo([OWSAnalyticsEvents registrationRegistrationFailed]);
OWSLogError(@"error verifying challenge: %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf stopActivityIndicator];
if ([error.domain isEqualToString:OWSSignalServiceKitErrorDomain]
&& error.code == OWSErrorCodeRegistrationMissing2FAPIN) {
CodeVerificationViewController *strongSelf = weakSelf;
if (!strongSelf) {
return;
}
OWSLogInfo(@"Showing 2FA registration view.");
OWS2FARegistrationViewController *viewController = [OWS2FARegistrationViewController new];
viewController.verificationCode = strongSelf.validationCodeFromTextField;
[strongSelf.navigationController pushViewController:viewController animated:YES];
} else {
[weakSelf presentAlertWithVerificationError:error];
[weakSelf.challengeTextField becomeFirstResponder];
}
});
}) retainUntilComplete];
}
- (void)verificationWasCompleted
{
[RegistrationController verificationWasCompletedFromView:self];
}
- (void)presentAlertWithVerificationError:(NSError *)error
{
UIAlertController *alert;
alert = [UIAlertController
alertControllerWithTitle:NSLocalizedString(@"REGISTRATION_VERIFICATION_FAILED_TITLE", @"Alert view title")
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:CommonStrings.dismissButton
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self.challengeTextField becomeFirstResponder];
}]];
[self presentViewController:alert animated:YES completion:nil];
}
- (NSString *)validationCodeFromTextField
{
return [self.challengeTextField.text stringByReplacingOccurrencesOfString:@"-" withString:@""];
}
#pragma mark - Actions
- (void)sendCodeViaSMSAction:(id)sender
{
OWSProdInfo([OWSAnalyticsEvents registrationRegisteringRequestedNewCodeBySms]);
[self enableServerActions:NO];
[_requestCodeAgainSpinner startAnimating];
__weak CodeVerificationViewController *weakSelf = self;
[self.tsAccountManager rerequestSMSWithCaptchaToken:nil
success:^{
OWSLogInfo(@"Successfully requested SMS code");
[weakSelf enableServerActions:YES];
[weakSelf.requestCodeAgainSpinner stopAnimating];
}
failure:^(NSError *error) {
OWSLogError(@"Failed to request SMS code with error: %@", error);
[weakSelf showRegistrationErrorMessage:error];
[weakSelf enableServerActions:YES];
[weakSelf.requestCodeAgainSpinner stopAnimating];
[weakSelf.challengeTextField becomeFirstResponder];
}];
}
- (void)sendCodeViaVoiceAction:(id)sender
{
OWSProdInfo([OWSAnalyticsEvents registrationRegisteringRequestedNewCodeByVoice]);
[self enableServerActions:NO];
[_requestCallSpinner startAnimating];
__weak CodeVerificationViewController *weakSelf = self;
[self.tsAccountManager rerequestVoiceWithCaptchaToken:nil
success:^{
OWSLogInfo(@"Successfully requested voice code");
[weakSelf enableServerActions:YES];
[weakSelf.requestCallSpinner stopAnimating];
}
failure:^(NSError *error) {
OWSLogError(@"Failed to request voice code with error: %@", error);
[weakSelf showRegistrationErrorMessage:error];
[weakSelf enableServerActions:YES];
[weakSelf.requestCallSpinner stopAnimating];
[weakSelf.challengeTextField becomeFirstResponder];
}];
}
- (void)showRegistrationErrorMessage:(NSError *)registrationError
{
[OWSAlerts showAlertWithTitle:registrationError.localizedDescription
message:registrationError.localizedRecoverySuggestion];
}
- (void)enableServerActions:(BOOL)enabled
{
[_submitButton setEnabled:enabled];
[_sendCodeViaSMSAgainButton setEnabled:enabled];
[_sendCodeViaVoiceButton setEnabled:enabled];
}
- (void)backButtonPressed:(id)sender
{
OWSProdInfo([OWSAnalyticsEvents registrationVerificationBack]);
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - Keyboard notifications
- (void)initializeKeyboardHandlers
{
UITapGestureRecognizer *outsideTabRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)];
[self.view addGestureRecognizer:outsideTabRecognizer];
self.view.userInteractionEnabled = YES;
}
- (void)dismissKeyboardFromAppropriateSubView
{
[self.view endEditing:NO];
}
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)insertionText
{
// Verification codes take this form: "123-456".
//
// * We only want to let the user "6 decimal digits + 1 hyphen = 7".
// * The user shouldn't have to enter the hyphen - it should be added automatically.
// * The user should be able to copy and paste freely.
// * Invalid input (including extraneous hyphens) should be simply ignored.
//
// We accomplish this by being permissive and trying to "take as much of the user
// input as possible".
//
// * Always accept deletes.
// * Ignore invalid input.
// * Take partial input if possible.
NSString *oldText = textField.text;
// Construct the new contents of the text field by:
// 1. Determining the "left" substring: the contents of the old text _before_ the deletion range.
// Filtering will remove non-decimal digit characters like hyphen "-".
NSString *left = [oldText substringToIndex:range.location].digitsOnly;
// 2. Determining the "right" substring: the contents of the old text _after_ the deletion range.
NSString *right = [oldText substringFromIndex:range.location + range.length].digitsOnly;
// 3. Determining the "center" substring: the contents of the new insertion text.
NSString *center = insertionText.digitsOnly;
// 3a. Trim the tail of the "center" substring to ensure that we don't end up
// with more than 6 decimal digits.
while (center.length > 0 && left.length + center.length + right.length > 6) {
center = [center substringToIndex:center.length - 1];
}
// 4. Construct the "raw" new text by concatenating left, center and right.
NSString *rawNewText = [[left stringByAppendingString:center] stringByAppendingString:right];
// 5. Construct the "formatted" new text by inserting a hyphen if necessary.
NSString *formattedNewText
= (rawNewText.length <= 3 ? rawNewText
: [[[rawNewText substringToIndex:3] stringByAppendingString:@"-"]
stringByAppendingString:[rawNewText substringFromIndex:3]]);
textField.text = formattedNewText;
// Move the cursor after the newly inserted text.
NSUInteger newInsertionPoint = left.length + center.length;
if (newInsertionPoint > 3) {
// Nudge the cursor to the right to reflect the hyphen
// if necessary.
newInsertionPoint++;
}
UITextPosition *newPosition =
[textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)newInsertionPoint];
textField.selectedTextRange = [textField textRangeFromPosition:newPosition toPosition:newPosition];
return NO;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self submitVerificationCode];
[textField resignFirstResponder];
return NO;
}
- (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode
{
NSString *rawNewText = verificationCode.digitsOnly;
NSString *formattedNewText
= (rawNewText.length <= 3 ? rawNewText
: [[[rawNewText substringToIndex:3] stringByAppendingString:@"-"]
stringByAppendingString:[rawNewText substringFromIndex:3]]);
self.challengeTextField.text = formattedNewText;
// Move the cursor after the newly inserted text.
UITextPosition *newPosition = [self.challengeTextField endOfDocument];
self.challengeTextField.selectedTextRange =
[self.challengeTextField textRangeFromPosition:newPosition toPosition:newPosition];
[self submitVerificationCode];
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#pragma mark - Orientation
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
@end
NS_ASSUME_NONNULL_END

@ -187,6 +187,14 @@ private class OnboardingCodeView: UIView {
digitStroke.backgroundColor = backgroundColor
}
}
fileprivate func set(verificationCode: String) {
digitText = verificationCode
updateViewState()
self.delegate?.codeViewDidChange()
}
}
// MARK: -
@ -251,10 +259,16 @@ public class OnboardingVerificationViewController: OnboardingBaseViewController
private var codeState = CodeState.sent
private var titleLabel: UILabel?
private var backLink: UIView?
private let onboardingCodeView = OnboardingCodeView()
private var codeStateLink: OWSFlatButton?
private let errorLabel = UILabel()
@objc
public func hideBackLink() {
backLink?.isHidden = true
}
override public func loadView() {
super.loadView()
@ -267,6 +281,7 @@ public class OnboardingVerificationViewController: OnboardingBaseViewController
let backLink = self.linkButton(title: NSLocalizedString("ONBOARDING_VERIFICATION_BACK_LINK",
comment: "Label for the link that lets users change their phone number in the onboarding views."),
selector: #selector(backLinkTapped))
self.backLink = backLink
onboardingCodeView.delegate = self
@ -495,6 +510,19 @@ public class OnboardingVerificationViewController: OnboardingBaseViewController
onboardingCodeView.setHasError(value)
errorLabel.isHidden = !value
}
@objc
public func setVerificationCodeAndTryToVerify(_ verificationCode: String) {
AssertIsOnMainThread()
let filteredCode = verificationCode.digitsOnly
guard filteredCode.count > 0 else {
owsFailDebug("Invalid code: \(verificationCode)")
return
}
onboardingCodeView.set(verificationCode: filteredCode)
}
}
// MARK: -

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import UIKit
@ -23,30 +23,6 @@ public class RegistrationController: NSObject {
// MARK: -
@objc
public class func verificationWasCompleted(fromView view: UIViewController) {
AssertIsOnMainThread()
if tsAccountManager.isReregistering() {
showProfileView(fromView: view)
} else {
checkCanImportBackup(fromView: view)
}
}
private class func showProfileView(fromView view: UIViewController) {
AssertIsOnMainThread()
Logger.info("")
guard let navigationController = view.navigationController else {
owsFailDebug("Missing navigationController")
return
}
ProfileViewController.present(forRegistration: navigationController)
}
private class func showBackupRestoreView(fromView view: UIViewController) {
AssertIsOnMainThread()
@ -61,44 +37,45 @@ public class RegistrationController: NSObject {
navigationController.setViewControllers([restoreView], animated: true)
}
private class func checkCanImportBackup(fromView view: UIViewController) {
AssertIsOnMainThread()
Logger.info("")
self.backup.checkCanImport({ (canImport) in
Logger.info("canImport: \(canImport)")
if (canImport) {
self.backup.setHasPendingRestoreDecision(true)
self.showBackupRestoreView(fromView: view)
} else {
self.showProfileView(fromView: view)
}
}) { (_) in
self.showBackupCheckFailedAlert(fromView: view)
}
}
private class func showBackupCheckFailedAlert(fromView view: UIViewController) {
AssertIsOnMainThread()
Logger.info("")
let alert = UIAlertController(title: NSLocalizedString("CHECK_FOR_BACKUP_FAILED_TITLE",
comment: "Title for alert shown when the app failed to check for an existing backup."),
message: NSLocalizedString("CHECK_FOR_BACKUP_FAILED_MESSAGE",
comment: "Message for alert shown when the app failed to check for an existing backup."),
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("REGISTER_FAILED_TRY_AGAIN", comment: ""),
style: .default) { (_) in
self.checkCanImportBackup(fromView: view)
})
alert.addAction(UIAlertAction(title: NSLocalizedString("CHECK_FOR_BACKUP_DO_NOT_RESTORE", comment: "The label for the 'do not restore backup' button."),
style: .destructive) { (_) in
self.showProfileView(fromView: view)
})
view.present(alert, animated: true)
}
// TODO: OnboardingController will eventually need to do something like this.
// private class func checkCanImportBackup(fromView view: UIViewController) {
// AssertIsOnMainThread()
//
// Logger.info("")
//
// self.backup.checkCanImport({ (canImport) in
// Logger.info("canImport: \(canImport)")
//
// if (canImport) {
// self.backup.setHasPendingRestoreDecision(true)
//
// self.showBackupRestoreView(fromView: view)
// } else {
// self.showProfileView(fromView: view)
// }
// }) { (_) in
// self.showBackupCheckFailedAlert(fromView: view)
// }
// }
//
// private class func showBackupCheckFailedAlert(fromView view: UIViewController) {
// AssertIsOnMainThread()
//
// Logger.info("")
//
// let alert = UIAlertController(title: NSLocalizedString("CHECK_FOR_BACKUP_FAILED_TITLE",
// comment: "Title for alert shown when the app failed to check for an existing backup."),
// message: NSLocalizedString("CHECK_FOR_BACKUP_FAILED_MESSAGE",
// comment: "Message for alert shown when the app failed to check for an existing backup."),
// preferredStyle: .alert)
// alert.addAction(UIAlertAction(title: NSLocalizedString("REGISTER_FAILED_TRY_AGAIN", comment: ""),
// style: .default) { (_) in
// self.checkCanImportBackup(fromView: view)
// })
// alert.addAction(UIAlertAction(title: NSLocalizedString("CHECK_FOR_BACKUP_DO_NOT_RESTORE", comment: "The label for the 'do not restore backup' button."),
// style: .destructive) { (_) in
// self.showProfileView(fromView: view)
// })
// view.present(alert, animated: true)
// }
}

@ -1,13 +0,0 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import <SignalMessaging/OWSViewController.h>
NS_ASSUME_NONNULL_BEGIN
@interface RegistrationViewController : OWSViewController
@end
NS_ASSUME_NONNULL_END

@ -1,646 +0,0 @@
//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
#import "RegistrationViewController.h"
#import "CodeVerificationViewController.h"
#import "CountryCodeViewController.h"
#import "PhoneNumber.h"
#import "PhoneNumberUtil.h"
#import "Signal-Swift.h"
#import "TSAccountManager.h"
#import "UIView+OWS.h"
#import "ViewControllerUtils.h"
#import <SignalMessaging/Environment.h>
#import <SignalMessaging/OWSNavigationController.h>
#import <SignalServiceKit/NSString+SSK.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h>
#import <SignalMessaging/UIUtil.h>
NS_ASSUME_NONNULL_BEGIN
#ifdef DEBUG
NSString *const kKeychainService_LastRegistered = @"kKeychainService_LastRegistered";
NSString *const kKeychainKey_LastRegisteredCountryCode = @"kKeychainKey_LastRegisteredCountryCode";
NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegisteredPhoneNumber";
#endif
@interface RegistrationViewController () <CountryCodeViewControllerDelegate, UITextFieldDelegate>
@property (nonatomic) NSString *countryCode;
@property (nonatomic) NSString *callingCode;
@property (nonatomic) UILabel *countryCodeLabel;
@property (nonatomic) UITextField *phoneNumberTextField;
@property (nonatomic) UILabel *examplePhoneNumberLabel;
@property (nonatomic) OWSFlatButton *activateButton;
@property (nonatomic) UIActivityIndicatorView *spinnerView;
@end
#pragma mark -
@implementation RegistrationViewController
#pragma mark - Dependencies
- (TSAccountManager *)tsAccountManager
{
OWSAssertDebug(SSKEnvironment.shared.tsAccountManager);
return SSKEnvironment.shared.tsAccountManager;
}
#pragma mark -
- (void)loadView
{
[super loadView];
self.shouldUseTheme = NO;
[self createViews];
// Do any additional setup after loading the view.
[self populateDefaultCountryNameAndCode];
OWSAssertDebug([self.navigationController isKindOfClass:[OWSNavigationController class]]);
[SignalApp.sharedApp setSignUpFlowNavigationController:(OWSNavigationController *)self.navigationController];
}
- (void)viewDidLoad
{
[super viewDidLoad];
OWSProdInfo([OWSAnalyticsEvents registrationBegan]);
}
- (void)createViews
{
self.view.backgroundColor = [UIColor whiteColor];
self.view.userInteractionEnabled = YES;
[self.view
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backgroundTapped:)]];
self.view.accessibilityIdentifier = SUBVIEW_ACCESSIBILITY_IDENTIFIER(self, @"root_view");
UIView *headerWrapper = [UIView containerView];
[self.view addSubview:headerWrapper];
headerWrapper.backgroundColor = UIColor.ows_signalBrandBlueColor;
[headerWrapper autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero excludingEdge:ALEdgeBottom];
UILabel *headerLabel = [UILabel new];
headerLabel.text = NSLocalizedString(@"REGISTRATION_TITLE_LABEL", @"");
headerLabel.textColor = [UIColor whiteColor];
headerLabel.font = [UIFont ows_mediumFontWithSize:ScaleFromIPhone5To7Plus(20.f, 24.f)];
NSString *legalTopMatterFormat = NSLocalizedString(@"REGISTRATION_LEGAL_TOP_MATTER_FORMAT",
@"legal disclaimer, embeds a tappable {{link title}} which is styled as a hyperlink");
NSString *legalTopMatterLinkWord = NSLocalizedString(
@"REGISTRATION_LEGAL_TOP_MATTER_LINK_TITLE", @"embedded in legal topmatter, styled as a link");
NSString *legalTopMatter = [NSString stringWithFormat:legalTopMatterFormat, legalTopMatterLinkWord];
NSMutableAttributedString *attributedLegalTopMatter =
[[NSMutableAttributedString alloc] initWithString:legalTopMatter];
NSRange linkRange = [legalTopMatter rangeOfString:legalTopMatterLinkWord];
NSDictionary *linkStyleAttributes = @{
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid),
};
[attributedLegalTopMatter setAttributes:linkStyleAttributes range:linkRange];
UILabel *legalTopMatterLabel = [UILabel new];
legalTopMatterLabel.textColor = UIColor.whiteColor;
legalTopMatterLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)];
legalTopMatterLabel.numberOfLines = 0;
legalTopMatterLabel.textAlignment = NSTextAlignmentCenter;
legalTopMatterLabel.attributedText = attributedLegalTopMatter;
legalTopMatterLabel.userInteractionEnabled = YES;
SET_SUBVIEW_ACCESSIBILITY_IDENTIFIER(self, legalTopMatterLabel);
UITapGestureRecognizer *tapGesture =
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapLegalTerms:)];
[legalTopMatterLabel addGestureRecognizer:tapGesture];
UIStackView *headerContent = [[UIStackView alloc] initWithArrangedSubviews:@[ headerLabel ]];
[headerContent addArrangedSubview:legalTopMatterLabel];
headerContent.axis = UILayoutConstraintAxisVertical;
headerContent.alignment = UIStackViewAlignmentCenter;
headerContent.spacing = ScaleFromIPhone5To7Plus(8, 16);
headerContent.layoutMarginsRelativeArrangement = YES;
{
CGFloat topMargin = ScaleFromIPhone5To7Plus(4, 16);
CGFloat bottomMargin = ScaleFromIPhone5To7Plus(8, 16);
headerContent.layoutMargins = UIEdgeInsetsMake(topMargin, 40, bottomMargin, 40);
}
[headerWrapper addSubview:headerContent];
[headerContent autoPinToTopLayoutGuideOfViewController:self withInset:0];
[headerContent autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeTop];
const CGFloat kRowHeight = 60.f;
const CGFloat kRowHMargin = 20.f;
const CGFloat kSeparatorHeight = 1.f;
const CGFloat kExamplePhoneNumberVSpacing = 8.f;
const CGFloat fontSizePoints = ScaleFromIPhone5To7Plus(16.f, 20.f);
UIView *contentView = [UIView containerView];
[contentView setHLayoutMargins:kRowHMargin];
contentView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:contentView];
[contentView autoPinToBottomLayoutGuideOfViewController:self withInset:0];
[contentView autoPinWidthToSuperview];
[contentView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:headerContent];
// Country
UIView *countryRow = [UIView containerView];
[contentView addSubview:countryRow];
[countryRow autoPinLeadingAndTrailingToSuperviewMargin];
[countryRow autoPinEdgeToSuperviewEdge:ALEdgeTop];
[countryRow autoSetDimension:ALDimensionHeight toSize:kRowHeight];
[countryRow
addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(countryCodeRowWasTapped:)]];
SET_SUBVIEW_ACCESSIBILITY_IDENTIFIER(self, countryRow);
UILabel *countryNameLabel = [UILabel new];
countryNameLabel.text
= NSLocalizedString(@"REGISTRATION_DEFAULT_COUNTRY_NAME", @"Label for the country code field");
countryNameLabel.textColor = [UIColor blackColor];
countryNameLabel.font = [UIFont ows_mediumFontWithSize:fontSizePoints];
[countryRow addSubview:countryNameLabel];
[countryNameLabel autoVCenterInSuperview];
[countryNameLabel autoPinLeadingToSuperviewMargin];
UILabel *countryCodeLabel = [UILabel new];
self.countryCodeLabel = countryCodeLabel;
countryCodeLabel.textColor = [UIColor ows_materialBlueColor];
countryCodeLabel.font = [UIFont ows_mediumFontWithSize:fontSizePoints + 2.f];
[countryRow addSubview:countryCodeLabel];
[countryCodeLabel autoVCenterInSuperview];
[countryCodeLabel autoPinTrailingToSuperviewMargin];
UIView *separatorView1 = [UIView new];
separatorView1.backgroundColor = [UIColor colorWithWhite:0.75f alpha:1.f];
[contentView addSubview:separatorView1];
[separatorView1 autoPinWidthToSuperview];
[separatorView1 autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:countryRow];
[separatorView1 autoSetDimension:ALDimensionHeight toSize:kSeparatorHeight];
// Phone Number
UIView *phoneNumberRow = [UIView containerView];
[contentView addSubview:phoneNumberRow];
[phoneNumberRow autoPinLeadingAndTrailingToSuperviewMargin];
[phoneNumberRow autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:separatorView1];
[phoneNumberRow autoSetDimension:ALDimensionHeight toSize:kRowHeight];
UILabel *phoneNumberLabel = [UILabel new];
phoneNumberLabel.text
= NSLocalizedString(@"REGISTRATION_PHONENUMBER_BUTTON", @"Label for the phone number textfield");
phoneNumberLabel.textColor = [UIColor blackColor];
phoneNumberLabel.font = [UIFont ows_mediumFontWithSize:fontSizePoints];
[phoneNumberRow addSubview:phoneNumberLabel];
[phoneNumberLabel autoVCenterInSuperview];
[phoneNumberLabel autoPinLeadingToSuperviewMargin];
UITextField *phoneNumberTextField;
if (UIDevice.currentDevice.isShorterThanIPhone5) {
phoneNumberTextField = [DismissableTextField new];
} else {
phoneNumberTextField = [OWSTextField new];
}
phoneNumberTextField.textAlignment = NSTextAlignmentRight;
phoneNumberTextField.delegate = self;
phoneNumberTextField.keyboardType = UIKeyboardTypeNumberPad;
phoneNumberTextField.placeholder = NSLocalizedString(
@"REGISTRATION_ENTERNUMBER_DEFAULT_TEXT", @"Placeholder text for the phone number textfield");
self.phoneNumberTextField = phoneNumberTextField;
phoneNumberTextField.textColor = [UIColor ows_materialBlueColor];
phoneNumberTextField.font = [UIFont ows_mediumFontWithSize:fontSizePoints + 2];
[phoneNumberRow addSubview:phoneNumberTextField];
[phoneNumberTextField autoVCenterInSuperview];
[phoneNumberTextField autoPinTrailingToSuperviewMargin];
SET_SUBVIEW_ACCESSIBILITY_IDENTIFIER(self, phoneNumberTextField);
UILabel *examplePhoneNumberLabel = [UILabel new];
self.examplePhoneNumberLabel = examplePhoneNumberLabel;
examplePhoneNumberLabel.font = [UIFont ows_regularFontWithSize:fontSizePoints - 2.f];
examplePhoneNumberLabel.textColor = Theme.middleGrayColor;
[contentView addSubview:examplePhoneNumberLabel];
[examplePhoneNumberLabel autoPinTrailingToSuperviewMargin];
[examplePhoneNumberLabel autoPinEdge:ALEdgeTop
toEdge:ALEdgeBottom
ofView:phoneNumberTextField
withOffset:kExamplePhoneNumberVSpacing];
UIView *separatorView2 = [UIView new];
separatorView2.backgroundColor = [UIColor colorWithWhite:0.75f alpha:1.f];
[contentView addSubview:separatorView2];
[separatorView2 autoPinWidthToSuperview];
[separatorView2 autoPinEdge:ALEdgeTop
toEdge:ALEdgeBottom
ofView:phoneNumberRow
withOffset:examplePhoneNumberLabel.font.lineHeight];
[separatorView2 autoSetDimension:ALDimensionHeight toSize:kSeparatorHeight];
// Activate Button
const CGFloat kActivateButtonHeight = 47.f;
// NOTE: We use ows_signalBrandBlueColor instead of ows_materialBlueColor
// throughout the onboarding flow to be consistent with the headers.
OWSFlatButton *activateButton = [OWSFlatButton buttonWithTitle:NSLocalizedString(@"REGISTRATION_VERIFY_DEVICE", @"")
font:[OWSFlatButton fontForHeight:kActivateButtonHeight]
titleColor:[UIColor whiteColor]
backgroundColor:[UIColor ows_signalBrandBlueColor]
target:self
selector:@selector(didTapRegisterButton)];
self.activateButton = activateButton;
[contentView addSubview:activateButton];
[activateButton autoPinLeadingAndTrailingToSuperviewMargin];
[activateButton autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:separatorView2 withOffset:15];
[activateButton autoSetDimension:ALDimensionHeight toSize:kActivateButtonHeight];
SET_SUBVIEW_ACCESSIBILITY_IDENTIFIER(self, activateButton);
UIActivityIndicatorView *spinnerView =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
self.spinnerView = spinnerView;
[activateButton addSubview:spinnerView];
[spinnerView autoVCenterInSuperview];
[spinnerView autoSetDimension:ALDimensionWidth toSize:20.f];
[spinnerView autoSetDimension:ALDimensionHeight toSize:20.f];
[spinnerView autoPinTrailingToSuperviewMarginWithInset:20.f];
[spinnerView stopAnimating];
NSString *bottomTermsLinkText = NSLocalizedString(@"REGISTRATION_LEGAL_TERMS_LINK",
@"one line label below submit button on registration screen, which links to an external webpage.");
UIButton *bottomLegalLinkButton = [UIButton new];
bottomLegalLinkButton.titleLabel.font = [UIFont ows_regularFontWithSize:ScaleFromIPhone5To7Plus(13.f, 15.f)];
[bottomLegalLinkButton setTitleColor:UIColor.ows_materialBlueColor forState:UIControlStateNormal];
[bottomLegalLinkButton setTitle:bottomTermsLinkText forState:UIControlStateNormal];
[contentView addSubview:bottomLegalLinkButton];
[bottomLegalLinkButton addTarget:self
action:@selector(didTapLegalTerms:)
forControlEvents:UIControlEventTouchUpInside];
[bottomLegalLinkButton autoPinLeadingAndTrailingToSuperviewMargin];
[bottomLegalLinkButton autoPinEdge:ALEdgeTop
toEdge:ALEdgeBottom
ofView:activateButton
withOffset:ScaleFromIPhone5To7Plus(8, 12)];
[bottomLegalLinkButton setCompressionResistanceHigh];
[bottomLegalLinkButton setContentHuggingHigh];
SET_SUBVIEW_ACCESSIBILITY_IDENTIFIER(self, bottomLegalLinkButton);
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.activateButton setEnabled:YES];
[self.spinnerView stopAnimating];
[self.phoneNumberTextField becomeFirstResponder];
if (self.tsAccountManager.isReregistering) {
// If re-registering, pre-populate the country (country code, calling code, country name)
// and phone number state.
NSString *_Nullable phoneNumberE164 = self.tsAccountManager.reregisterationPhoneNumber;
if (!phoneNumberE164) {
OWSFailDebug(@"Could not resume re-registration; missing phone number.");
} else if ([self tryToApplyPhoneNumberE164:phoneNumberE164]) {
// Don't let user edit their phone number while re-registering.
self.phoneNumberTextField.enabled = NO;
}
}
}
- (BOOL)tryToApplyPhoneNumberE164:(NSString *)phoneNumberE164
{
OWSAssertDebug(phoneNumberE164);
if (phoneNumberE164.length < 1) {
OWSFailDebug(@"Could not resume re-registration; invalid phoneNumberE164.");
return NO;
}
PhoneNumber *_Nullable parsedPhoneNumber = [PhoneNumber phoneNumberFromE164:phoneNumberE164];
if (!parsedPhoneNumber) {
OWSFailDebug(@"Could not resume re-registration; couldn't parse phoneNumberE164.");
return NO;
}
NSNumber *_Nullable callingCode = parsedPhoneNumber.getCountryCode;
if (!callingCode) {
OWSFailDebug(@"Could not resume re-registration; missing callingCode.");
return NO;
}
NSString *callingCodeText = [NSString stringWithFormat:@"+%d", callingCode.intValue];
NSArray<NSString *> *_Nullable countryCodes =
[PhoneNumberUtil.sharedThreadLocal countryCodesFromCallingCode:callingCodeText];
if (countryCodes.count < 1) {
OWSFailDebug(@"Could not resume re-registration; unknown countryCode.");
return NO;
}
NSString *countryCode = countryCodes.firstObject;
NSString *_Nullable countryName = [PhoneNumberUtil countryNameFromCountryCode:countryCode];
if (!countryName) {
OWSFailDebug(@"Could not resume re-registration; unknown countryName.");
return NO;
}
if (![phoneNumberE164 hasPrefix:callingCodeText]) {
OWSFailDebug(@"Could not resume re-registration; non-matching calling code.");
return NO;
}
NSString *phoneNumberWithoutCallingCode = [phoneNumberE164 substringFromIndex:callingCodeText.length];
[self updateCountryWithName:countryName callingCode:callingCodeText countryCode:countryCode];
self.phoneNumberTextField.text = phoneNumberWithoutCallingCode;
return YES;
}
#pragma mark - Country
- (void)populateDefaultCountryNameAndCode
{
NSString *countryCode = [PhoneNumber defaultCountryCode];
#ifdef DEBUG
if ([self lastRegisteredCountryCode].length > 0) {
countryCode = [self lastRegisteredCountryCode];
}
self.phoneNumberTextField.text = [self lastRegisteredPhoneNumber];
#endif
NSNumber *callingCode = [[PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil getCountryCodeForRegion:countryCode];
NSString *countryName = [PhoneNumberUtil countryNameFromCountryCode:countryCode];
[self updateCountryWithName:countryName
callingCode:[NSString stringWithFormat:@"%@%@", COUNTRY_CODE_PREFIX, callingCode]
countryCode:countryCode];
}
- (void)updateCountryWithName:(NSString *)countryName
callingCode:(NSString *)callingCode
countryCode:(NSString *)countryCode
{
OWSAssertIsOnMainThread();
OWSAssertDebug(countryName.length > 0);
OWSAssertDebug(callingCode.length > 0);
OWSAssertDebug(countryCode.length > 0);
_countryCode = countryCode;
_callingCode = callingCode;
NSString *title = [NSString stringWithFormat:@"%@ (%@)", callingCode, countryCode.localizedUppercaseString];
self.countryCodeLabel.text = title;
[self.countryCodeLabel setNeedsLayout];
self.examplePhoneNumberLabel.text =
[ViewControllerUtils examplePhoneNumberForCountryCode:countryCode callingCode:callingCode];
[self.examplePhoneNumberLabel setNeedsLayout];
}
#pragma mark - Actions
- (void)didTapRegisterButton
{
NSString *phoneNumberText = [_phoneNumberTextField.text ows_stripped];
if (phoneNumberText.length < 1) {
[OWSAlerts
showAlertWithTitle:NSLocalizedString(@"REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_TITLE",
@"Title of alert indicating that users needs to enter a phone number to register.")
message:
NSLocalizedString(@"REGISTRATION_VIEW_NO_PHONE_NUMBER_ALERT_MESSAGE",
@"Message of alert indicating that users needs to enter a phone number to register.")];
return;
}
NSString *countryCode = self.countryCode;
NSString *phoneNumber = [NSString stringWithFormat:@"%@%@", _callingCode, phoneNumberText];
PhoneNumber *localNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber];
NSString *parsedPhoneNumber = localNumber.toE164;
if (parsedPhoneNumber.length < 1
|| ![[PhoneNumberValidator new] isValidForRegistrationWithPhoneNumber:localNumber]) {
[OWSAlerts showAlertWithTitle:
NSLocalizedString(@"REGISTRATION_VIEW_INVALID_PHONE_NUMBER_ALERT_TITLE",
@"Title of alert indicating that users needs to enter a valid phone number to register.")
message:NSLocalizedString(@"REGISTRATION_VIEW_INVALID_PHONE_NUMBER_ALERT_MESSAGE",
@"Message of alert indicating that users needs to enter a valid phone number "
@"to register.")];
return;
}
if (UIDevice.currentDevice.isIPad) {
[OWSAlerts showConfirmationAlertWithTitle:NSLocalizedString(@"REGISTRATION_IPAD_CONFIRM_TITLE",
@"alert title when registering an iPad")
message:NSLocalizedString(@"REGISTRATION_IPAD_CONFIRM_BODY",
@"alert body when registering an iPad")
proceedTitle:NSLocalizedString(@"REGISTRATION_IPAD_CONFIRM_BUTTON",
@"button text to proceed with registration when on an iPad")
proceedAction:^(UIAlertAction *_Nonnull action) {
[self sendCodeActionWithParsedPhoneNumber:parsedPhoneNumber
phoneNumberText:phoneNumberText
countryCode:countryCode];
}];
} else {
[self sendCodeActionWithParsedPhoneNumber:parsedPhoneNumber
phoneNumberText:phoneNumberText
countryCode:countryCode];
}
}
- (void)sendCodeActionWithParsedPhoneNumber:(NSString *)parsedPhoneNumber
phoneNumberText:(NSString *)phoneNumberText
countryCode:(NSString *)countryCode
{
[self.activateButton setEnabled:NO];
[self.spinnerView startAnimating];
[self.phoneNumberTextField resignFirstResponder];
__weak RegistrationViewController *weakSelf = self;
[self.tsAccountManager registerWithPhoneNumber:parsedPhoneNumber
captchaToken:nil
success:^{
OWSProdInfo([OWSAnalyticsEvents registrationRegisteredPhoneNumber]);
[weakSelf.spinnerView stopAnimating];
CodeVerificationViewController *vc = [CodeVerificationViewController new];
[weakSelf.navigationController pushViewController:vc animated:YES];
#ifdef DEBUG
[weakSelf setLastRegisteredCountryCode:countryCode];
[weakSelf setLastRegisteredPhoneNumber:phoneNumberText];
#endif
}
failure:^(NSError *error) {
if (error.code == 400) {
[OWSAlerts showAlertWithTitle:NSLocalizedString(@"REGISTRATION_ERROR", nil)
message:NSLocalizedString(@"REGISTRATION_NON_VALID_NUMBER", nil)];
} else {
[OWSAlerts showAlertWithTitle:error.localizedDescription message:error.localizedRecoverySuggestion];
}
[weakSelf.activateButton setEnabled:YES];
[weakSelf.spinnerView stopAnimating];
[weakSelf.phoneNumberTextField becomeFirstResponder];
}
smsVerification:YES];
}
- (void)countryCodeRowWasTapped:(UIGestureRecognizer *)sender
{
if (self.tsAccountManager.isReregistering) {
// Don't let user edit their phone number while re-registering.
return;
}
if (sender.state == UIGestureRecognizerStateRecognized) {
[self changeCountryCodeTapped];
}
}
- (void)didTapLegalTerms:(UIButton *)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:kLegalTermsUrlString]];
}
- (void)changeCountryCodeTapped
{
CountryCodeViewController *countryCodeController = [CountryCodeViewController new];
countryCodeController.countryCodeDelegate = self;
countryCodeController.interfaceOrientationMask = UIInterfaceOrientationMaskPortrait;
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:countryCodeController];
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)backgroundTapped:(UIGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateRecognized) {
[self.phoneNumberTextField becomeFirstResponder];
}
}
#pragma mark - CountryCodeViewControllerDelegate
- (void)countryCodeViewController:(CountryCodeViewController *)vc
didSelectCountryCode:(NSString *)countryCode
countryName:(NSString *)countryName
callingCode:(NSString *)callingCode
{
OWSAssertDebug(countryCode.length > 0);
OWSAssertDebug(countryName.length > 0);
OWSAssertDebug(callingCode.length > 0);
[self updateCountryWithName:countryName callingCode:callingCode countryCode:countryCode];
// Trigger the formatting logic with a no-op edit.
[self textField:self.phoneNumberTextField shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@""];
}
#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];
}
#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)insertionText
{
[ViewControllerUtils phoneNumberTextField:textField
shouldChangeCharactersInRange:range
replacementString:insertionText
callingCode:_callingCode];
return NO; // inform our caller that we took care of performing the change
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self didTapRegisterButton];
[textField resignFirstResponder];
return NO;
}
#pragma mark - Debug
#ifdef DEBUG
- (NSString *_Nullable)debugValueForKey:(NSString *)key
{
OWSCAssertDebug([NSThread isMainThread]);
OWSCAssertDebug(key.length > 0);
NSError *error;
NSString *_Nullable value =
[CurrentAppContext().keychainStorage stringForService:kKeychainService_LastRegistered key:key error:&error];
if (error || !value) {
OWSLogWarn(@"Could not retrieve 'last registered' value from keychain: %@.", error);
return nil;
}
return value;
}
- (void)setDebugValue:(NSString *)value forKey:(NSString *)key
{
OWSCAssertDebug([NSThread isMainThread]);
OWSCAssertDebug(key.length > 0);
OWSCAssertDebug(value.length > 0);
NSError *error;
BOOL success = [CurrentAppContext().keychainStorage setString:value
service:kKeychainService_LastRegistered
key:key
error:&error];
if (!success || error) {
OWSLogError(@"Error persisting 'last registered' value in keychain: %@", error);
}
}
- (NSString *_Nullable)lastRegisteredCountryCode
{
return [self debugValueForKey:kKeychainKey_LastRegisteredCountryCode];
}
- (void)setLastRegisteredCountryCode:(NSString *)value
{
[self setDebugValue:value forKey:kKeychainKey_LastRegisteredCountryCode];
}
- (NSString *_Nullable)lastRegisteredPhoneNumber
{
return [self debugValueForKey:kKeychainKey_LastRegisteredPhoneNumber];
}
- (void)setLastRegisteredPhoneNumber:(NSString *)value
{
[self setDebugValue:value forKey:kKeychainKey_LastRegisteredPhoneNumber];
}
#endif
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#pragma mark - Orientation
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
@end
NS_ASSUME_NONNULL_END

@ -1,5 +1,5 @@
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -115,7 +115,7 @@ class AppUpdateNag: NSObject {
}
switch frontmostViewController {
case is HomeViewController, is RegistrationViewController:
case is HomeViewController, is OnboardingSplashViewController:
self.setLastNagDate(Date())
self.clearFirstHeardOfNewVersionDate()
presentUpgradeNag(appStoreRecord: appStoreRecord)

@ -3,8 +3,8 @@
//
#import "RegistrationUtils.h"
#import "CodeVerificationViewController.h"
#import "OWSNavigationController.h"
#import "Signal-Swift.h"
#import <SignalMessaging/Environment.h>
#import <SignalMessaging/OWSPreferences.h>
#import <SignalMessaging/SignalMessaging-Swift.h>
@ -59,16 +59,23 @@ NS_ASSUME_NONNULL_BEGIN
presentFromViewController:fromViewController
canCancel:NO
backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) {
[self.tsAccountManager registerWithPhoneNumber:self.tsAccountManager.reregisterationPhoneNumber
NSString *phoneNumber = self.tsAccountManager.reregisterationPhoneNumber;
[self.tsAccountManager registerWithPhoneNumber:phoneNumber
captchaToken:nil
success:^{
OWSLogInfo(@"re-registering: send verification code succeeded.");
dispatch_async(dispatch_get_main_queue(), ^{
[modalActivityIndicator dismissWithCompletion:^{
CodeVerificationViewController *viewController =
[CodeVerificationViewController new];
OnboardingController *onboardingController = [OnboardingController new];
OnboardingPhoneNumber *onboardingPhoneNumber =
[[OnboardingPhoneNumber alloc] initWithE164:phoneNumber
userInput:phoneNumber];
[onboardingController updateWithPhoneNumber:onboardingPhoneNumber];
OnboardingVerificationViewController *viewController =
[[OnboardingVerificationViewController alloc]
initWithOnboardingController:onboardingController];
[viewController hideBackLink];
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:viewController];
navigationController.navigationBarHidden = YES;

@ -414,8 +414,6 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien
#pragma mark - UITextFieldDelegate
// TODO: This logic resides in both RegistrationViewController and here.
// We should refactor it out into a utility function.
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)insertionText

Loading…
Cancel
Save