- Notifications
You must be signed in to change notification settings - Fork 487
Fix OTP autofill by using UITextField in FUICodeField #930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -25,49 +25,37 @@ | |
| | ||
| @interface FUICodeField () | ||
| | ||
| @property (nonatomic, retain, readonly) UIView *inputField; | ||
| | ||
| @property (weak, nonatomic) IBOutlet UILabel *digits; | ||
| | ||
| @property (nonatomic, readonly) IBInspectable NSString *placeholder; | ||
| @property (nonatomic, readonly) IBInspectable NSString *placeholderChar; | ||
| | ||
| @end | ||
| | ||
| @implementation FUICodeField | ||
| | ||
| - (instancetype)initWithFrame:(CGRect)frame { | ||
| if (self = [super initWithFrame:frame]){ | ||
| [self setUpFromNib]; | ||
| [self commonInit]; | ||
| } | ||
| return self; | ||
| } | ||
| | ||
| - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { | ||
| if (self = [super initWithCoder:aDecoder]){ | ||
| [self setUpFromNib]; | ||
| [self commonInit]; | ||
| } | ||
| return self; | ||
| } | ||
| | ||
| - (void)setUpFromNib { | ||
| NSBundle *bundle = [FUIAuthUtils bundleNamed:FUIPhoneAuthBundleName]; | ||
| UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:bundle]; | ||
| | ||
| _inputField = [nib instantiateWithOwner:self options:nil][0]; | ||
| self.inputField.frame = [self bounds]; | ||
| self.inputField.autoresizingMask = | ||
| UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; | ||
| self.inputField.userInteractionEnabled = YES; | ||
| | ||
| if (@available(iOS 12.0, *)) { | ||
| if ([self.inputField respondsToSelector:@selector(setTextContentType:)]) { | ||
| id<UITextInputTraits> inputField = (id<UITextInputTraits>)self.inputField; | ||
| inputField.textContentType = UITextContentTypeOneTimeCode; | ||
| } | ||
| } | ||
| | ||
| - (void)commonInit { | ||
| // Initialization code | ||
| _codeEntry = [NSMutableString string]; | ||
| self.backgroundColor = UIColor.clearColor; | ||
| self.tintColor = UIColor.clearColor; | ||
| self.font = [UIFont fontWithName:@"Courier" size:40]; | ||
| self.textAlignment = NSTextAlignmentLeft; | ||
| UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, self.bounds.size.height)]; | ||
| self.leftView = paddingView; | ||
| self.leftViewMode = UITextFieldViewModeAlways; | ||
| self.textContentType = UITextContentTypeOneTimeCode; | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please keep the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll accept the PR as is and add this line manually since I want to get it into the next release. Thanks @akivab! | ||
| | ||
| // Default values | ||
| if (!self.codeLength) { | ||
| | @@ -76,11 +64,12 @@ - (void)setUpFromNib { | |
| _codeLength = MIN(self.codeLength, 12); | ||
| } | ||
| | ||
| if (!self.placeholder || !self.placeholder.length) { | ||
| _placeholder = @"-"; | ||
| if (!self.placeholderChar || !self.placeholderChar.length) { | ||
| _placeholderChar = @"-"; | ||
| } | ||
| | ||
| [self addSubview:self.inputField]; | ||
| self.delegate = self; | ||
| [self updateText]; | ||
| } | ||
| | ||
| - (UIKeyboardType) keyboardType { | ||
| | @@ -91,38 +80,6 @@ - (UIKeyboardType) keyboardType { | |
| } | ||
| } | ||
| | ||
| - (BOOL)canBecomeFirstResponder { | ||
| return YES; | ||
| } | ||
| | ||
| - (void) touchesBegan: (NSSet *) touches withEvent: (nullable UIEvent *) event { | ||
| [self becomeFirstResponder]; | ||
| } | ||
| | ||
| - (void)drawRect:(CGRect)rect { | ||
| NSString *code = [self.codeEntry copy]; | ||
| if (self.secureTextEntry) { | ||
| code = [[NSString string] stringByPaddingToLength:code.length | ||
| withString:@"\u2022" startingAtIndex:0]; | ||
| } | ||
| | ||
| NSInteger add = self.codeLength - code.length; | ||
| if (add > 0) { | ||
| NSString *pad = [[NSString string] stringByPaddingToLength:add | ||
| withString:self.placeholder | ||
| startingAtIndex:0]; | ||
| code = [code stringByAppendingString:pad]; | ||
| } | ||
| | ||
| NSMutableAttributedString *attributedString = | ||
| [[NSMutableAttributedString alloc] initWithString:code]; | ||
| [attributedString addAttribute:NSKernAttributeName value:@20 | ||
| range:NSMakeRange(0, attributedString.length-1)]; | ||
| | ||
| self.digits.text = @""; | ||
| [self.digits setAttributedText:attributedString]; | ||
| } | ||
| | ||
| - (BOOL)hasText { | ||
| return self.codeEntry.length > 0; | ||
| } | ||
| | @@ -131,63 +88,69 @@ - (void)insertText:(NSString *)theText { | |
| if (self.codeEntry.length >= self.codeLength){ | ||
| // UX: if code was submitted and there is an error message, | ||
| // typing a new number should clear the field and start over | ||
| [self updateText]; | ||
| return; | ||
| } | ||
| | ||
| [self.codeEntry appendString:theText]; | ||
| [self setNeedsDisplay]; | ||
| [self updateText]; | ||
| [self notifyEntryCompletion]; | ||
| } | ||
| | ||
| - (void)deleteBackward { | ||
| if (!self.codeEntry.length){ | ||
| if (!self.codeEntry.length) { | ||
| return; | ||
| } | ||
| | ||
| NSRange theRange = NSMakeRange(self.codeEntry.length-1, 1); | ||
| NSRange theRange = NSMakeRange(self.codeEntry.length - 1, 1); | ||
| [self.codeEntry deleteCharactersInRange:theRange]; | ||
| [self setNeedsDisplay]; | ||
| [self updateText]; | ||
| [self notifyEntryCompletion]; | ||
| } | ||
| | ||
| - (void)clearCodeInput { | ||
| [self.codeEntry setString:@""]; | ||
| | ||
| [self setNeedsDisplay]; | ||
| [self updateText]; | ||
| [self notifyEntryCompletion]; | ||
| } | ||
| | ||
| - (void)notifyEntryCompletion { | ||
| if (self.codeEntry.length >= self.codeLength) { | ||
| [self.delegate entryIsCompletedWithCode:[self.codeEntry copy]]; | ||
| [self.codeDelegate entryIsCompletedWithCode:[self.codeEntry copy]]; | ||
| } else { | ||
| [self.delegate entryIsIncomplete]; | ||
| [self.codeDelegate entryIsIncomplete]; | ||
| } | ||
| } | ||
| | ||
| - (CGSize)inputFieldIntrinsicContentSize { | ||
| CGSize textFieldSize = [self.inputField intrinsicContentSize]; | ||
| if (textFieldSize.height < FUICodeFieldMinInputFieldHeight) { | ||
| textFieldSize.height = FUICodeFieldMinInputFieldHeight; | ||
| } | ||
| | ||
| return textFieldSize; | ||
| } | ||
| - (void)updateText { | ||
| NSString *code = [self.codeEntry copy]; | ||
| if (self.secureTextEntry) { | ||
| code = [[NSString string] stringByPaddingToLength:code.length | ||
| withString:@"\u2022" startingAtIndex:0]; | ||
| } | ||
| | ||
| - (CGSize)intrinsicContentSize { | ||
| CGSize textFieldSize = [self inputFieldIntrinsicContentSize]; | ||
| return textFieldSize; | ||
| } | ||
| NSInteger add = self.codeLength - code.length; | ||
| if (add > 0) { | ||
| NSString *pad = [[NSString string] stringByPaddingToLength:add | ||
| withString:self.placeholderChar | ||
| startingAtIndex:0]; | ||
| code = [code stringByAppendingString:pad]; | ||
| } | ||
| | ||
| - (UITextContentType _Null_unspecified)textContentType { | ||
| if (@available(iOS 12.0, *)) { | ||
| return UITextContentTypeOneTimeCode; | ||
| } | ||
| return nil; | ||
| NSMutableAttributedString *attributedString = | ||
| [[NSMutableAttributedString alloc] initWithString:code]; | ||
| [attributedString addAttribute:NSKernAttributeName value:@20 | ||
| range:NSMakeRange(0, attributedString.length - 1)]; | ||
| self.attributedText = attributedString; | ||
| } | ||
| | ||
| - (void)setTextContentType:(_Null_unspecified UITextContentType)textContentType { | ||
| // do nothing | ||
| - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { | ||
| if (string.length == 0) { | ||
| [self deleteBackward]; | ||
| } else { | ||
| [self insertText:string]; | ||
| } | ||
| return false; | ||
| } | ||
| | ||
| @end | ||
| | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the cursor in UITextField made me increase the size of the area for the codeField in the FUIPhoneVerificationViewController.xib and add this space here