Add re-registration UI.
This commit is contained in:
parent
fc4763673f
commit
bc6a4ea8d8
|
@ -24,14 +24,6 @@
|
|||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TSAccountManager (DebugUI)
|
||||
|
||||
- (void)resetForRegistration;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface OWSStorage (DebugUI)
|
||||
|
||||
- (NSData *)databasePassword;
|
||||
|
@ -147,7 +139,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (void)reregister
|
||||
{
|
||||
DDLogInfo(@"%@ re-registering.", self.logTag);
|
||||
[[TSAccountManager sharedInstance] resetForRegistration];
|
||||
|
||||
if (![[TSAccountManager sharedInstance] resetForReregistration]) {
|
||||
OWSFail(@"%@ could not reset for re-registration.", self.logTag);
|
||||
return;
|
||||
}
|
||||
|
||||
[[Environment current].preferences unsetRecordedAPNSTokens];
|
||||
|
||||
RegistrationViewController *viewController = [RegistrationViewController new];
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
#import "HomeViewController.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "AppSettingsViewController.h"
|
||||
#import "CodeVerificationViewController.h"
|
||||
#import "HomeViewCell.h"
|
||||
#import "NewContactThreadViewController.h"
|
||||
#import "OWSNavigationController.h"
|
||||
#import "OWSPrimaryStorage.h"
|
||||
#import "ProfileViewController.h"
|
||||
#import "PushManager.h"
|
||||
#import "RegistrationViewController.h"
|
||||
#import "Signal-Swift.h"
|
||||
#import "SignalApp.h"
|
||||
#import "TSAccountManager.h"
|
||||
|
@ -210,11 +212,12 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
[SignalApp.sharedApp setHomeViewController:self];
|
||||
}
|
||||
|
||||
__weak HomeViewController *weakSelf = self;
|
||||
ReminderView *deregisteredView =
|
||||
[ReminderView nagWithText:NSLocalizedString(@"INBOX_VIEW_DEREGISTRATION_WARNING",
|
||||
[ReminderView nagWithText:NSLocalizedString(@"DEREGISTRATION_WARNING",
|
||||
@"Label warning the user that they have been de-registered.")
|
||||
tapAction:^{
|
||||
// TODO:
|
||||
[weakSelf showReRegistrationUI];
|
||||
}];
|
||||
[self.view addSubview:deregisteredView];
|
||||
[deregisteredView autoPinWidthToSuperview];
|
||||
|
@ -1407,6 +1410,80 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations
|
|||
_emptyBoxLabel.attributedText = fullLabelString;
|
||||
}
|
||||
|
||||
- (void)showReRegistrationUI
|
||||
{
|
||||
UIAlertController *actionSheetController =
|
||||
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
__weak HomeViewController *weakSelf = self;
|
||||
[actionSheetController
|
||||
addAction:[UIAlertAction
|
||||
actionWithTitle:NSLocalizedString(@"DEREGISTRATION_REREGISTER_WITH_SAME_PHONE_NUMBER",
|
||||
@"Label for button that lets users re-register using the same phone number.")
|
||||
style:UIAlertActionStyleDestructive
|
||||
handler:^(UIAlertAction *action) {
|
||||
[weakSelf reregisterWithSamePhoneNumber];
|
||||
}]];
|
||||
|
||||
[actionSheetController addAction:[OWSAlerts cancelAction]];
|
||||
|
||||
[self presentViewController:actionSheetController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)reregisterWithSamePhoneNumber
|
||||
{
|
||||
DDLogInfo(@"%@ reregisterWithSamePhoneNumber.", self.logTag);
|
||||
|
||||
if (![[TSAccountManager sharedInstance] resetForReregistration]) {
|
||||
OWSFail(@"%@ could not reset for re-registration.", self.logTag);
|
||||
return;
|
||||
}
|
||||
|
||||
[[Environment current].preferences unsetRecordedAPNSTokens];
|
||||
|
||||
[ModalActivityIndicatorViewController
|
||||
presentFromViewController:self
|
||||
canCancel:NO
|
||||
backgroundBlock:^(ModalActivityIndicatorViewController *modalActivityIndicator) {
|
||||
[TSAccountManager
|
||||
registerWithPhoneNumber:[TSAccountManager sharedInstance].reregisterationPhoneNumber
|
||||
success:^{
|
||||
DDLogInfo(@"%@ re-registering: send verification code succeeded.", self.logTag);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[modalActivityIndicator dismissWithCompletion:^{
|
||||
CodeVerificationViewController *viewController =
|
||||
[CodeVerificationViewController new];
|
||||
|
||||
OWSNavigationController *navigationController =
|
||||
[[OWSNavigationController alloc] initWithRootViewController:viewController];
|
||||
navigationController.navigationBarHidden = YES;
|
||||
|
||||
[UIApplication sharedApplication].delegate.window.rootViewController
|
||||
= navigationController;
|
||||
}];
|
||||
});
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
DDLogError(@"%@ re-registering: send verification code failed.", self.logTag);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[modalActivityIndicator dismissWithCompletion:^{
|
||||
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];
|
||||
}
|
||||
}];
|
||||
});
|
||||
}
|
||||
smsVerification:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -112,16 +112,25 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[titleLabel autoSetDimension:ALDimensionHeight toSize:40];
|
||||
[titleLabel autoHCenterInSuperview];
|
||||
|
||||
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];
|
||||
// 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];
|
||||
|
|
|
@ -278,6 +278,61 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi
|
|||
[self.activateButton setEnabled:YES];
|
||||
[self.spinnerView stopAnimating];
|
||||
[self.phoneNumberTextField becomeFirstResponder];
|
||||
|
||||
if ([TSAccountManager sharedInstance].isReregistering) {
|
||||
// If re-registering, pre-populate the country (country code, calling code, country name)
|
||||
// and phone number state.
|
||||
NSString *_Nullable phoneNumberE164 = [TSAccountManager sharedInstance].reregisterationPhoneNumber;
|
||||
if (!phoneNumberE164) {
|
||||
OWSFail(@"%@ Could not resume re-registration; missing phone number.", self.logTag);
|
||||
} else if ([self tryToApplyPhoneNumberE164:phoneNumberE164]) {
|
||||
// Don't let user edit their phone number while re-registering.
|
||||
self.phoneNumberTextField.enabled = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)tryToApplyPhoneNumberE164:(NSString *)phoneNumberE164
|
||||
{
|
||||
OWSAssert(phoneNumberE164);
|
||||
|
||||
if (phoneNumberE164.length < 1) {
|
||||
OWSFail(@"%@ Could not resume re-registration; invalid phoneNumberE164.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
PhoneNumber *_Nullable parsedPhoneNumber = [PhoneNumber phoneNumberFromE164:phoneNumberE164];
|
||||
if (!parsedPhoneNumber) {
|
||||
OWSFail(@"%@ Could not resume re-registration; couldn't parse phoneNumberE164.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
NSNumber *_Nullable callingCode = parsedPhoneNumber.getCountryCode;
|
||||
if (!callingCode) {
|
||||
OWSFail(@"%@ Could not resume re-registration; missing callingCode.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
NSString *callingCodeText = [NSString stringWithFormat:@"+%d", callingCode.intValue];
|
||||
NSArray<NSString *> *_Nullable countryCodes =
|
||||
[PhoneNumberUtil.sharedThreadLocal countryCodesFromCallingCode:callingCodeText];
|
||||
if (countryCodes.count < 1) {
|
||||
OWSFail(@"%@ Could not resume re-registration; unknown countryCode.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
NSString *countryCode = countryCodes.firstObject;
|
||||
NSString *_Nullable countryName = [PhoneNumberUtil countryNameFromCountryCode:countryCode];
|
||||
if (!countryName) {
|
||||
OWSFail(@"%@ Could not resume re-registration; unknown countryName.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
if (![phoneNumberE164 hasPrefix:callingCodeText]) {
|
||||
OWSFail(@"%@ Could not resume re-registration; non-matching calling code.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
NSString *phoneNumberWithoutCallingCode = [phoneNumberE164 substringFromIndex:callingCodeText.length];
|
||||
|
||||
[self updateCountryWithName:countryName callingCode:callingCodeText countryCode:countryCode];
|
||||
self.phoneNumberTextField.text = phoneNumberWithoutCallingCode;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Country
|
||||
|
@ -385,6 +440,11 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi
|
|||
|
||||
- (void)countryCodeRowWasTapped:(UIGestureRecognizer *)sender
|
||||
{
|
||||
if (TSAccountManager.sharedInstance.isReregistering) {
|
||||
// Don't let user edit their phone number while re-registering.
|
||||
return;
|
||||
}
|
||||
|
||||
if (sender.state == UIGestureRecognizerStateRecognized) {
|
||||
[self changeCountryCodeTapped];
|
||||
}
|
||||
|
|
|
@ -647,6 +647,12 @@
|
|||
/* Title of the alert before redirecting to GitHub Issues. */
|
||||
"DEBUG_LOG_GITHUB_ISSUE_ALERT_TITLE" = "GitHub Redirection";
|
||||
|
||||
/* Label for button that lets users re-register using the same phone number. */
|
||||
"DEREGISTRATION_REREGISTER_WITH_SAME_PHONE_NUMBER" = "Re-register this phone number";
|
||||
|
||||
/* Label warning the user that they have been de-registered. */
|
||||
"DEREGISTRATION_WARNING" = "Device no longer registered! This is likely because you registered your phone number with Signal on a different device. Tap to re-register.";
|
||||
|
||||
/* {{Short Date}} when device last communicated with Signal Server. */
|
||||
"DEVICE_LAST_ACTIVE_AT_LABEL" = "Last active: %@";
|
||||
|
||||
|
@ -1022,9 +1028,6 @@
|
|||
/* Label reminding the user that they are in archive mode. */
|
||||
"INBOX_VIEW_ARCHIVE_MODE_REMINDER" = "These conversations are archived. They will appear in the inbox if new messages are received.";
|
||||
|
||||
/* Label warning the user that they have been de-registered. */
|
||||
"INBOX_VIEW_DEREGISTRATION_WARNING" = "You are not logged in. Another device may have been registered with your phone number.";
|
||||
|
||||
/* Multi-line label explaining how to show names instead of phone numbers in your inbox */
|
||||
"INBOX_VIEW_MISSING_CONTACTS_PERMISSION" = "To see the names of your contacts, update your system settings to allow contact access.";
|
||||
|
||||
|
|
|
@ -18,10 +18,7 @@ extern NSString *const kNSNotificationName_LocalNumberDidChange;
|
|||
|
||||
@interface TSAccountManager : NSObject
|
||||
|
||||
// This property is exposed for testing purposes only.
|
||||
#ifdef DEBUG
|
||||
@property (nonatomic, nullable) NSString *phoneNumberAwaitingVerification;
|
||||
#endif
|
||||
@property (nonatomic, nullable, readonly) NSString *phoneNumberAwaitingVerification;
|
||||
|
||||
#pragma mark - Initializers
|
||||
|
||||
|
@ -117,12 +114,22 @@ extern NSString *const kNSNotificationName_LocalNumberDidChange;
|
|||
|
||||
+ (void)unregisterTextSecureWithSuccess:(void (^)(void))success failure:(void (^)(NSError *error))failureBlock;
|
||||
|
||||
#pragma mark - Deregistration
|
||||
#pragma mark - De-Registration
|
||||
|
||||
// De-registration reflects whether or not the service has received a 403
|
||||
// De-registration reflects whether or not the client has received
|
||||
// a 403 from the service.
|
||||
- (BOOL)isDeregistered;
|
||||
- (void)setIsDeregistered:(BOOL)isDeregistered;
|
||||
|
||||
#pragma mark - Re-registration
|
||||
|
||||
// Re-registration is the process of re-registering _with the same phone number_.
|
||||
|
||||
// Returns YES on success.
|
||||
- (BOOL)resetForReregistration;
|
||||
- (NSString *)reregisterationPhoneNumber;
|
||||
- (BOOL)isReregistering;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -29,6 +29,7 @@ NSString *const kNSNotificationName_LocalNumberDidChange = @"kNSNotificationName
|
|||
|
||||
NSString *const TSAccountManager_RegisteredNumberKey = @"TSStorageRegisteredNumberKey";
|
||||
NSString *const TSAccountManager_IsDeregisteredKey = @"TSAccountManager_IsDeregisteredKey";
|
||||
NSString *const TSAccountManager_ReregisteringPhoneNumberKey = @"TSAccountManager_ReregisteringPhoneNumberKey";
|
||||
NSString *const TSAccountManager_LocalRegistrationIdKey = @"TSStorageLocalRegistrationId";
|
||||
|
||||
NSString *const TSAccountManager_UserAccountCollection = @"TSStorageUserAccountCollection";
|
||||
|
@ -39,10 +40,7 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
|
|||
|
||||
@property (nonatomic, readonly) BOOL isRegistered;
|
||||
|
||||
// This property is exposed publicly for testing purposes only.
|
||||
#ifndef DEBUG
|
||||
@property (nonatomic, nullable) NSString *phoneNumberAwaitingVerification;
|
||||
#endif
|
||||
|
||||
@property (nonatomic, nullable) NSString *cachedLocalNumber;
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
|
@ -75,6 +73,10 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
|
|||
selector:@selector(yapDatabaseModifiedExternally:)
|
||||
name:YapDatabaseModifiedExternallyNotification
|
||||
object:nil];
|
||||
|
||||
self.phoneNumberAwaitingVerification =
|
||||
[self.dbConnection stringForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
||||
inCollection:TSAccountManager_UserAccountCollection];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -106,22 +108,6 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
|
|||
userInfo:nil];
|
||||
}
|
||||
|
||||
- (void)resetForRegistration
|
||||
{
|
||||
@synchronized(self)
|
||||
{
|
||||
_isRegistered = NO;
|
||||
_cachedLocalNumber = nil;
|
||||
_phoneNumberAwaitingVerification = nil;
|
||||
_cachedIsDeregistered = nil;
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection];
|
||||
|
||||
[[OWSPrimaryStorage sharedManager] resetSessionStore:transaction];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)isRegistered
|
||||
{
|
||||
return [[self sharedInstance] isRegistered];
|
||||
|
@ -198,6 +184,11 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
|
|||
[self.dbConnection setObject:localNumber
|
||||
forKey:TSAccountManager_RegisteredNumberKey
|
||||
inCollection:TSAccountManager_UserAccountCollection];
|
||||
|
||||
[self.dbConnection removeObjectForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
||||
inCollection:TSAccountManager_UserAccountCollection];
|
||||
|
||||
self.phoneNumberAwaitingVerification = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -531,7 +522,7 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Deregistration
|
||||
#pragma mark - De-Registration
|
||||
|
||||
- (BOOL)isDeregistered
|
||||
{
|
||||
|
@ -571,6 +562,51 @@ NSString *const TSAccountManager_ServerSignalingKey = @"TSStorageServerSignaling
|
|||
userInfo:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Re-registration
|
||||
|
||||
- (BOOL)resetForReregistration
|
||||
{
|
||||
@synchronized(self) {
|
||||
NSString *_Nullable localNumber = self.localNumber;
|
||||
if (!localNumber) {
|
||||
OWSFail(@"%@ can't re-register without valid local number.", self.logTag);
|
||||
return NO;
|
||||
}
|
||||
|
||||
_isRegistered = NO;
|
||||
_cachedLocalNumber = nil;
|
||||
_phoneNumberAwaitingVerification = nil;
|
||||
_cachedIsDeregistered = nil;
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSAccountManager_UserAccountCollection];
|
||||
|
||||
[[OWSPrimaryStorage sharedManager] resetSessionStore:transaction];
|
||||
|
||||
[transaction setObject:localNumber
|
||||
forKey:TSAccountManager_ReregisteringPhoneNumberKey
|
||||
inCollection:TSAccountManager_UserAccountCollection];
|
||||
}];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)reregisterationPhoneNumber
|
||||
{
|
||||
OWSAssert([self isReregistering]);
|
||||
|
||||
NSString *_Nullable result = [self.dbConnection stringForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
||||
inCollection:TSAccountManager_UserAccountCollection];
|
||||
OWSAssert(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)isReregistering
|
||||
{
|
||||
return nil !=
|
||||
[self.dbConnection stringForKey:TSAccountManager_ReregisteringPhoneNumberKey
|
||||
inCollection:TSAccountManager_UserAccountCollection];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
Loading…
Reference in New Issue