Further refine the registration and verification views.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 199c564174
commit 57c60deda2

@ -139,6 +139,7 @@ NSString *const kCompletedRegistrationSegue = @"CompletedRegistration";
@"Text field placeholder for SMS verification code during registration"); @"Text field placeholder for SMS verification code during registration");
_challengeTextField.font = [UIFont ows_lightFontWithSize:21.f]; _challengeTextField.font = [UIFont ows_lightFontWithSize:21.f];
_challengeTextField.textAlignment = NSTextAlignmentCenter; _challengeTextField.textAlignment = NSTextAlignmentCenter;
_challengeTextField.keyboardType = UIKeyboardTypePhonePad;
_challengeTextField.delegate = self; _challengeTextField.delegate = self;
[self.view addSubview:_challengeTextField]; [self.view addSubview:_challengeTextField];
[_challengeTextField autoPinWidthToSuperviewWithMargin:kHMargin]; [_challengeTextField autoPinWidthToSuperviewWithMargin:kHMargin];
@ -392,18 +393,6 @@ NSString *const kCompletedRegistrationSegue = @"CompletedRegistration";
[self.view endEditing:NO]; [self.view endEditing:NO];
} }
- (NSString *)stringByFilteringString:(NSString *)input
withCharacterSet:(NSCharacterSet *)characterSet {
NSMutableString *result = [NSMutableString new];
for (NSUInteger i=0; i < input.length; i++) {
unichar c = [input characterAtIndex:i];
if ([characterSet characterIsMember:c]) {
[result appendFormat:@"%c", c];
}
}
return [result copy];
}
- (BOOL)textField:(UITextField *)textField - (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)insertionText { replacementString:(NSString *)insertionText {
@ -423,18 +412,14 @@ NSString *const kCompletedRegistrationSegue = @"CompletedRegistration";
// * Take partial input if possible. // * Take partial input if possible.
NSString *oldText = textField.text; NSString *oldText = textField.text;
NSCharacterSet *validCharacterSet = [NSCharacterSet decimalDigitCharacterSet];
// Construct the new contents of the text field by: // Construct the new contents of the text field by:
// 1. Determining the "left" substring: the contents of the old text _before_ the deletion range. // 1. Determining the "left" substring: the contents of the old text _before_ the deletion range.
// Filtering will remove non-decimal digit characters like hyphen "-". // Filtering will remove non-decimal digit characters like hyphen "-".
NSString *left = [self stringByFilteringString:[oldText substringToIndex:range.location] NSString *left = [oldText substringToIndex:range.location].digitsOnly;
withCharacterSet:validCharacterSet];
// 2. Determining the "right" substring: the contents of the old text _after_ the deletion range. // 2. Determining the "right" substring: the contents of the old text _after_ the deletion range.
NSString *right = [self stringByFilteringString:[oldText substringFromIndex:range.location + range.length] NSString *right = [oldText substringFromIndex:range.location + range.length].digitsOnly;
withCharacterSet:validCharacterSet];
// 3. Determining the "center" substring: the contents of the new insertion text. // 3. Determining the "center" substring: the contents of the new insertion text.
NSString *center = [self stringByFilteringString:insertionText NSString *center = insertionText.digitsOnly;
withCharacterSet:validCharacterSet];
// 3a. Trim the tail of the "center" substring to ensure that we don't end up // 3a. Trim the tail of the "center" substring to ensure that we don't end up
// with more than 6 decimal digits. // with more than 6 decimal digits.
while (center.length > 0 && while (center.length > 0 &&
@ -474,9 +459,17 @@ NSString *const kCompletedRegistrationSegue = @"CompletedRegistration";
} }
- (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode { - (void)setVerificationCodeAndTryToVerify:(NSString *)verificationCode {
NSCharacterSet *validCharacterSet = [NSCharacterSet decimalDigitCharacterSet]; NSString *rawNewText = verificationCode.digitsOnly;
self.challengeTextField.text = [self stringByFilteringString:verificationCode NSString *formattedNewText = (rawNewText.length <= 3
withCharacterSet:validCharacterSet]; ? 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 verifyChallengeAction:nil]; [self verifyChallengeAction:nil];
} }

@ -26,6 +26,7 @@ static NSString *const kCodeSentSegue = @"codeSent";
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
_phoneNumberTextField.delegate = self; _phoneNumberTextField.delegate = self;
_phoneNumberTextField.keyboardType = UIKeyboardTypePhonePad;
[self populateDefaultCountryNameAndCode]; [self populateDefaultCountryNameAndCode];
[[Environment getCurrent] setSignUpFlowNavigationController:self.navigationController]; [[Environment getCurrent] setSignUpFlowNavigationController:self.navigationController];
@ -148,48 +149,60 @@ static NSString *const kCodeSentSegue = @"codeSent";
- (BOOL)textField:(UITextField *)textField - (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string { replacementString:(NSString *)insertionText {
NSString *textBeforeChange = textField.text;
// Phone numbers takes many forms.
// backspacing should skip over formatting characters //
UITextPosition *posIfBackspace = [textField positionFromPosition:textField.beginningOfDocument // * We only want to let the user enter decimal digits.
offset:(NSInteger)(range.location + range.length)]; // * The user shouldn't have to enter hyphen, parentheses or whitespace;
UITextRange *rangeIfBackspace = [textField textRangeFromPosition:posIfBackspace toPosition:posIfBackspace]; // the phone number should be formatted automatically.
bool isBackspace = // * The user should be able to copy and paste freely.
string.length == 0 && range.length == 1 && [rangeIfBackspace isEqual:textField.selectedTextRange]; // * Invalid input should be simply ignored.
if (isBackspace) { //
NSString *digits = textBeforeChange.digitsOnly; // We accomplish this by being permissive and trying to "take as much of the user
NSUInteger correspondingDeletePosition = [PhoneNumberUtil translateCursorPosition:range.location + range.length // input as possible".
from:textBeforeChange //
to:digits // * Always accept deletes.
stickingRightward:true]; // * Ignore invalid input.
if (correspondingDeletePosition > 0) { // * Take partial input if possible.
textBeforeChange = digits;
range = NSMakeRange(correspondingDeletePosition - 1, 1); 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 "-".
// make the proposed change NSString *left = [oldText substringToIndex:range.location].digitsOnly;
NSString *textAfterChange = [textBeforeChange withCharactersInRange:range replacedBy:string]; // 2. Determining the "right" substring: the contents of the old text _after_ the deletion range.
NSUInteger cursorPositionAfterChange = range.location + string.length; 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;
// 4. Construct the "raw" new text by concatenating left, center and right.
NSString *textAfterChange = [[left stringByAppendingString:center]
stringByAppendingString:right];
// 5. Construct the "formatted" new text by inserting a hyphen if necessary.
// reformat the phone number, trying to keep the cursor beside the inserted or deleted digit // reformat the phone number, trying to keep the cursor beside the inserted or deleted digit
bool isJustDeletion = string.length == 0; bool isJustDeletion = insertionText.length == 0;
NSUInteger cursorPositionAfterChange = left.length + center.length;
NSString *textAfterReformat = NSString *textAfterReformat =
[PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:textAfterChange.digitsOnly [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:textAfterChange
withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text];
NSUInteger cursorPositionAfterReformat = [PhoneNumberUtil translateCursorPosition:cursorPositionAfterChange NSUInteger cursorPositionAfterReformat = [PhoneNumberUtil translateCursorPosition:cursorPositionAfterChange
from:textAfterChange from:textAfterChange
to:textAfterReformat to:textAfterReformat
stickingRightward:isJustDeletion]; stickingRightward:isJustDeletion];
textField.text = textAfterReformat; textField.text = textAfterReformat;
UITextPosition *pos = UITextPosition *pos =
[textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)cursorPositionAfterReformat]; [textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)cursorPositionAfterReformat];
[textField setSelectedTextRange:[textField textRangeFromPosition:pos toPosition:pos]]; [textField setSelectedTextRange:[textField textRangeFromPosition:pos toPosition:pos]];
return NO; // inform our caller that we took care of performing the change return NO; // inform our caller that we took care of performing the change
} }
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self sendCodeAction:nil];
[textField resignFirstResponder];
return NO;
}
#pragma mark - Unwind segue #pragma mark - Unwind segue
- (IBAction)unwindToChangeNumber:(UIStoryboardSegue *)sender { - (IBAction)unwindToChangeNumber:(UIStoryboardSegue *)sender {

Loading…
Cancel
Save