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 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" | 5 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #import "base/mac/foundation_util.h" | 8 #import "base/mac/foundation_util.h" |
9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
10 #include "components/strings/grit/components_strings.h" | 10 #include "components/strings/grit/components_strings.h" |
11 #import "ios/chrome/browser/ui/autofill/autofill_edit_accessory_view.h" | 11 #import "ios/chrome/browser/ui/autofill/autofill_edit_accessory_view.h" |
12 #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" | 12 #import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h" |
13 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom
e.h" | 13 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom
e.h" |
14 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item
.h" | 14 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item
.h" |
15 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item+collec
tion_view_controller.h" | 15 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item+collec
tion_view_controller.h" |
| 16 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item
.h" |
16 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" | 17 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" |
17 #import "ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.h" | 18 #import "ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.h" |
18 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h" | 19 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h" |
19 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller+int
ernal.h" | 20 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_act
ions.h" |
20 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" | 21 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" |
21 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 22 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
22 #include "ios/chrome/grit/ios_theme_resources.h" | 23 #include "ios/chrome/grit/ios_theme_resources.h" |
23 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | 24 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" |
24 #include "ui/base/l10n/l10n_util.h" | 25 #include "ui/base/l10n/l10n_util.h" |
25 | 26 |
26 #if !defined(__has_feature) || !__has_feature(objc_arc) | 27 #if !defined(__has_feature) || !__has_feature(objc_arc) |
27 #error "This file requires ARC support." | 28 #error "This file requires ARC support." |
28 #endif | 29 #endif |
29 | 30 |
(...skipping 15 matching lines...) Expand all Loading... |
45 AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view); | 46 AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view); |
46 if (cell) | 47 if (cell) |
47 return cell; | 48 return cell; |
48 } | 49 } |
49 | 50 |
50 // There has to be a cell associated with this text field. | 51 // There has to be a cell associated with this text field. |
51 NOTREACHED(); | 52 NOTREACHED(); |
52 return nil; | 53 return nil; |
53 } | 54 } |
54 | 55 |
| 56 CollectionViewSwitchCell* CollectionViewSwitchCellForSwitchField( |
| 57 UISwitch* switchField) { |
| 58 for (UIView* view = switchField; view; view = [view superview]) { |
| 59 CollectionViewSwitchCell* cell = |
| 60 base::mac::ObjCCast<CollectionViewSwitchCell>(view); |
| 61 if (cell) |
| 62 return cell; |
| 63 } |
| 64 |
| 65 // There should be a cell associated with this switch field. |
| 66 NOTREACHED(); |
| 67 return nil; |
| 68 } |
| 69 |
55 typedef NS_ENUM(NSInteger, SectionIdentifier) { | 70 typedef NS_ENUM(NSInteger, SectionIdentifier) { |
56 SectionIdentifierHeader = kSectionIdentifierEnumZero, | 71 SectionIdentifierHeader = kSectionIdentifierEnumZero, |
57 SectionIdentifierFooter, | 72 SectionIdentifierFooter, |
58 SectionIdentifierFirstField, // Must be the last section identifier. | 73 SectionIdentifierFirstField, // Must be the last section identifier. |
59 }; | 74 }; |
60 | 75 |
61 typedef NS_ENUM(NSInteger, ItemType) { | 76 typedef NS_ENUM(NSInteger, ItemType) { |
62 ItemTypeHeader = kItemTypeEnumZero, | 77 ItemTypeHeader = kItemTypeEnumZero, |
63 ItemTypeFooter, | 78 ItemTypeFooter, |
64 ItemTypeTextField, // This is a repeated item type. | 79 ItemTypeTextField, // This is a repeated item type. |
65 ItemTypeSelectorField, // This is a repeated item type. | 80 ItemTypeSelectorField, // This is a repeated item type. |
| 81 ItemTypeSwitchField, // This is a repeated item type. |
66 ItemTypeErrorMessage, // This is a repeated item type. | 82 ItemTypeErrorMessage, // This is a repeated item type. |
67 }; | 83 }; |
68 | 84 |
69 } // namespace | 85 } // namespace |
70 | 86 |
71 @interface PaymentRequestEditViewController ()<AutofillEditAccessoryDelegate, | 87 @interface PaymentRequestEditViewController ()< |
72 UITextFieldDelegate, | 88 AutofillEditAccessoryDelegate, |
73 UIPickerViewDataSource, | 89 PaymentRequestEditViewControllerActions, |
74 UIPickerViewDelegate> { | 90 UIPickerViewDataSource, |
| 91 UIPickerViewDelegate, |
| 92 UITextFieldDelegate> { |
75 // The currently focused cell. May be nil. | 93 // The currently focused cell. May be nil. |
76 __weak AutofillEditCell* _currentEditingCell; | 94 __weak AutofillEditCell* _currentEditingCell; |
77 | 95 |
78 AutofillEditAccessoryView* _accessoryView; | 96 AutofillEditAccessoryView* _accessoryView; |
79 } | 97 } |
80 | 98 |
81 // The map of autofill types to the fields definitions for the editor. | 99 // The map of section identifiers to the fields definitions for the editor. |
82 @property(nonatomic, strong) | 100 @property(nonatomic, strong) |
83 NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap; | 101 NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap; |
84 | 102 |
85 // The list of field definitions for the editor. | 103 // The list of field definitions for the editor. |
86 @property(nonatomic, strong) NSArray<EditorField*>* fields; | 104 @property(nonatomic, strong) NSArray<EditorField*>* fields; |
87 | 105 |
88 // The map of autofill types to lists of UIPickerView options. | 106 // The map of autofill types to lists of UIPickerView options. |
89 @property(nonatomic, strong) | 107 @property(nonatomic, strong) |
90 NSMutableDictionary<NSNumber*, NSArray<NSString*>*>* options; | 108 NSMutableDictionary<NSNumber*, NSArray<NSString*>*>* options; |
91 | 109 |
(...skipping 13 matching lines...) Expand all Loading... |
105 // Enables or disables the accessory view's previous and next buttons depending | 123 // Enables or disables the accessory view's previous and next buttons depending |
106 // on whether there is a text field before and after the currently focused text | 124 // on whether there is a text field before and after the currently focused text |
107 // field. | 125 // field. |
108 - (void)updateAccessoryViewButtonsStates; | 126 - (void)updateAccessoryViewButtonsStates; |
109 | 127 |
110 // Adds an error message item in the section |sectionIdentifier| if | 128 // Adds an error message item in the section |sectionIdentifier| if |
111 // |errorMessage| is non-empty. Otherwise removes such an item if one exists. | 129 // |errorMessage| is non-empty. Otherwise removes such an item if one exists. |
112 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage | 130 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage |
113 inSectionWithIdentifier:(NSInteger)sectionIdentifier; | 131 inSectionWithIdentifier:(NSInteger)sectionIdentifier; |
114 | 132 |
| 133 // Validates each field. If there is a validation error, displays an error |
| 134 // message item in the same section as the field and returns NO. Otherwise |
| 135 // removes the error message item in that section if one exists and sets the |
| 136 // value on the field. Returns YES if all the fields are validated successfully. |
| 137 - (BOOL)validateForm; |
| 138 |
| 139 // Returns the index path for the cell associated with the currently focused |
| 140 // text field. |
| 141 - (NSIndexPath*)indexPathForCurrentTextField; |
| 142 |
115 @end | 143 @end |
116 | 144 |
117 @implementation PaymentRequestEditViewController | 145 @implementation PaymentRequestEditViewController |
118 | 146 |
119 @synthesize dataSource = _dataSource; | 147 @synthesize dataSource = _dataSource; |
120 @synthesize delegate = _delegate; | 148 @synthesize delegate = _delegate; |
121 @synthesize validatorDelegate = _validatorDelegate; | 149 @synthesize validatorDelegate = _validatorDelegate; |
122 @synthesize fieldsMap = _fieldsMap; | 150 @synthesize fieldsMap = _fieldsMap; |
123 @synthesize fields = _fields; | 151 @synthesize fields = _fields; |
124 @synthesize options = _options; | 152 @synthesize options = _options; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 | 221 |
194 [self.pickerViews removeAllObjects]; | 222 [self.pickerViews removeAllObjects]; |
195 | 223 |
196 CollectionViewItem* headerItem = [_dataSource headerItem]; | 224 CollectionViewItem* headerItem = [_dataSource headerItem]; |
197 if (headerItem) { | 225 if (headerItem) { |
198 [headerItem setType:ItemTypeHeader]; | 226 [headerItem setType:ItemTypeHeader]; |
199 [model addSectionWithIdentifier:SectionIdentifierHeader]; | 227 [model addSectionWithIdentifier:SectionIdentifierHeader]; |
200 [model addItem:headerItem toSectionWithIdentifier:SectionIdentifierHeader]; | 228 [model addItem:headerItem toSectionWithIdentifier:SectionIdentifierHeader]; |
201 } | 229 } |
202 | 230 |
| 231 self.fieldsMap = |
| 232 [[NSMutableDictionary alloc] initWithCapacity:self.fields.count]; |
| 233 |
203 // Iterate over the fields and add the respective sections and items. | 234 // Iterate over the fields and add the respective sections and items. |
204 [self.fields enumerateObjectsUsingBlock:^(EditorField* field, | 235 [self.fields enumerateObjectsUsingBlock:^(EditorField* field, |
205 NSUInteger index, BOOL* stop) { | 236 NSUInteger index, BOOL* stop) { |
206 NSInteger sectionIdentifier = SectionIdentifierFirstField + index; | 237 NSInteger sectionIdentifier = SectionIdentifierFirstField + index; |
207 [model addSectionWithIdentifier:sectionIdentifier]; | 238 [model addSectionWithIdentifier:sectionIdentifier]; |
208 switch (field.fieldType) { | 239 switch (field.fieldType) { |
209 case EditorFieldTypeTextField: { | 240 case EditorFieldTypeTextField: { |
210 AutofillEditItem* item = | 241 AutofillEditItem* item = |
211 [[AutofillEditItem alloc] initWithType:ItemTypeTextField]; | 242 [[AutofillEditItem alloc] initWithType:ItemTypeTextField]; |
212 item.textFieldName = field.label; | 243 item.textFieldName = field.label; |
213 item.textFieldEnabled = field.enabled; | 244 item.textFieldEnabled = field.enabled; |
214 item.textFieldValue = field.value; | 245 item.textFieldValue = field.value; |
215 item.required = field.isRequired; | 246 item.required = field.isRequired; |
216 item.autofillUIType = field.autofillUIType; | 247 item.autofillUIType = field.autofillUIType; |
| 248 item.identifyingIcon = [_dataSource iconIdentifyingEditorField:field]; |
217 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; | 249 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; |
218 field.item = item; | 250 field.item = item; |
219 | 251 |
220 break; | 252 break; |
221 } | 253 } |
222 case EditorFieldTypeSelector: { | 254 case EditorFieldTypeSelector: { |
223 PaymentsSelectorEditItem* item = [[PaymentsSelectorEditItem alloc] | 255 PaymentsSelectorEditItem* item = [[PaymentsSelectorEditItem alloc] |
224 initWithType:ItemTypeSelectorField]; | 256 initWithType:ItemTypeSelectorField]; |
225 item.name = field.label; | 257 item.name = field.label; |
226 item.value = field.displayValue; | 258 item.value = field.displayValue; |
227 item.required = field.isRequired; | 259 item.required = field.isRequired; |
228 item.autofillUIType = field.autofillUIType; | 260 item.autofillUIType = field.autofillUIType; |
229 item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; | 261 item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator; |
230 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; | 262 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; |
231 field.item = item; | 263 field.item = item; |
232 break; | 264 break; |
233 } | 265 } |
| 266 case EditorFieldTypeSwitch: { |
| 267 CollectionViewSwitchItem* item = |
| 268 [[CollectionViewSwitchItem alloc] initWithType:ItemTypeSwitchField]; |
| 269 item.text = field.label; |
| 270 item.on = [field.value boolValue]; |
| 271 [model addItem:item toSectionWithIdentifier:sectionIdentifier]; |
| 272 field.item = item; |
| 273 break; |
| 274 } |
234 default: | 275 default: |
235 NOTREACHED(); | 276 NOTREACHED(); |
236 } | 277 } |
237 | 278 |
238 field.sectionIdentifier = sectionIdentifier; | 279 field.sectionIdentifier = sectionIdentifier; |
| 280 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; |
| 281 [self.fieldsMap setObject:field forKey:key]; |
239 }]; | 282 }]; |
240 | 283 |
241 [self loadFooterItems]; | 284 [model addSectionWithIdentifier:SectionIdentifierFooter]; |
| 285 CollectionViewFooterItem* footerItem = |
| 286 [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; |
| 287 footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE); |
| 288 [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter]; |
242 } | 289 } |
243 | 290 |
244 - (void)viewDidLoad { | 291 - (void)viewDidLoad { |
245 [super viewDidLoad]; | 292 [super viewDidLoad]; |
246 | 293 |
247 self.collectionView.accessibilityIdentifier = | 294 self.collectionView.accessibilityIdentifier = |
248 kPaymentRequestEditCollectionViewAccessibilityID; | 295 kPaymentRequestEditCollectionViewAccessibilityID; |
249 | 296 |
250 // Customize collection view settings. | 297 // Customize collection view settings. |
251 self.styler.cellStyle = MDCCollectionViewCellStyleCard; | 298 self.styler.cellStyle = MDCCollectionViewCellStyleCard; |
252 self.styler.separatorInset = | 299 self.styler.separatorInset = |
253 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset); | 300 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset); |
254 } | 301 } |
255 | 302 |
256 #pragma mark - PaymentRequestEditConsumer | 303 #pragma mark - PaymentRequestEditConsumer |
257 | 304 |
258 - (void)setEditorFields:(NSArray<EditorField*>*)fields { | 305 - (void)setEditorFields:(NSArray<EditorField*>*)fields { |
259 self.fields = fields; | 306 self.fields = fields; |
260 self.fieldsMap = [[NSMutableDictionary alloc] initWithCapacity:fields.count]; | |
261 // Iterate over the fields and populate the map. | |
262 [self.fields enumerateObjectsUsingBlock:^(EditorField* field, | |
263 NSUInteger index, BOOL* stop) { | |
264 NSNumber* key = [NSNumber numberWithInt:field.autofillUIType]; | |
265 [self.fieldsMap setObject:field forKey:key]; | |
266 }]; | |
267 } | 307 } |
268 | 308 |
269 - (void)setOptions:(NSArray<NSString*>*)options | 309 - (void)setOptions:(NSArray<NSString*>*)options |
270 forEditorField:(EditorField*)field { | 310 forEditorField:(EditorField*)field { |
271 DCHECK(field.fieldType == EditorFieldTypeTextField); | 311 DCHECK(field.fieldType == EditorFieldTypeTextField); |
272 AutofillEditItem* item = | 312 AutofillEditItem* item = |
273 base::mac::ObjCCastStrict<AutofillEditItem>(field.item); | 313 base::mac::ObjCCastStrict<AutofillEditItem>(field.item); |
274 item.textFieldEnabled = field.enabled; | 314 item.textFieldEnabled = field.enabled; |
275 item.textFieldValue = field.value; | 315 item.textFieldValue = field.value; |
276 | 316 |
(...skipping 20 matching lines...) Expand all Loading... |
297 | 337 |
298 - (void)textFieldDidBeginEditing:(UITextField*)textField { | 338 - (void)textFieldDidBeginEditing:(UITextField*)textField { |
299 _currentEditingCell = AutofillEditCellForTextField(textField); | 339 _currentEditingCell = AutofillEditCellForTextField(textField); |
300 [textField setInputAccessoryView:_accessoryView]; | 340 [textField setInputAccessoryView:_accessoryView]; |
301 [self updateAccessoryViewButtonsStates]; | 341 [self updateAccessoryViewButtonsStates]; |
302 } | 342 } |
303 | 343 |
304 - (void)textFieldDidEndEditing:(UITextField*)textField { | 344 - (void)textFieldDidEndEditing:(UITextField*)textField { |
305 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); | 345 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); |
306 | 346 |
307 CollectionViewModel* model = self.collectionViewModel; | 347 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; |
| 348 NSInteger sectionIdentifier = [self.collectionViewModel |
| 349 sectionIdentifierForSection:[indexPath section]]; |
308 | 350 |
309 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; | 351 // Find the respective editor field, update its value, and validate it. |
310 AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>( | 352 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; |
311 [model itemAtIndexPath:indexPath]); | |
312 | |
313 // Find and validate the respective editor field. | |
314 NSNumber* key = [NSNumber numberWithInt:item.autofillUIType]; | |
315 EditorField* field = self.fieldsMap[key]; | 353 EditorField* field = self.fieldsMap[key]; |
316 DCHECK(field); | 354 DCHECK(field); |
317 field.value = textField.text; | 355 field.value = textField.text; |
318 NSString* errorMessage = | 356 NSString* errorMessage = |
319 [_validatorDelegate paymentRequestEditViewController:self | 357 [_validatorDelegate paymentRequestEditViewController:self |
320 validateField:field]; | 358 validateField:field]; |
321 NSInteger sectionIdentifier = | |
322 [model sectionIdentifierForSection:[indexPath section]]; | |
323 [self addOrRemoveErrorMessage:errorMessage | 359 [self addOrRemoveErrorMessage:errorMessage |
324 inSectionWithIdentifier:sectionIdentifier]; | 360 inSectionWithIdentifier:sectionIdentifier]; |
325 | 361 |
326 [textField setInputAccessoryView:nil]; | 362 [textField setInputAccessoryView:nil]; |
327 _currentEditingCell = nil; | 363 _currentEditingCell = nil; |
328 } | 364 } |
329 | 365 |
330 - (BOOL)textFieldShouldReturn:(UITextField*)textField { | 366 - (BOOL)textFieldShouldReturn:(UITextField*)textField { |
331 DCHECK([_currentEditingCell textField] == textField); | 367 DCHECK([_currentEditingCell textField] == textField); |
332 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; | 368 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; |
333 if (nextCell) | 369 if (nextCell) |
334 [self nextPressed]; | 370 [self nextPressed]; |
335 else | 371 else |
336 [self closePressed]; | 372 [self closePressed]; |
337 | 373 |
338 return NO; | 374 return NO; |
339 } | 375 } |
340 | 376 |
| 377 // This method is called as the text is being typed in, pasted, or deleted. Asks |
| 378 // the delegate if the text should be changed. Should always return YES. During |
| 379 // typing/pasting text, |newText| contains one or more new characters. When user |
| 380 // deletes text, |newText| is empty. |range| is the range of characters to be |
| 381 // replaced. |
| 382 - (BOOL)textField:(UITextField*)textField |
| 383 shouldChangeCharactersInRange:(NSRange)range |
| 384 replacementString:(NSString*)newText { |
| 385 CollectionViewModel* model = self.collectionViewModel; |
| 386 |
| 387 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); |
| 388 |
| 389 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; |
| 390 NSInteger sectionIdentifier = |
| 391 [model sectionIdentifierForSection:[indexPath section]]; |
| 392 AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>( |
| 393 [model itemAtIndexPath:indexPath]); |
| 394 |
| 395 // Find the respective editor field and update its value. |
| 396 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; |
| 397 EditorField* field = self.fieldsMap[key]; |
| 398 DCHECK(field); |
| 399 // Obtain the text being typed. |
| 400 NSString* updatedText = |
| 401 [textField.text stringByReplacingCharactersInRange:range |
| 402 withString:newText]; |
| 403 field.value = updatedText; |
| 404 |
| 405 // Get the icon that identifies the field value and reload the cell if the |
| 406 // icon changes. |
| 407 UIImage* oldIcon = item.identifyingIcon; |
| 408 item.identifyingIcon = [_dataSource iconIdentifyingEditorField:field]; |
| 409 if (item.identifyingIcon != oldIcon) |
| 410 [self reconfigureCellsForItems:@[ item ]]; |
| 411 |
| 412 return YES; |
| 413 } |
| 414 |
341 #pragma mark - AutofillEditAccessoryDelegate | 415 #pragma mark - AutofillEditAccessoryDelegate |
342 | 416 |
343 - (void)nextPressed { | 417 - (void)nextPressed { |
344 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; | 418 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; |
345 if (nextCell) | 419 if (nextCell) |
346 [nextCell.textField becomeFirstResponder]; | 420 [nextCell.textField becomeFirstResponder]; |
347 } | 421 } |
348 | 422 |
349 - (void)previousPressed { | 423 - (void)previousPressed { |
350 AutofillEditCell* previousCell = [self nextTextFieldWithOffset:-1]; | 424 AutofillEditCell* previousCell = [self nextTextFieldWithOffset:-1]; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 base::mac::ObjCCast<AutofillEditCell>(cell); | 481 base::mac::ObjCCast<AutofillEditCell>(cell); |
408 autofillEditCell.textField.delegate = self; | 482 autofillEditCell.textField.delegate = self; |
409 autofillEditCell.textField.clearButtonMode = UITextFieldViewModeNever; | 483 autofillEditCell.textField.clearButtonMode = UITextFieldViewModeNever; |
410 autofillEditCell.textLabel.font = [MDCTypography body2Font]; | 484 autofillEditCell.textLabel.font = [MDCTypography body2Font]; |
411 autofillEditCell.textLabel.textColor = [[MDCPalette greyPalette] tint900]; | 485 autofillEditCell.textLabel.textColor = [[MDCPalette greyPalette] tint900]; |
412 autofillEditCell.textField.font = [MDCTypography body1Font]; | 486 autofillEditCell.textField.font = [MDCTypography body1Font]; |
413 autofillEditCell.textField.textColor = | 487 autofillEditCell.textField.textColor = |
414 [[MDCPalette cr_bluePalette] tint600]; | 488 [[MDCPalette cr_bluePalette] tint600]; |
415 break; | 489 break; |
416 } | 490 } |
| 491 case ItemTypeSwitchField: { |
| 492 CollectionViewSwitchCell* switchCell = |
| 493 base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell); |
| 494 [switchCell.switchView addTarget:self |
| 495 action:@selector(switchToggled:) |
| 496 forControlEvents:UIControlEventValueChanged]; |
| 497 break; |
| 498 } |
417 case ItemTypeErrorMessage: { | 499 case ItemTypeErrorMessage: { |
418 PaymentsTextCell* errorMessageCell = | 500 PaymentsTextCell* errorMessageCell = |
419 base::mac::ObjCCastStrict<PaymentsTextCell>(cell); | 501 base::mac::ObjCCastStrict<PaymentsTextCell>(cell); |
420 errorMessageCell.textLabel.font = [MDCTypography body1Font]; | 502 errorMessageCell.textLabel.font = [MDCTypography body1Font]; |
421 errorMessageCell.textLabel.textColor = | 503 errorMessageCell.textLabel.textColor = |
422 [[MDCPalette cr_redPalette] tint600]; | 504 [[MDCPalette cr_redPalette] tint600]; |
423 break; | 505 break; |
424 } | 506 } |
425 case ItemTypeFooter: { | 507 case ItemTypeFooter: { |
426 CollectionViewFooterCell* footerCell = | 508 CollectionViewFooterCell* footerCell = |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 #pragma mark MDCCollectionViewStylingDelegate | 546 #pragma mark MDCCollectionViewStylingDelegate |
465 | 547 |
466 - (CGFloat)collectionView:(UICollectionView*)collectionView | 548 - (CGFloat)collectionView:(UICollectionView*)collectionView |
467 cellHeightAtIndexPath:(NSIndexPath*)indexPath { | 549 cellHeightAtIndexPath:(NSIndexPath*)indexPath { |
468 CollectionViewItem* item = | 550 CollectionViewItem* item = |
469 [self.collectionViewModel itemAtIndexPath:indexPath]; | 551 [self.collectionViewModel itemAtIndexPath:indexPath]; |
470 switch (item.type) { | 552 switch (item.type) { |
471 case ItemTypeHeader: | 553 case ItemTypeHeader: |
472 case ItemTypeFooter: | 554 case ItemTypeFooter: |
473 case ItemTypeTextField: | 555 case ItemTypeTextField: |
| 556 case ItemTypeSwitchField: |
474 case ItemTypeErrorMessage: | 557 case ItemTypeErrorMessage: |
475 return [MDCCollectionViewCell | 558 return [MDCCollectionViewCell |
476 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) | 559 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) |
477 forItem:item]; | 560 forItem:item]; |
478 case ItemTypeSelectorField: | 561 case ItemTypeSelectorField: |
479 return MDCCellDefaultOneLineHeight; | 562 return MDCCellDefaultOneLineHeight; |
480 default: | 563 default: |
481 NOTREACHED(); | 564 NOTREACHED(); |
482 return MDCCellDefaultOneLineHeight; | 565 return MDCCellDefaultOneLineHeight; |
483 } | 566 } |
484 } | 567 } |
485 | 568 |
486 - (BOOL)collectionView:(UICollectionView*)collectionView | 569 - (BOOL)collectionView:(UICollectionView*)collectionView |
487 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { | 570 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { |
488 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; | 571 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; |
489 switch (type) { | 572 switch (type) { |
490 case ItemTypeHeader: | 573 case ItemTypeHeader: |
491 case ItemTypeFooter: | 574 case ItemTypeFooter: |
492 case ItemTypeErrorMessage: | 575 case ItemTypeErrorMessage: |
| 576 case ItemTypeTextField: |
| 577 case ItemTypeSwitchField: |
493 return YES; | 578 return YES; |
494 default: | 579 default: |
495 return NO; | 580 return NO; |
496 } | 581 } |
497 } | 582 } |
498 | 583 |
499 - (BOOL)collectionView:(UICollectionView*)collectionView | 584 - (BOOL)collectionView:(UICollectionView*)collectionView |
500 shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { | 585 shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { |
501 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; | 586 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; |
502 switch (type) { | 587 switch (type) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 errorMessageItem.text = errorMessage; | 660 errorMessageItem.text = errorMessage; |
576 errorMessageItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING); | 661 errorMessageItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING); |
577 errorMessageItem.accessibilityIdentifier = kWarningMessageAccessibilityID; | 662 errorMessageItem.accessibilityIdentifier = kWarningMessageAccessibilityID; |
578 [model addItem:errorMessageItem toSectionWithIdentifier:sectionIdentifier]; | 663 [model addItem:errorMessageItem toSectionWithIdentifier:sectionIdentifier]; |
579 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage | 664 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage |
580 sectionIdentifier:sectionIdentifier]; | 665 sectionIdentifier:sectionIdentifier]; |
581 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; | 666 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; |
582 } | 667 } |
583 } | 668 } |
584 | 669 |
585 #pragma mark - Keyboard handling | |
586 | |
587 - (void)keyboardDidShow { | |
588 [self.collectionView | |
589 scrollToItemAtIndexPath:[self.collectionView | |
590 indexPathForCell:_currentEditingCell] | |
591 atScrollPosition:UICollectionViewScrollPositionCenteredVertically | |
592 animated:YES]; | |
593 } | |
594 | |
595 @end | |
596 | |
597 @implementation PaymentRequestEditViewController (Internal) | |
598 | |
599 - (BOOL)validateForm { | 670 - (BOOL)validateForm { |
600 for (EditorField* field in self.fields) { | 671 for (EditorField* field in self.fields) { |
601 NSString* errorMessage = | 672 NSString* errorMessage = |
602 [_validatorDelegate paymentRequestEditViewController:self | 673 [_validatorDelegate paymentRequestEditViewController:self |
603 validateField:field]; | 674 validateField:field]; |
604 [self addOrRemoveErrorMessage:errorMessage | 675 [self addOrRemoveErrorMessage:errorMessage |
605 inSectionWithIdentifier:field.sectionIdentifier]; | 676 inSectionWithIdentifier:field.sectionIdentifier]; |
606 if (errorMessage.length) | 677 if (errorMessage.length) |
607 return NO; | 678 return NO; |
608 } | 679 } |
609 return YES; | 680 return YES; |
610 } | 681 } |
611 | 682 |
612 - (void)loadFooterItems { | |
613 CollectionViewModel* model = self.collectionViewModel; | |
614 | |
615 [model addSectionWithIdentifier:SectionIdentifierFooter]; | |
616 CollectionViewFooterItem* footerItem = | |
617 [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; | |
618 footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE); | |
619 [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter]; | |
620 } | |
621 | |
622 - (NSIndexPath*)indexPathForCurrentTextField { | 683 - (NSIndexPath*)indexPathForCurrentTextField { |
623 DCHECK(_currentEditingCell); | 684 DCHECK(_currentEditingCell); |
624 NSIndexPath* indexPath = | 685 NSIndexPath* indexPath = |
625 [[self collectionView] indexPathForCell:_currentEditingCell]; | 686 [[self collectionView] indexPathForCell:_currentEditingCell]; |
626 DCHECK(indexPath); | 687 DCHECK(indexPath); |
627 return indexPath; | 688 return indexPath; |
628 } | 689 } |
629 | 690 |
| 691 #pragma mark - Keyboard handling |
| 692 |
| 693 - (void)keyboardDidShow { |
| 694 [self.collectionView |
| 695 scrollToItemAtIndexPath:[self.collectionView |
| 696 indexPathForCell:_currentEditingCell] |
| 697 atScrollPosition:UICollectionViewScrollPositionCenteredVertically |
| 698 animated:YES]; |
| 699 } |
| 700 |
| 701 #pragma mark Switch Actions |
| 702 |
| 703 - (void)switchToggled:(UISwitch*)sender { |
| 704 CollectionViewSwitchCell* switchCell = |
| 705 CollectionViewSwitchCellForSwitchField(sender); |
| 706 NSIndexPath* indexPath = [[self collectionView] indexPathForCell:switchCell]; |
| 707 DCHECK(indexPath); |
| 708 |
| 709 NSInteger sectionIdentifier = [self.collectionViewModel |
| 710 sectionIdentifierForSection:[indexPath section]]; |
| 711 |
| 712 // Update editor field's value. |
| 713 NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; |
| 714 EditorField* field = self.fieldsMap[key]; |
| 715 DCHECK(field); |
| 716 field.value = [sender isOn] ? @"YES" : @"NO"; |
| 717 } |
| 718 |
630 #pragma mark - PaymentRequestEditViewControllerActions methods | 719 #pragma mark - PaymentRequestEditViewControllerActions methods |
631 | 720 |
632 - (void)onCancel { | 721 - (void)onCancel { |
| 722 [self.delegate paymentRequestEditViewControllerDidCancel:self]; |
633 } | 723 } |
634 | 724 |
635 - (void)onDone { | 725 - (void)onDone { |
636 [_currentEditingCell.textField resignFirstResponder]; | 726 [_currentEditingCell.textField resignFirstResponder]; |
| 727 |
| 728 if (![self validateForm]) |
| 729 return; |
| 730 |
| 731 [self.delegate paymentRequestEditViewController:self |
| 732 didFinishEditingFields:self.fields]; |
637 } | 733 } |
638 | 734 |
639 @end | 735 @end |
OLD | NEW |