Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: ios/chrome/browser/ui/autofill/cells/cvc_item.mm

Issue 2586993002: Upstream Chrome on iOS source code [3/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/ui/autofill/cells/cvc_item.h"
6
7 #include "components/strings/grit/components_strings.h"
8 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
9 #include "ios/chrome/grit/ios_strings.h"
10 #import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
11 #import "ios/public/provider/chrome/browser/ui/text_field_styling.h"
12 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h"
13 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoF ontLoader.h"
14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/base/resource/resource_bundle.h"
16
17 #if !defined(__has_feature) || !__has_feature(objc_arc)
18 #error "This file requires ARC support."
19 #endif
20
21 namespace {
22 // Padding used on the leading and trailing edges of the cell.
23 const CGFloat kHorizontalPadding = 16;
24 // Padding used on the top and bottom edges of the cell.
25 const CGFloat kVerticalPadding = 16;
26 // Spacing between elements.
27 const CGFloat kUISpacing = 5;
28 // Spacing around the CVC container.
29 const CGFloat kUICVCSpacing = 20;
30 // Height of the different text fields.
31 const CGFloat kTextFieldHeight = 50;
32 // Width of the date text fields.
33 const CGFloat kDateTextFieldWidth = 40;
34 // Width of the CVC text field.
35 const CGFloat kCVCTextFieldWidth = 60;
36 }
37
38 @interface CVCCell ()<UITextFieldDelegate>
39 @property(nonatomic, strong) UILabel* dateSeparator;
40 @property(nonatomic, strong) UIView* dateContainerView;
41 @property(nonatomic, strong) UIView* CVCContainerView;
42 @property(nonatomic, strong)
43 NSLayoutConstraint* CVCContainerLeadingConstraintWithDate;
44 @property(nonatomic, strong)
45 NSLayoutConstraint* CVCContainerLeadingConstraintWithoutDate;
46 @end
47
48 @implementation CVCItem
49
50 @synthesize instructionsText = _instructionsText;
51 @synthesize errorMessage = _errorMessage;
52 @synthesize monthText = _monthText;
53 @synthesize yearText = _yearText;
54 @synthesize CVCText = _CVCText;
55 @synthesize showDateInput = _showDateInput;
56 @synthesize showNewCardButton = _showNewCardButton;
57 @synthesize showDateInputError = _showDateInputError;
58 @synthesize showCVCInputError = _showCVCInputError;
59 @synthesize CVCImageResourceID = _CVCImageResourceID;
60
61 - (instancetype)initWithType:(NSInteger)type {
62 self = [super initWithType:type];
63 if (self) {
64 self.cellClass = [CVCCell class];
65 }
66 return self;
67 }
68
69 #pragma mark CollectionViewItem
70
71 - (void)configureCell:(CVCCell*)cell {
72 [super configureCell:cell];
73 cell.instructionsTextLabel.text = self.instructionsText;
74 cell.errorLabel.text = self.errorMessage;
75
76 cell.monthInput.text = self.monthText;
77 cell.yearInput.text = self.yearText;
78 cell.CVCInput.text = self.CVCText;
79
80 cell.dateContainerView.hidden = !self.showDateInput;
81
82 cell.CVCContainerLeadingConstraintWithDate.active = self.showDateInput;
83 cell.CVCContainerLeadingConstraintWithoutDate.active = !self.showDateInput;
84
85 [cell.monthInput setUseErrorStyling:self.showDateInputError];
86 [cell.yearInput setUseErrorStyling:self.showDateInputError];
87 [cell.CVCInput setUseErrorStyling:self.showDateInputError];
88
89 cell.buttonForNewCard.hidden = !self.showNewCardButton;
90
91 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
92 cell.CVCImageView.image =
93 rb.GetNativeImageNamed(self.CVCImageResourceID).ToUIImage();
94 }
95
96 @end
97
98 @implementation CVCCell
99
100 @synthesize instructionsTextLabel = _instructionsTextLabel;
101 @synthesize errorLabel = _errorLabel;
102 @synthesize monthInput = _monthInput;
103 @synthesize yearInput = _yearInput;
104 @synthesize CVCInput = _CVCInput;
105 @synthesize buttonForNewCard = _buttonForNewCard;
106 @synthesize dateSeparator = _dateSeparator;
107 @synthesize CVCImageView = _CVCImageView;
108 @synthesize dateContainerView = _dateContainerView;
109 @synthesize CVCContainerView = _CVCContainerView;
110 @synthesize CVCContainerLeadingConstraintWithDate =
111 _CVCContainerLeadingConstraintWithDate;
112 @synthesize CVCContainerLeadingConstraintWithoutDate =
113 _CVCContainerLeadingConstraintWithoutDate;
114
115 - (instancetype)initWithFrame:(CGRect)frame {
116 self = [super initWithFrame:frame];
117 if (self) {
118 UIView* contentView = self.contentView;
119
120 _instructionsTextLabel = [[UILabel alloc] init];
121 _instructionsTextLabel.font =
122 [[MDFRobotoFontLoader sharedInstance] mediumFontOfSize:14];
123 _instructionsTextLabel.textColor = [[MDCPalette greyPalette] tint500];
124 _instructionsTextLabel.numberOfLines = 0;
125 _instructionsTextLabel.lineBreakMode = NSLineBreakByWordWrapping;
126 _instructionsTextLabel.translatesAutoresizingMaskIntoConstraints = NO;
127 [contentView addSubview:_instructionsTextLabel];
128
129 _errorLabel = [[UILabel alloc] init];
130 _errorLabel.font =
131 [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:12];
132 _errorLabel.textColor = [[MDCPalette cr_redPalette] tint500];
133 _errorLabel.numberOfLines = 0;
134 _errorLabel.lineBreakMode = NSLineBreakByWordWrapping;
135 _errorLabel.translatesAutoresizingMaskIntoConstraints = NO;
136 [contentView addSubview:_errorLabel];
137
138 _dateContainerView = [[UIView alloc] init];
139 _dateContainerView.translatesAutoresizingMaskIntoConstraints = NO;
140 [contentView addSubview:_dateContainerView];
141
142 _monthInput =
143 ios::GetChromeBrowserProvider()->CreateStyledTextField(CGRectZero);
144 _monthInput.placeholder = l10n_util::GetNSString(
145 IDS_IOS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH);
146 _monthInput.keyboardType = UIKeyboardTypeNumberPad;
147 _monthInput.delegate = self;
148 _monthInput.translatesAutoresizingMaskIntoConstraints = NO;
149 [_dateContainerView addSubview:_monthInput];
150
151 _dateSeparator = [[UILabel alloc] init];
152 _dateSeparator.text = l10n_util::GetNSString(
153 IDS_AUTOFILL_CARD_UNMASK_EXPIRATION_DATE_SEPARATOR);
154 _dateSeparator.translatesAutoresizingMaskIntoConstraints = NO;
155 [_dateContainerView addSubview:_dateSeparator];
156
157 _yearInput =
158 ios::GetChromeBrowserProvider()->CreateStyledTextField(CGRectZero);
159 _yearInput.placeholder =
160 l10n_util::GetNSString(IDS_IOS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR);
161 _yearInput.keyboardType = UIKeyboardTypeNumberPad;
162 _yearInput.delegate = self;
163 _yearInput.translatesAutoresizingMaskIntoConstraints = NO;
164 [_dateContainerView addSubview:_yearInput];
165
166 _CVCContainerView = [[UIView alloc] init];
167 _CVCContainerView.translatesAutoresizingMaskIntoConstraints = NO;
168 [contentView addSubview:_CVCContainerView];
169
170 _CVCInput =
171 ios::GetChromeBrowserProvider()->CreateStyledTextField(CGRectZero);
172 _CVCInput.placeholder =
173 l10n_util::GetNSString(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC);
174 _CVCInput.keyboardType = UIKeyboardTypeNumberPad;
175 _CVCInput.delegate = self;
176 _CVCInput.translatesAutoresizingMaskIntoConstraints = NO;
177 [_CVCContainerView addSubview:_CVCInput];
178
179 _CVCImageView = [[UIImageView alloc] init];
180 _CVCImageView.translatesAutoresizingMaskIntoConstraints = NO;
181 [_CVCContainerView addSubview:_CVCImageView];
182
183 _buttonForNewCard = [UIButton buttonWithType:UIButtonTypeCustom];
184 _buttonForNewCard.titleLabel.font =
185 [[MDFRobotoFontLoader sharedInstance] regularFontOfSize:12];
186 [_buttonForNewCard
187 setTitle:l10n_util::GetNSString(IDS_AUTOFILL_CARD_UNMASK_NEW_CARD_LINK)
188 forState:UIControlStateNormal];
189 [_buttonForNewCard setTitleColor:[[MDCPalette cr_bluePalette] tint500]
190 forState:UIControlStateNormal];
191 _buttonForNewCard.translatesAutoresizingMaskIntoConstraints = NO;
192 [contentView addSubview:_buttonForNewCard];
193
194 [NSLayoutConstraint activateConstraints:@[
195 // Text label
196 [_instructionsTextLabel.topAnchor
197 constraintEqualToAnchor:contentView.topAnchor
198 constant:kVerticalPadding],
199 [_instructionsTextLabel.leadingAnchor
200 constraintEqualToAnchor:contentView.leadingAnchor
201 constant:kHorizontalPadding],
202 [_instructionsTextLabel.trailingAnchor
203 constraintEqualToAnchor:contentView.trailingAnchor
204 constant:-kHorizontalPadding],
205
206 // Date container
207 [_dateContainerView.topAnchor
208 constraintEqualToAnchor:_instructionsTextLabel.bottomAnchor
209 constant:kUISpacing],
210 [_dateContainerView.leadingAnchor
211 constraintEqualToAnchor:_instructionsTextLabel.leadingAnchor],
212 [_dateContainerView.heightAnchor
213 constraintEqualToConstant:kTextFieldHeight],
214
215 // Date content - Month input
216 [_monthInput.topAnchor
217 constraintEqualToAnchor:_dateContainerView.topAnchor],
218 [_monthInput.leadingAnchor
219 constraintEqualToAnchor:_dateContainerView.leadingAnchor],
220 [_monthInput.widthAnchor constraintEqualToConstant:kDateTextFieldWidth],
221 [_monthInput.bottomAnchor
222 constraintEqualToAnchor:_dateContainerView.bottomAnchor],
223
224 // Date content - Separator
225 [_dateSeparator.leadingAnchor
226 constraintEqualToAnchor:_monthInput.trailingAnchor
227 constant:kUISpacing],
228 [_dateSeparator.firstBaselineAnchor
229 constraintEqualToAnchor:_monthInput.firstBaselineAnchor],
230
231 // Date content = Year input
232 [_yearInput.leadingAnchor
233 constraintEqualToAnchor:_dateSeparator.trailingAnchor
234 constant:kUISpacing],
235 [_yearInput.widthAnchor constraintEqualToAnchor:_monthInput.widthAnchor],
236 [_yearInput.heightAnchor
237 constraintEqualToAnchor:_monthInput.heightAnchor],
238 [_yearInput.firstBaselineAnchor
239 constraintEqualToAnchor:_monthInput.firstBaselineAnchor],
240 [_dateContainerView.trailingAnchor
241 constraintEqualToAnchor:_yearInput.trailingAnchor],
242
243 // CVC container
244 [_CVCContainerView.topAnchor
245 constraintEqualToAnchor:_dateContainerView.topAnchor],
246 [_CVCContainerView.heightAnchor
247 constraintEqualToAnchor:_dateContainerView.heightAnchor],
248 // The horizontal placement of this container is dynamic. The two possible
249 // placements are defined below with
250 // _CVCContainerLeadingConstraintWithDate and
251 // _CVCContainerLeadingConstraintWithoutDate.
252
253 // CVC content - CVC input
254 [_CVCInput.leadingAnchor
255 constraintEqualToAnchor:_CVCContainerView.leadingAnchor],
256 [_CVCInput.widthAnchor constraintEqualToConstant:kCVCTextFieldWidth],
257 [_CVCInput.firstBaselineAnchor
258 constraintEqualToAnchor:_monthInput.firstBaselineAnchor],
259 [_CVCInput.bottomAnchor
260 constraintEqualToAnchor:_CVCContainerView.bottomAnchor],
261
262 // CVC content - CVC image view
263 [_CVCImageView.leadingAnchor
264 constraintEqualToAnchor:_CVCInput.trailingAnchor
265 constant:kUISpacing],
266 [_CVCImageView.centerYAnchor
267 constraintEqualToAnchor:_CVCInput.centerYAnchor],
268 [_CVCContainerView.trailingAnchor
269 constraintEqualToAnchor:_CVCImageView.trailingAnchor],
270
271 // "New Card?" label
272 [_buttonForNewCard.leadingAnchor
273 constraintEqualToAnchor:_CVCContainerView.trailingAnchor
274 constant:kUICVCSpacing],
275 [_buttonForNewCard.firstBaselineAnchor
276 constraintEqualToAnchor:_CVCInput.firstBaselineAnchor],
277
278 // Error label
279 [_errorLabel.topAnchor
280 constraintEqualToAnchor:_dateContainerView.bottomAnchor
281 constant:kUISpacing],
282 [_errorLabel.leadingAnchor
283 constraintEqualToAnchor:_instructionsTextLabel.leadingAnchor],
284 [_errorLabel.trailingAnchor
285 constraintEqualToAnchor:_instructionsTextLabel.trailingAnchor],
286
287 [contentView.bottomAnchor constraintEqualToAnchor:_errorLabel.bottomAnchor
288 constant:kUISpacing],
289 ]];
290
291 _CVCContainerLeadingConstraintWithDate = [_CVCContainerView.leadingAnchor
292 constraintEqualToAnchor:_dateContainerView.trailingAnchor
293 constant:kUICVCSpacing];
294 _CVCContainerLeadingConstraintWithoutDate = [_CVCContainerView.leadingAnchor
295 constraintEqualToAnchor:_instructionsTextLabel.leadingAnchor];
296 }
297 return self;
298 }
299
300 - (void)prepareForReuse {
301 [super prepareForReuse];
302 self.instructionsTextLabel.text = nil;
303 self.errorLabel.text = nil;
304 self.monthInput.text = nil;
305 [self.monthInput removeTarget:nil
306 action:nil
307 forControlEvents:UIControlEventAllEvents];
308 self.yearInput.text = nil;
309 [self.yearInput removeTarget:nil
310 action:nil
311 forControlEvents:UIControlEventAllEvents];
312 self.CVCInput.text = nil;
313 [self.CVCInput removeTarget:nil
314 action:nil
315 forControlEvents:UIControlEventAllEvents];
316 [self.buttonForNewCard removeTarget:nil
317 action:nil
318 forControlEvents:UIControlEventAllEvents];
319 self.dateContainerView.hidden = YES;
320 self.CVCContainerLeadingConstraintWithDate.active = NO;
321 self.CVCContainerLeadingConstraintWithoutDate.active = YES;
322 [self.monthInput setUseErrorStyling:NO];
323 [self.yearInput setUseErrorStyling:NO];
324 [self.CVCInput setUseErrorStyling:NO];
325 self.buttonForNewCard.hidden = YES;
326 self.CVCImageView.image = nil;
327 }
328
329 // Implements -layoutSubviews as per instructions in documentation for
330 // +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:].
331 - (void)layoutSubviews {
332 [super layoutSubviews];
333
334 // Adjust the text labels preferredMaxLayoutWidth when the parent's width
335 // changes, for instance on screen rotation.
336 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
337 CGFloat labelsPreferredMaxLayoutWidth = parentWidth - 2 * kHorizontalPadding;
338 self.instructionsTextLabel.preferredMaxLayoutWidth =
339 labelsPreferredMaxLayoutWidth;
340 self.errorLabel.preferredMaxLayoutWidth = labelsPreferredMaxLayoutWidth;
341
342 // Re-layout with the new preferred width to allow the labels to adjust their
343 // height.
344 [super layoutSubviews];
345 }
346
347 #pragma mark - UITextFieldDelegate
348
349 // Limit month input to 2 characters. Year input is limited to 4 characters
350 // (both 2-digit and 4-digit years are accepted). CVC input is limited to 4
351 // characters since CVCs are never longer than that.
352 - (BOOL)textField:(UITextField*)textField
353 shouldChangeCharactersInRange:(NSRange)range
354 replacementString:(NSString*)string {
355 if (textField == self.CVCInput || textField == self.yearInput) {
356 return ([textField.text length] + [string length] - range.length) <= 4;
357 } else if (textField == self.monthInput) {
358 return ([textField.text length] + [string length] - range.length) <= 2;
359 }
360 return YES;
361 }
362
363 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/ui/autofill/cells/cvc_item.h ('k') | ios/chrome/browser/ui/autofill/cells/cvc_item_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698