| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if !defined(__has_feature) || !__has_feature(objc_arc) | 5 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 6 #error "This file requires ARC support." | 6 #error "This file requires ARC support." |
| 7 #endif | 7 #endif |
| 8 | 8 |
| 9 #import "remoting/ios/app/pin_entry_view.h" | 9 #import "remoting/ios/app/pin_entry_view.h" |
| 10 | 10 |
| 11 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate
rialButtons.h" | 11 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate
rialButtons.h" |
| 12 #import "remoting/ios/app/remoting_theme.h" | 12 #import "remoting/ios/app/remoting_theme.h" |
| 13 | 13 |
| 14 static const CGFloat kMargin = 5.f; | 14 static const CGFloat kMargin = 5.f; |
| 15 static const CGFloat kPadding = 6.f; | 15 static const CGFloat kPadding = 8.f; |
| 16 static const CGFloat kLineSpace = 12.f; | 16 static const CGFloat kLineSpace = 12.f; |
| 17 | 17 |
| 18 @interface PinEntryView () { | 18 static const int kMinPinLength = 6; |
| 19 |
| 20 @interface PinEntryView ()<UITextFieldDelegate> { |
| 19 UISwitch* _pairingSwitch; | 21 UISwitch* _pairingSwitch; |
| 20 UILabel* _pairingLabel; | 22 UILabel* _pairingLabel; |
| 21 MDCFloatingButton* _pinButton; | 23 MDCFloatingButton* _pinButton; |
| 22 UITextField* _pinEntry; | 24 UITextField* _pinEntry; |
| 23 } | 25 } |
| 24 @end | 26 @end |
| 25 | 27 |
| 26 @implementation PinEntryView | 28 @implementation PinEntryView |
| 27 | 29 |
| 28 @synthesize delegate = _delegate; | 30 @synthesize delegate = _delegate; |
| 29 | 31 |
| 30 - (id)initWithFrame:(CGRect)frame { | 32 - (id)initWithFrame:(CGRect)frame { |
| 31 self = [super initWithFrame:frame]; | 33 self = [super initWithFrame:frame]; |
| 32 if (self) { | 34 if (self) { |
| 33 self.backgroundColor = [UIColor clearColor]; | 35 self.backgroundColor = [UIColor clearColor]; |
| 34 | 36 |
| 35 _pairingSwitch = [[UISwitch alloc] init]; | 37 _pairingSwitch = [[UISwitch alloc] init]; |
| 36 _pairingSwitch.tintColor = | 38 _pairingSwitch.tintColor = |
| 37 [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5]; | 39 [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5]; |
| 38 _pairingSwitch.transform = CGAffineTransformMakeScale(0.5, 0.5); | 40 _pairingSwitch.transform = CGAffineTransformMakeScale(0.5, 0.5); |
| 41 _pairingSwitch.translatesAutoresizingMaskIntoConstraints = NO; |
| 39 [self addSubview:_pairingSwitch]; | 42 [self addSubview:_pairingSwitch]; |
| 40 | 43 |
| 41 _pairingLabel = [[UILabel alloc] init]; | 44 _pairingLabel = [[UILabel alloc] init]; |
| 42 _pairingLabel.textColor = | 45 _pairingLabel.textColor = |
| 43 [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5]; | 46 [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5]; |
| 44 _pairingLabel.font = [UIFont systemFontOfSize:12.f]; | 47 _pairingLabel.font = [UIFont systemFontOfSize:12.f]; |
| 45 _pairingLabel.text = @"Remember my PIN on this device."; | 48 _pairingLabel.text = @"Remember my PIN on this device."; |
| 49 _pairingLabel.translatesAutoresizingMaskIntoConstraints = NO; |
| 46 [self addSubview:_pairingLabel]; | 50 [self addSubview:_pairingLabel]; |
| 47 | 51 |
| 48 _pinButton = | 52 _pinButton = |
| 49 [MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini]; | 53 [MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini]; |
| 50 [_pinButton setImage:RemotingTheme.arrowIcon forState:UIControlStateNormal]; | 54 [_pinButton setImage:RemotingTheme.arrowIcon forState:UIControlStateNormal]; |
| 51 [_pinButton addTarget:self | 55 [_pinButton addTarget:self |
| 52 action:@selector(didTapPinEntry:) | 56 action:@selector(didTapPinEntry:) |
| 53 forControlEvents:UIControlEventTouchUpInside]; | 57 forControlEvents:UIControlEventTouchUpInside]; |
| 54 _pinButton.translatesAutoresizingMaskIntoConstraints = NO; | 58 _pinButton.translatesAutoresizingMaskIntoConstraints = NO; |
| 59 _pinButton.enabled = NO; |
| 60 _pinButton.translatesAutoresizingMaskIntoConstraints = NO; |
| 55 [self addSubview:_pinButton]; | 61 [self addSubview:_pinButton]; |
| 56 | 62 |
| 57 _pinEntry = [[UITextField alloc] init]; | 63 _pinEntry = [[UITextField alloc] init]; |
| 58 _pinEntry.textColor = [UIColor whiteColor]; | 64 _pinEntry.textColor = [UIColor whiteColor]; |
| 59 _pinEntry.secureTextEntry = YES; | 65 _pinEntry.secureTextEntry = YES; |
| 60 _pinEntry.keyboardType = UIKeyboardTypeNumberPad; | 66 _pinEntry.keyboardType = UIKeyboardTypeNumberPad; |
| 61 // TODO(nicholss): L18N this. | 67 // TODO(nicholss): L18N this. |
| 62 _pinEntry.attributedPlaceholder = [[NSAttributedString alloc] | 68 _pinEntry.attributedPlaceholder = [[NSAttributedString alloc] |
| 63 initWithString:@"Enter PIN" | 69 initWithString:@"Enter PIN" |
| 64 attributes:@{ | 70 attributes:@{ |
| 65 NSForegroundColorAttributeName : | 71 NSForegroundColorAttributeName : |
| 66 [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5] | 72 [UIColor colorWithRed:1.f green:1.f blue:1.f alpha:0.5] |
| 67 }]; | 73 }]; |
| 74 _pinEntry.translatesAutoresizingMaskIntoConstraints = NO; |
| 75 _pinEntry.delegate = self; |
| 68 [self addSubview:_pinEntry]; | 76 [self addSubview:_pinEntry]; |
| 77 |
| 78 [self |
| 79 initializeLayoutConstraintsWithViews:NSDictionaryOfVariableBindings( |
| 80 _pairingSwitch, _pairingLabel, |
| 81 _pinButton, _pinEntry)]; |
| 69 } | 82 } |
| 70 return self; | 83 return self; |
| 71 } | 84 } |
| 72 | 85 |
| 86 - (void)initializeLayoutConstraintsWithViews:(NSDictionary*)views { |
| 87 // Metrics to use in visual format strings. |
| 88 NSDictionary* layoutMetrics = @{ |
| 89 @"margin" : @(kMargin), |
| 90 @"padding" : @(kPadding), |
| 91 @"lineSpace" : @(kLineSpace), |
| 92 }; |
| 93 |
| 94 [self addConstraints: |
| 95 [NSLayoutConstraint |
| 96 constraintsWithVisualFormat: |
| 97 @"H:|-[_pinEntry]-(padding)-[_pinButton]-|" |
| 98 options:NSLayoutFormatAlignAllCenterY |
| 99 metrics:layoutMetrics |
| 100 views:views]]; |
| 101 |
| 102 [self addConstraints: |
| 103 [NSLayoutConstraint |
| 104 constraintsWithVisualFormat: |
| 105 @"H:|-[_pairingSwitch]-(padding)-[_pairingLabel]-|" |
| 106 options:NSLayoutFormatAlignAllCenterY |
| 107 metrics:layoutMetrics |
| 108 views:views]]; |
| 109 |
| 110 [self addConstraints:[NSLayoutConstraint |
| 111 constraintsWithVisualFormat: |
| 112 @"V:|-[_pinButton]-(lineSpace)-[_pairingSwitch]" |
| 113 options:0 |
| 114 metrics:layoutMetrics |
| 115 views:views]]; |
| 116 [self setNeedsUpdateConstraints]; |
| 117 } |
| 118 |
| 73 #pragma mark - UIView | 119 #pragma mark - UIView |
| 74 | 120 |
| 75 - (BOOL)canBecomeFirstResponder { | 121 - (BOOL)canBecomeFirstResponder { |
| 76 return [_pinEntry canBecomeFirstResponder]; | 122 return [_pinEntry canBecomeFirstResponder]; |
| 77 } | 123 } |
| 78 | 124 |
| 79 - (BOOL)becomeFirstResponder { | 125 - (BOOL)becomeFirstResponder { |
| 80 return [_pinEntry becomeFirstResponder]; | 126 return [_pinEntry becomeFirstResponder]; |
| 81 } | 127 } |
| 82 | 128 |
| 83 - (BOOL)endEditing:(BOOL)force { | 129 - (BOOL)endEditing:(BOOL)force { |
| 84 return [_pinEntry endEditing:force]; | 130 return [_pinEntry endEditing:force]; |
| 85 } | 131 } |
| 86 | 132 |
| 87 - (void)layoutSubviews { | 133 #pragma mark - UITextFieldDelegate |
| 88 [super layoutSubviews]; | |
| 89 | 134 |
| 90 [_pinButton sizeToFit]; | 135 - (BOOL)textField:(UITextField*)textField |
| 91 CGFloat buttonSize = _pinButton.frame.size.width; // Assume circle. | 136 shouldChangeCharactersInRange:(NSRange)range |
| 137 replacementString:(NSString*)string { |
| 138 if (textField == _pinEntry) { |
| 139 NSUInteger length = _pinEntry.text.length - range.length + string.length; |
| 140 _pinButton.enabled = length >= kMinPinLength; |
| 141 } |
| 142 return YES; |
| 143 } |
| 92 | 144 |
| 93 _pinEntry.frame = | 145 - (BOOL)textFieldShouldReturn:(UITextField*)textField { |
| 94 CGRectMake(kMargin, 0.f, | 146 NSLog(@"textFieldShouldReturn"); |
| 95 self.frame.size.width - kPadding - kMargin * 2.f - buttonSize, | 147 if ([_pinButton isEnabled]) { |
| 96 buttonSize); | 148 [self didTapPinEntry:textField]; |
| 149 return YES; |
| 150 } |
| 151 return NO; |
| 152 } |
| 97 | 153 |
| 98 [_pinButton sizeToFit]; | 154 #pragma mark - Public |
| 99 _pinButton.frame = | |
| 100 CGRectMake(self.frame.size.width - kPadding - kMargin - buttonSize, 0.f, | |
| 101 buttonSize, buttonSize); | |
| 102 | 155 |
| 103 [_pairingSwitch sizeToFit]; | 156 - (void)clearPinEntry { |
| 104 _pairingSwitch.center = CGPointMake( | 157 _pinEntry.text = @""; |
| 105 kMargin + _pairingSwitch.frame.size.width / 2.f, | 158 _pinButton.enabled = NO; |
| 106 buttonSize + _pairingSwitch.frame.size.height / 2.f + kLineSpace); | |
| 107 | |
| 108 _pairingLabel.frame = | |
| 109 CGRectMake(kMargin + _pairingSwitch.frame.size.width + kPadding, | |
| 110 buttonSize + kLineSpace, 0.f, 0.f); | |
| 111 [_pairingLabel sizeToFit]; | |
| 112 } | 159 } |
| 113 | 160 |
| 114 #pragma mark - Private | 161 #pragma mark - Private |
| 115 | 162 |
| 116 - (void)didTapPinEntry:(id)sender { | 163 - (void)didTapPinEntry:(id)sender { |
| 117 [_delegate didProvidePin:_pinEntry.text createPairing:_pairingSwitch.isOn]; | 164 [_delegate didProvidePin:_pinEntry.text createPairing:_pairingSwitch.isOn]; |
| 118 [_pinEntry endEditing:YES]; | 165 [_pinEntry endEditing:YES]; |
| 119 } | 166 } |
| 120 | 167 |
| 121 @end | 168 @end |
| OLD | NEW |