diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 1c2041c5c..b06e2c143 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -129,6 +129,7 @@ 346941A3215D2EE400B5BFAD /* Theme.m in Sources */ = {isa = PBXBuildFile; fileRef = 3469419F215D2EE400B5BFAD /* Theme.m */; }; 346941A4215D2EE400B5BFAD /* OWSConversationColor.h in Headers */ = {isa = PBXBuildFile; fileRef = 346941A0215D2EE400B5BFAD /* OWSConversationColor.h */; settings = {ATTRIBUTES = (Public, ); }; }; 346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */; }; + 346E9D5421B040B700562252 /* RegistrationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346E9D5321B040B600562252 /* RegistrationController.swift */; }; 347850311FD7494A007B8332 /* dripicons-v2.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5B1E787A9800DF2FB9 /* dripicons-v2.ttf */; }; 347850321FD7494A007B8332 /* ElegantIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A5D1E787BD800DF2FB9 /* ElegantIcons.ttf */; }; 347850331FD7494A007B8332 /* fontawesome-webfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34330A591E7875FB00DF2FB9 /* fontawesome-webfont.ttf */; }; @@ -781,6 +782,7 @@ 3469419F215D2EE400B5BFAD /* Theme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Theme.m; sourceTree = ""; }; 346941A0215D2EE400B5BFAD /* OWSConversationColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSConversationColor.h; sourceTree = ""; }; 346B66301F4E29B200E5122F /* CropScaleImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CropScaleImageViewController.swift; sourceTree = ""; }; + 346E9D5321B040B600562252 /* RegistrationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegistrationController.swift; sourceTree = ""; }; 347850561FD86544007B8332 /* SAEFailedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SAEFailedViewController.swift; sourceTree = ""; }; 3478505A1FD999D5007B8332 /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = translations/et.lproj/Localizable.strings; sourceTree = ""; }; 3478505C1FD99A1F007B8332 /* zh_TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_TW; path = translations/zh_TW.lproj/Localizable.strings; sourceTree = ""; }; @@ -1427,6 +1429,7 @@ 3441FD9E21A3604F00BB9542 /* BackupRestoreViewController.swift */, 340FC879204DAC8C007AEB0F /* CodeVerificationViewController.h */, 340FC877204DAC8C007AEB0F /* CodeVerificationViewController.m */, + 346E9D5321B040B600562252 /* RegistrationController.swift */, 340FC878204DAC8C007AEB0F /* RegistrationViewController.h */, 340FC876204DAC8C007AEB0F /* RegistrationViewController.m */, ); @@ -3425,6 +3428,7 @@ 451166C01FD86B98000739BA /* AccountManager.swift in Sources */, 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 */, diff --git a/Signal/src/Models/AccountManager.swift b/Signal/src/Models/AccountManager.swift index de6714cab..79ca9c47c 100644 --- a/Signal/src/Models/AccountManager.swift +++ b/Signal/src/Models/AccountManager.swift @@ -41,9 +41,9 @@ public class AccountManager: NSObject { // MARK: registration - @objc func register(verificationCode: String, - pin: String?) -> AnyPromise { - return AnyPromise(register(verificationCode: verificationCode, pin: pin) as Promise) + @objc func registerObjc(verificationCode: String, + pin: String?) -> AnyPromise { + return AnyPromise(register(verificationCode: verificationCode, pin: pin)) } func register(verificationCode: String, diff --git a/Signal/src/ViewControllers/OWS2FARegistrationViewController.h b/Signal/src/ViewControllers/OWS2FARegistrationViewController.h index 2b6bcd050..81333e33a 100644 --- a/Signal/src/ViewControllers/OWS2FARegistrationViewController.h +++ b/Signal/src/ViewControllers/OWS2FARegistrationViewController.h @@ -6,10 +6,16 @@ NS_ASSUME_NONNULL_BEGIN +@class RegistrationController; + @interface OWS2FARegistrationViewController : OWSViewController @property (nonatomic) NSString *verificationCode; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithRegistrationController:(RegistrationController *)registrationController + NS_DESIGNATED_INITIALIZER; + @end NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWS2FARegistrationViewController.m b/Signal/src/ViewControllers/OWS2FARegistrationViewController.m index 2d573478d..dc1a58d36 100644 --- a/Signal/src/ViewControllers/OWS2FARegistrationViewController.m +++ b/Signal/src/ViewControllers/OWS2FARegistrationViewController.m @@ -15,7 +15,8 @@ NS_ASSUME_NONNULL_BEGIN @interface OWS2FARegistrationViewController () -@property (nonatomic, readonly) AccountManager *accountManager; +@property (nonatomic, readonly) RegistrationController *registrationController; + @property (nonatomic) PinEntryView *entryView; @end @@ -24,26 +25,23 @@ NS_ASSUME_NONNULL_BEGIN @implementation OWS2FARegistrationViewController -- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder +#pragma mark - Dependencies + +- (AccountManager *)accountManager { - self = [super initWithCoder:aDecoder]; - if (!self) { - return self; - } - - _accountManager = AppEnvironment.shared.accountManager; - - return self; + return AppEnvironment.shared.accountManager; } -- (instancetype)init +#pragma mark - + +- (instancetype)initWithRegistrationController:(RegistrationController *)registrationController { self = [super init]; if (!self) { return self; } - _accountManager = AppEnvironment.shared.accountManager; + _registrationController = registrationController; return self; } @@ -125,7 +123,7 @@ NS_ASSUME_NONNULL_BEGIN canCancel:NO backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) { OWSProdInfo([OWSAnalyticsEvents registrationRegisteringCode]); - [self.accountManager registerWithVerificationCode:self.verificationCode pin:pinCode] + [self.accountManager registerObjcWithVerificationCode:self.verificationCode pin:pinCode] .then(^{ OWSAssertIsOnMainThread(); OWSProdInfo([OWSAnalyticsEvents registrationRegisteringSubmittedCode]); @@ -163,7 +161,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)verificationWasCompleted { - [ProfileViewController presentForRegistration:self.navigationController]; + [self.registrationController verificationWasCompletedFromView:self]; } @end diff --git a/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift b/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift index bdc393a29..66bd1be27 100644 --- a/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift +++ b/Signal/src/ViewControllers/Registration/BackupRestoreViewController.swift @@ -7,12 +7,25 @@ import UIKit @objc public class BackupRestoreViewController: OWSTableViewController { + private let registrationController: RegistrationController private var hasBegunImport = false + // MARK: - Dependencies + private var backup: OWSBackup { return AppEnvironment.shared.backup } + // MARK: - + + @objc + public required init(registrationController: RegistrationController) { + AssertIsOnMainThread() + + self.registrationController = registrationController + super.init() + } + override public func loadView() { super.loadView() diff --git a/Signal/src/ViewControllers/Registration/CodeVerificationViewController.h b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.h index 492aaa68b..6b8703fc5 100644 --- a/Signal/src/ViewControllers/Registration/CodeVerificationViewController.h +++ b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.h @@ -6,8 +6,14 @@ NS_ASSUME_NONNULL_BEGIN +@class RegistrationController; + @interface CodeVerificationViewController : OWSViewController +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithRegistrationController:(RegistrationController *)registrationController + NS_DESIGNATED_INITIALIZER; + - (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode; @end diff --git a/Signal/src/ViewControllers/Registration/CodeVerificationViewController.m b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.m index b4c5dda71..55d4f971a 100644 --- a/Signal/src/ViewControllers/Registration/CodeVerificationViewController.m +++ b/Signal/src/ViewControllers/Registration/CodeVerificationViewController.m @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @interface CodeVerificationViewController () -@property (nonatomic, readonly) AccountManager *accountManager; +@property (nonatomic, readonly) RegistrationController *registrationController; // Where the user enters the verification code they wish to document @property (nonatomic) UITextField *challengeTextField; @@ -47,28 +47,21 @@ NS_ASSUME_NONNULL_BEGIN return SSKEnvironment.shared.tsAccountManager; } -#pragma mark - - -- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder +- (AccountManager *)accountManager { - self = [super initWithCoder:aDecoder]; - if (!self) { - return self; - } - - _accountManager = AppEnvironment.shared.accountManager; - - return self; + return AppEnvironment.shared.accountManager; } -- (instancetype)init +#pragma mark - + +- (instancetype)initWithRegistrationController:(RegistrationController *)registrationController { self = [super init]; if (!self) { return self; } - _accountManager = AppEnvironment.shared.accountManager; + _registrationController = registrationController; return self; } @@ -292,7 +285,7 @@ NS_ASSUME_NONNULL_BEGIN [self startActivityIndicator]; OWSProdInfo([OWSAnalyticsEvents registrationRegisteringCode]); __weak CodeVerificationViewController *weakSelf = self; - [[self.accountManager registerWithVerificationCode:[self validationCodeFromTextField] pin:nil] + [[self.accountManager registerObjcWithVerificationCode:[self validationCodeFromTextField] pin:nil] .then(^{ OWSProdInfo([OWSAnalyticsEvents registrationRegisteringSubmittedCode]); @@ -316,7 +309,8 @@ NS_ASSUME_NONNULL_BEGIN return; } OWSLogInfo(@"Showing 2FA registration view."); - OWS2FARegistrationViewController *viewController = [OWS2FARegistrationViewController new]; + OWS2FARegistrationViewController *viewController = [[OWS2FARegistrationViewController alloc] + initWithRegistrationController:self.registrationController]; viewController.verificationCode = strongSelf.validationCodeFromTextField; [strongSelf.navigationController pushViewController:viewController animated:YES]; } else { @@ -329,78 +323,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)verificationWasCompleted { - if ([TSAccountManager sharedInstance].isReregistering) { - [self showProfileView]; - } else { - [self checkCanImportBackup]; - } -} - -- (void)showProfileView -{ - [ProfileViewController presentForRegistration:self.navigationController]; -} - -- (void)showBackupRestoreView -{ - OWSAssertIsOnMainThread(); - OWSLogVerbose(@""); - - BackupRestoreViewController *restoreView = [BackupRestoreViewController new]; - [self.navigationController setViewControllers:@[ - restoreView, - ] - animated:YES]; -} - -- (void)checkCanImportBackup -{ - OWSLogVerbose(@""); - - __weak CodeVerificationViewController *weakSelf = self; - [OWSBackup.sharedManager - checkCanImportBackup:^(BOOL value) { - OWSAssertIsOnMainThread(); - - OWSLogInfo(@"has backup available for import? %d", value); - - if (value) { - [OWSBackup.sharedManager setHasPendingRestoreDecision:YES]; - - [weakSelf showBackupRestoreView]; - } else { - [weakSelf showProfileView]; - } - } - failure:^(NSError *error) { - [weakSelf showBackupCheckFailedAlert]; - }]; -} - -- (void)showBackupCheckFailedAlert -{ - OWSLogVerbose(@""); - - __weak CodeVerificationViewController *weakSelf = self; - UIAlertController *controller = [UIAlertController - alertControllerWithTitle:NSLocalizedString(@"CHECK_FOR_BACKUP_FAILED_TITLE", - @"Title for alert shown when the app failed to check for an existing backup.") - message:NSLocalizedString(@"CHECK_FOR_BACKUP_FAILED_MESSAGE", - @"Message for alert shown when the app failed to check for an existing " - @"backup.") - preferredStyle:UIAlertControllerStyleAlert]; - [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"REGISTER_FAILED_TRY_AGAIN", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - [weakSelf checkCanImportBackup]; - }]]; - [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"CHECK_FOR_BACKUP_DO_NOT_RESTORE", - @"The label for the 'do not restore backup' button.") - style:UIAlertActionStyleDestructive - handler:^(UIAlertAction *action) { - [weakSelf showProfileView]; - }]]; - [self presentViewController:controller animated:YES completion:nil]; + [self.registrationController verificationWasCompletedFromView:self]; } - (void)presentAlertWithVerificationError:(NSError *)error diff --git a/Signal/src/ViewControllers/Registration/RegistrationController.swift b/Signal/src/ViewControllers/Registration/RegistrationController.swift new file mode 100644 index 000000000..fd61014f3 --- /dev/null +++ b/Signal/src/ViewControllers/Registration/RegistrationController.swift @@ -0,0 +1,113 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import UIKit + +@objc +public class RegistrationController: NSObject { + + // MARK: - Dependencies + + private var tsAccountManager: TSAccountManager { + return TSAccountManager.sharedInstance() + } + + private var backup: OWSBackup { + return AppEnvironment.shared.backup + } + + // MARK: registration + + @objc + public func verificationWasCompleted(fromView view: UIViewController) { + AssertIsOnMainThread() + + if tsAccountManager.isReregistering() { + showProfileView(fromView: view) + } else { + checkCanImportBackup(fromView: view) + } + } + + private func showProfileView(fromView view: UIViewController) { + AssertIsOnMainThread() + + Logger.info("") + + guard let navigationController = view.navigationController else { + owsFailDebug("Missing navigationController") + return + } + + ProfileViewController.present(forRegistration: navigationController) + } + + private func showBackupRestoreView(fromView view: UIViewController) { + AssertIsOnMainThread() + + Logger.info("") + + guard let navigationController = view.navigationController else { + owsFailDebug("Missing navigationController") + return + } + + let restoreView = BackupRestoreViewController() + navigationController.setViewControllers([restoreView], animated: true) + } + + private func checkCanImportBackup(fromView view: UIViewController) { + AssertIsOnMainThread() + + Logger.info("") + + self.backup.checkCanImport({ [weak self] (canImport) in + guard let strongSelf = self else { + return + } + + Logger.info("canImport: \(canImport)") + + if (canImport) { + strongSelf.backup.setHasPendingRestoreDecision(true) + + strongSelf.showBackupRestoreView(fromView: view) + } else { + strongSelf.showProfileView(fromView: view) + } + }) { [weak self] (_) in + guard let strongSelf = self else { + return + } + strongSelf.showBackupCheckFailedAlert(fromView: view) + } + } + + private 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) { [weak self] (_) in + guard let strongSelf = self else { + return + } + strongSelf.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) { [weak self] (_) in + guard let strongSelf = self else { + return + } + strongSelf.showProfileView(fromView: view) + }) + view.present(alert, animated: true) + } +} diff --git a/Signal/src/ViewControllers/Registration/RegistrationViewController.m b/Signal/src/ViewControllers/Registration/RegistrationViewController.m index a10e0117d..aec254d2f 100644 --- a/Signal/src/ViewControllers/Registration/RegistrationViewController.m +++ b/Signal/src/ViewControllers/Registration/RegistrationViewController.m @@ -28,6 +28,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi @interface RegistrationViewController () +@property (nonatomic, readonly) RegistrationController *registrationController; + @property (nonatomic) NSString *countryCode; @property (nonatomic) NSString *callingCode; @@ -58,6 +60,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi { [super loadView]; + _registrationController = [RegistrationController new]; + self.shouldUseTheme = NO; [self createViews]; @@ -458,7 +462,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi [weakSelf.spinnerView stopAnimating]; - CodeVerificationViewController *vc = [CodeVerificationViewController new]; + CodeVerificationViewController *vc = + [[CodeVerificationViewController alloc] initWithRegistrationController:self.registrationController]; [weakSelf.navigationController pushViewController:vc animated:YES]; #ifdef DEBUG