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

Side by Side Diff: ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm

Issue 2876603005: [Payment Request] Refactors the edit view controller (Closed)
Patch Set: Addressed comments Created 3 years, 7 months 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
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/colors/MDCPalette+CrAdditions.h" 16 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
17 #import "ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.h"
16 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h" 18 #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h"
17 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller+int ernal.h" 19 #import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller+int ernal.h"
18 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h" 20 #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
19 #import "ios/chrome/browser/ui/uikit_ui_util.h" 21 #import "ios/chrome/browser/ui/uikit_ui_util.h"
20 #include "ios/chrome/grit/ios_theme_resources.h" 22 #include "ios/chrome/grit/ios_theme_resources.h"
21 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" 23 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h"
22 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
23 25
24 #if !defined(__has_feature) || !__has_feature(objc_arc) 26 #if !defined(__has_feature) || !__has_feature(objc_arc)
25 #error "This file requires ARC support." 27 #error "This file requires ARC support."
26 #endif 28 #endif
27 29
28 NSString* const kWarningMessageAccessibilityID = 30 NSString* const kWarningMessageAccessibilityID =
29 @"kWarningMessageAccessibilityID"; 31 @"kWarningMessageAccessibilityID";
30 32
31 namespace { 33 namespace {
32 34
33 NSString* const kPaymentRequestEditCollectionViewID = 35 NSString* const kPaymentRequestEditCollectionViewAccessibilityID =
34 @"kPaymentRequestEditCollectionViewID"; 36 @"kPaymentRequestEditCollectionViewAccessibilityID";
35 37
36 const CGFloat kSeparatorEdgeInset = 14; 38 const CGFloat kSeparatorEdgeInset = 14;
37 39
38 const CGFloat kFooterCellHorizontalPadding = 16; 40 const CGFloat kFooterCellHorizontalPadding = 16;
39 41
40 // Returns the AutofillEditCell that is the parent view of the |textField|. 42 // Returns the AutofillEditCell that is the parent view of the |textField|.
41 AutofillEditCell* AutofillEditCellForTextField(UITextField* textField) { 43 AutofillEditCell* AutofillEditCellForTextField(UITextField* textField) {
42 for (UIView* view = textField; view; view = [view superview]) { 44 for (UIView* view = textField; view; view = [view superview]) {
43 AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view); 45 AutofillEditCell* cell = base::mac::ObjCCast<AutofillEditCell>(view);
44 if (cell) 46 if (cell)
45 return cell; 47 return cell;
46 } 48 }
47 49
48 // There has to be a cell associated with this text field. 50 // There has to be a cell associated with this text field.
49 NOTREACHED(); 51 NOTREACHED();
50 return nil; 52 return nil;
51 } 53 }
52 54
53 typedef NS_ENUM(NSInteger, SectionIdentifier) { 55 typedef NS_ENUM(NSInteger, SectionIdentifier) {
54 SectionIdentifierFooter = kSectionIdentifierEnumZero, 56 SectionIdentifierHeader = kSectionIdentifierEnumZero,
55 SectionIdentifierFirstTextField, 57 SectionIdentifierFooter,
58 SectionIdentifierFirstField, // Must be the last section identifier.
56 }; 59 };
57 60
58 typedef NS_ENUM(NSInteger, ItemType) { 61 typedef NS_ENUM(NSInteger, ItemType) {
59 ItemTypeFooter = kItemTypeEnumZero, 62 ItemTypeHeader = kItemTypeEnumZero,
60 ItemTypeTextField, // This is a repeated item type. 63 ItemTypeFooter,
61 ItemTypeErrorMessage, // This is a repeated item type. 64 ItemTypeTextField, // This is a repeated item type.
65 ItemTypeSelectorField, // This is a repeated item type.
66 ItemTypeErrorMessage, // This is a repeated item type.
62 }; 67 };
63 68
64 } // namespace 69 } // namespace
65 70
66 @interface PaymentRequestEditViewController ()< 71 @interface PaymentRequestEditViewController ()<
67 AutofillEditAccessoryDelegate, 72 AutofillEditAccessoryDelegate,
68 PaymentRequestEditViewControllerValidator,
69 UITextFieldDelegate> { 73 UITextFieldDelegate> {
70 NSArray<EditorField*>* _fields; 74 NSArray<EditorField*>* _fields;
71 75
72 // The currently focused cell. May be nil. 76 // The currently focused cell. May be nil.
73 __weak AutofillEditCell* _currentEditingCell; 77 __weak AutofillEditCell* _currentEditingCell;
74 78
75 AutofillEditAccessoryView* _accessoryView; 79 AutofillEditAccessoryView* _accessoryView;
76 } 80 }
77 81
78 // Returns the indexPath for the same row as that of |indexPath| in a section 82 // Returns the indexPath for the same row as that of |indexPath| in a section
79 // with the given offset relative to that of |indexPath|. May return nil. 83 // with the given offset relative to that of |indexPath|. May return nil.
80 - (NSIndexPath*)indexPathWithSectionOffset:(NSInteger)offset 84 - (NSIndexPath*)indexPathWithSectionOffset:(NSInteger)offset
81 fromPath:(NSIndexPath*)indexPath; 85 fromPath:(NSIndexPath*)indexPath;
82 86
83 // Returns the text field with the given offset relative to the currently 87 // Returns the text field with the given offset relative to the currently
84 // focused text field. May return nil. 88 // focused text field. May return nil.
85 - (AutofillEditCell*)nextTextFieldWithOffset:(NSInteger)offset; 89 - (AutofillEditCell*)nextTextFieldWithOffset:(NSInteger)offset;
86 90
87 // Enables or disables the accessory view's previous and next buttons depending 91 // Enables or disables the accessory view's previous and next buttons depending
88 // on whether there is a text field before and after the currently focused text 92 // on whether there is a text field before and after the currently focused text
89 // field. 93 // field.
90 - (void)updateAccessoryViewButtonsStates; 94 - (void)updateAccessoryViewButtonsStates;
91 95
96 // Adds an error message item in the section |sectionIdentifier| if
97 // |errorMessage| is non-empty. Otherwise removes such an item if one exists.
98 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage
99 inSectionWithIdentifier:(NSInteger)sectionIdentifier;
100
92 @end 101 @end
93 102
94 @implementation PaymentRequestEditViewController 103 @implementation PaymentRequestEditViewController
95 104
96 @synthesize dataSource = _dataSource; 105 @synthesize dataSource = _dataSource;
106 @synthesize delegate = _delegate;
97 @synthesize validatorDelegate = _validatorDelegate; 107 @synthesize validatorDelegate = _validatorDelegate;
98 108
99 - (instancetype)initWithStyle:(CollectionViewControllerStyle)style { 109 - (instancetype)initWithStyle:(CollectionViewControllerStyle)style {
100 self = [super initWithStyle:style]; 110 self = [super initWithStyle:style];
101 if (self) { 111 if (self) {
102 // Set self as the validator delegate.
103 _validatorDelegate = self;
104
105 _accessoryView = [[AutofillEditAccessoryView alloc] initWithDelegate:self]; 112 _accessoryView = [[AutofillEditAccessoryView alloc] initWithDelegate:self];
106 } 113 }
107 return self; 114 return self;
108 } 115 }
109 116
110 - (void)setDataSource: 117 - (void)setDataSource:
111 (id<PaymentRequestEditViewControllerDataSource>)dataSource { 118 (id<PaymentRequestEditViewControllerDataSource>)dataSource {
112 _dataSource = dataSource; 119 _dataSource = dataSource;
113 _fields = [dataSource editorFields]; 120 _fields = [dataSource editorFields];
114 } 121 }
(...skipping 14 matching lines...) Expand all
129 name:UIKeyboardDidShowNotification 136 name:UIKeyboardDidShowNotification
130 object:nil]; 137 object:nil];
131 } 138 }
132 139
133 #pragma mark - CollectionViewController methods 140 #pragma mark - CollectionViewController methods
134 141
135 - (void)loadModel { 142 - (void)loadModel {
136 [super loadModel]; 143 [super loadModel];
137 CollectionViewModel* model = self.collectionViewModel; 144 CollectionViewModel* model = self.collectionViewModel;
138 145
139 [self loadHeaderItems]; 146 CollectionViewItem* headerItem = [_dataSource headerItem];
147 if (headerItem) {
148 [headerItem setType:ItemTypeHeader];
149 [model addSectionWithIdentifier:SectionIdentifierHeader];
150 [model addItem:headerItem toSectionWithIdentifier:SectionIdentifierHeader];
151 }
140 152
141 // Iterate over the fields and add the respective sections and items. 153 // Iterate over the fields and add the respective sections and items.
142 int sectionIdentifier = static_cast<int>(SectionIdentifierFirstTextField); 154 int sectionIdentifier = static_cast<int>(SectionIdentifierFirstField);
143 for (EditorField* field in _fields) { 155 for (EditorField* field in _fields) {
144 [model addSectionWithIdentifier:sectionIdentifier]; 156 [model addSectionWithIdentifier:sectionIdentifier];
145 AutofillEditItem* item = 157 switch (field.fieldType) {
146 [[AutofillEditItem alloc] initWithType:ItemTypeTextField]; 158 case EditorFieldTypeTextField: {
147 item.textFieldName = field.label; 159 AutofillEditItem* item =
148 item.textFieldEnabled = YES; 160 [[AutofillEditItem alloc] initWithType:ItemTypeTextField];
149 item.textFieldValue = field.value; 161 item.textFieldName = field.label;
150 item.required = field.isRequired; 162 item.textFieldEnabled = YES;
151 item.autofillUIType = field.autofillUIType; 163 item.textFieldValue = field.value;
152 [model addItem:item 164 item.required = field.isRequired;
153 toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)]; 165 item.autofillUIType = field.autofillUIType;
154 field.item = item; 166 [model addItem:item
167 toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)];
168 field.item = item;
169 break;
170 }
171 case EditorFieldTypeSelector: {
172 PaymentsSelectorEditItem* item = [[PaymentsSelectorEditItem alloc]
173 initWithType:ItemTypeSelectorField];
174 item.name = field.label;
175 item.value = field.displayValue;
176 item.required = field.isRequired;
177 item.autofillUIType = field.autofillUIType;
178 item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
179 [model addItem:item
180 toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)];
181 field.item = item;
182 break;
183 }
184 default:
185 NOTREACHED();
186 }
187
155 field.sectionIdentifier = static_cast<NSInteger>(sectionIdentifier); 188 field.sectionIdentifier = static_cast<NSInteger>(sectionIdentifier);
156 ++sectionIdentifier; 189 ++sectionIdentifier;
157 } 190 }
158 191
159 [self loadFooterItems]; 192 [self loadFooterItems];
160 } 193 }
161 194
162 - (void)viewDidLoad { 195 - (void)viewDidLoad {
163 [super viewDidLoad]; 196 [super viewDidLoad];
164 197
165 self.collectionView.accessibilityIdentifier = 198 self.collectionView.accessibilityIdentifier =
166 kPaymentRequestEditCollectionViewID; 199 kPaymentRequestEditCollectionViewAccessibilityID;
167 200
168 // Customize collection view settings. 201 // Customize collection view settings.
169 self.styler.cellStyle = MDCCollectionViewCellStyleCard; 202 self.styler.cellStyle = MDCCollectionViewCellStyleCard;
170 self.styler.separatorInset = 203 self.styler.separatorInset =
171 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset); 204 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset);
172 } 205 }
173 206
174 #pragma mark - UITextFieldDelegate 207 #pragma mark - UITextFieldDelegate
175 208
176 - (void)textFieldDidBeginEditing:(UITextField*)textField { 209 - (void)textFieldDidBeginEditing:(UITextField*)textField {
177 _currentEditingCell = AutofillEditCellForTextField(textField); 210 _currentEditingCell = AutofillEditCellForTextField(textField);
178 [textField setInputAccessoryView:_accessoryView]; 211 [textField setInputAccessoryView:_accessoryView];
179 [self updateAccessoryViewButtonsStates]; 212 [self updateAccessoryViewButtonsStates];
180 } 213 }
181 214
182 - (void)textFieldDidEndEditing:(UITextField*)textField { 215 - (void)textFieldDidEndEditing:(UITextField*)textField {
183 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField)); 216 DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField));
184 217
185 // Validate the text field. 218 // Validate the text field.
186 CollectionViewModel* model = self.collectionViewModel; 219 CollectionViewModel* model = self.collectionViewModel;
187 220
188 NSIndexPath* indexPath = [self indexPathForCurrentTextField]; 221 NSIndexPath* indexPath = [self indexPathForCurrentTextField];
189 AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>( 222 AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
190 [model itemAtIndexPath:indexPath]); 223 [model itemAtIndexPath:indexPath]);
191 224
225 // Create a dummy EditorField for validation only.
226 EditorField* fieldForValidation =
227 [[EditorField alloc] initWithAutofillUIType:item.autofillUIType
228 fieldType:EditorFieldTypeTextField
229 label:nil
230 value:textField.text
231 required:item.required];
192 NSString* errorMessage = 232 NSString* errorMessage =
193 [_validatorDelegate paymentRequestEditViewController:self 233 [_validatorDelegate paymentRequestEditViewController:self
194 validateValue:textField.text 234 validateField:fieldForValidation];
195 autofillUIType:item.autofillUIType
196 required:item.required];
197 NSInteger sectionIdentifier = 235 NSInteger sectionIdentifier =
198 [model sectionIdentifierForSection:[indexPath section]]; 236 [model sectionIdentifierForSection:[indexPath section]];
199 [self addOrRemoveErrorMessage:errorMessage 237 [self addOrRemoveErrorMessage:errorMessage
200 inSectionWithIdentifier:sectionIdentifier]; 238 inSectionWithIdentifier:sectionIdentifier];
201 239
202 [textField setInputAccessoryView:nil]; 240 [textField setInputAccessoryView:nil];
203 _currentEditingCell = nil; 241 _currentEditingCell = nil;
204 } 242 }
205 243
206 - (BOOL)textFieldShouldReturn:(UITextField*)textField { 244 - (BOOL)textFieldShouldReturn:(UITextField*)textField {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 footerCell.horizontalPadding = kFooterCellHorizontalPadding; 309 footerCell.horizontalPadding = kFooterCellHorizontalPadding;
272 break; 310 break;
273 } 311 }
274 default: 312 default:
275 break; 313 break;
276 } 314 }
277 315
278 return cell; 316 return cell;
279 } 317 }
280 318
319 #pragma mark UICollectionViewDelegate
320
321 - (void)collectionView:(UICollectionView*)collectionView
322 didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
323 [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
324
325 // Every field has its own section. Find out which field is selected using
326 // the section of |indexPath|. Adjust the index if a header section is
327 // present before the editor fields.
328 NSInteger index = indexPath.section;
329 if ([self.collectionViewModel
330 hasSectionForSectionIdentifier:SectionIdentifierHeader])
331 index--;
332 DCHECK(index >= 0 && index < static_cast<NSInteger>(_fields.count));
333 [_delegate paymentRequestEditViewController:self
334 didSelectField:[_fields objectAtIndex:index]];
335 }
336
281 #pragma mark MDCCollectionViewStylingDelegate 337 #pragma mark MDCCollectionViewStylingDelegate
282 338
283 - (CGFloat)collectionView:(UICollectionView*)collectionView 339 - (CGFloat)collectionView:(UICollectionView*)collectionView
284 cellHeightAtIndexPath:(NSIndexPath*)indexPath { 340 cellHeightAtIndexPath:(NSIndexPath*)indexPath {
285 CollectionViewItem* item = 341 CollectionViewItem* item =
286 [self.collectionViewModel itemAtIndexPath:indexPath]; 342 [self.collectionViewModel itemAtIndexPath:indexPath];
287 switch (item.type) { 343 switch (item.type) {
344 case ItemTypeHeader:
345 case ItemTypeFooter:
288 case ItemTypeTextField: 346 case ItemTypeTextField:
289 case ItemTypeErrorMessage: 347 case ItemTypeErrorMessage:
290 case ItemTypeFooter:
291 return [MDCCollectionViewCell 348 return [MDCCollectionViewCell
292 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) 349 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
293 forItem:item]; 350 forItem:item];
351 case ItemTypeSelectorField:
352 return MDCCellDefaultOneLineHeight;
294 default: 353 default:
295 NOTREACHED(); 354 NOTREACHED();
296 return MDCCellDefaultOneLineHeight; 355 return MDCCellDefaultOneLineHeight;
297 } 356 }
298 } 357 }
299 358
300 - (BOOL)collectionView:(UICollectionView*)collectionView 359 - (BOOL)collectionView:(UICollectionView*)collectionView
301 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { 360 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
302 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; 361 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
303 switch (type) { 362 switch (type) {
363 case ItemTypeHeader:
364 case ItemTypeFooter:
304 case ItemTypeErrorMessage: 365 case ItemTypeErrorMessage:
305 case ItemTypeFooter:
306 return YES; 366 return YES;
307 default: 367 default:
308 return NO; 368 return NO;
309 } 369 }
310 } 370 }
311 371
312 - (BOOL)collectionView:(UICollectionView*)collectionView 372 - (BOOL)collectionView:(UICollectionView*)collectionView
313 shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { 373 shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath {
314 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; 374 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
315 switch (type) { 375 switch (type) {
376 case ItemTypeHeader:
377 return [_dataSource shouldHideBackgroundForHeaderItem];
316 case ItemTypeFooter: 378 case ItemTypeFooter:
317 return YES; 379 return YES;
318 default: 380 default:
319 return NO; 381 return NO;
320 } 382 }
321 } 383 }
322 384
323 #pragma mark - PaymentRequestEditViewControllerValidator
324
325 - (NSString*)paymentRequestEditViewController:
326 (PaymentRequestEditViewController*)controller
327 validateValue:(NSString*)value
328 autofillUIType:(AutofillUIType)autofillUIType
329 required:(BOOL)required {
330 if (required && !value.length) {
331 return l10n_util::GetNSString(
332 IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE);
333 }
334 return nil;
335 }
336
337 #pragma mark - Helper methods 385 #pragma mark - Helper methods
338 386
339 - (NSIndexPath*)indexPathWithSectionOffset:(NSInteger)offset 387 - (NSIndexPath*)indexPathWithSectionOffset:(NSInteger)offset
340 fromPath:(NSIndexPath*)indexPath { 388 fromPath:(NSIndexPath*)indexPath {
341 DCHECK(indexPath); 389 DCHECK(indexPath);
342 DCHECK(offset); 390 DCHECK(offset);
343 NSInteger nextSection = [indexPath section] + offset; 391 NSInteger nextSection = [indexPath section] + offset;
344 if (nextSection >= 0 && 392 if (nextSection >= 0 &&
345 nextSection < [[self collectionView] numberOfSections]) { 393 nextSection < [[self collectionView] numberOfSections]) {
346 return [NSIndexPath indexPathForRow:[indexPath row] inSection:nextSection]; 394 return [NSIndexPath indexPathForRow:[indexPath row] inSection:nextSection];
347 } 395 }
348 return nil; 396 return nil;
349 } 397 }
350 398
351 - (AutofillEditCell*)nextTextFieldWithOffset:(NSInteger)offset { 399 - (AutofillEditCell*)nextTextFieldWithOffset:(NSInteger)offset {
352 UICollectionView* collectionView = [self collectionView]; 400 UICollectionView* collectionView = [self collectionView];
353 NSIndexPath* currentCellPath = [self indexPathForCurrentTextField]; 401 NSIndexPath* currentCellPath = [self indexPathForCurrentTextField];
354 DCHECK(currentCellPath); 402 DCHECK(currentCellPath);
355 NSIndexPath* nextCellPath = 403 NSIndexPath* nextCellPath =
356 [self indexPathWithSectionOffset:offset fromPath:currentCellPath]; 404 [self indexPathWithSectionOffset:offset fromPath:currentCellPath];
357 if (nextCellPath) { 405 while (nextCellPath) {
358 id nextCell = [collectionView cellForItemAtIndexPath:nextCellPath]; 406 id nextCell = [collectionView cellForItemAtIndexPath:nextCellPath];
359 if ([nextCell isKindOfClass:[AutofillEditCell class]]) { 407 if ([nextCell isKindOfClass:[AutofillEditCell class]]) {
360 return base::mac::ObjCCastStrict<AutofillEditCell>( 408 return base::mac::ObjCCastStrict<AutofillEditCell>(
361 [collectionView cellForItemAtIndexPath:nextCellPath]); 409 [collectionView cellForItemAtIndexPath:nextCellPath]);
362 } 410 }
411 nextCellPath =
412 [self indexPathWithSectionOffset:offset fromPath:nextCellPath];
363 } 413 }
364 return nil; 414 return nil;
365 } 415 }
366 416
367 - (void)updateAccessoryViewButtonsStates { 417 - (void)updateAccessoryViewButtonsStates {
368 AutofillEditCell* previousCell = [self nextTextFieldWithOffset:-1]; 418 AutofillEditCell* previousCell = [self nextTextFieldWithOffset:-1];
369 [[_accessoryView previousButton] setEnabled:previousCell != nil]; 419 [[_accessoryView previousButton] setEnabled:previousCell != nil];
370 420
371 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1]; 421 AutofillEditCell* nextCell = [self nextTextFieldWithOffset:1];
372 [[_accessoryView nextButton] setEnabled:nextCell != nil]; 422 [[_accessoryView nextButton] setEnabled:nextCell != nil];
373 } 423 }
374 424
425 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage
426 inSectionWithIdentifier:(NSInteger)sectionIdentifier {
427 CollectionViewModel* model = self.collectionViewModel;
428 if ([model hasItemForItemType:ItemTypeErrorMessage
429 sectionIdentifier:sectionIdentifier]) {
430 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage
431 sectionIdentifier:sectionIdentifier];
432 if (!errorMessage.length) {
433 // Remove the item at the index path.
434 [model removeItemWithType:ItemTypeErrorMessage
435 fromSectionWithIdentifier:sectionIdentifier];
436 [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]];
437 } else {
438 // Reload the item at the index path.
439 PaymentsTextItem* item = base::mac::ObjCCastStrict<PaymentsTextItem>(
440 [model itemAtIndexPath:indexPath]);
441 item.text = errorMessage;
442 [self.collectionView reloadItemsAtIndexPaths:@[ indexPath ]];
443 }
444 } else if (errorMessage.length) {
445 // Insert an item at the index path.
446 PaymentsTextItem* errorMessageItem =
447 [[PaymentsTextItem alloc] initWithType:ItemTypeErrorMessage];
448 errorMessageItem.text = errorMessage;
449 errorMessageItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING);
450 errorMessageItem.accessibilityIdentifier = kWarningMessageAccessibilityID;
451 [model addItem:errorMessageItem toSectionWithIdentifier:sectionIdentifier];
452 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage
453 sectionIdentifier:sectionIdentifier];
454 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]];
455 }
456 }
457
375 #pragma mark - Keyboard handling 458 #pragma mark - Keyboard handling
376 459
377 - (void)keyboardDidShow { 460 - (void)keyboardDidShow {
378 [self.collectionView 461 [self.collectionView
379 scrollToItemAtIndexPath:[self.collectionView 462 scrollToItemAtIndexPath:[self.collectionView
380 indexPathForCell:_currentEditingCell] 463 indexPathForCell:_currentEditingCell]
381 atScrollPosition:UICollectionViewScrollPositionCenteredVertically 464 atScrollPosition:UICollectionViewScrollPositionCenteredVertically
382 animated:YES]; 465 animated:YES];
383 } 466 }
384 467
385 @end 468 @end
386 469
387 @implementation PaymentRequestEditViewController (Internal) 470 @implementation PaymentRequestEditViewController (Internal)
388 471
389 - (BOOL)validateForm { 472 - (BOOL)validateForm {
390 for (EditorField* field in _fields) { 473 for (EditorField* field in _fields) {
391 AutofillEditItem* item = field.item; 474 switch (field.fieldType) {
475 case EditorFieldTypeTextField: {
476 AutofillEditItem* item =
477 base::mac::ObjCCastStrict<AutofillEditItem>(field.item);
478 // Update the EditorField with the value of the text field.
479 field.value = item.textFieldValue;
480 break;
481 }
482 case EditorFieldTypeSelector: {
483 // No need to update the EditorField. It should already be up-to-date.
484 break;
485 }
486 default:
487 NOTREACHED();
488 }
392 489
393 NSString* errorMessage = [_validatorDelegate 490 NSString* errorMessage =
394 paymentRequestEditViewController:self 491 [_validatorDelegate paymentRequestEditViewController:self
395 validateValue:item.textFieldValue 492 validateField:field];
396 autofillUIType:field.autofillUIType
397 required:field.isRequired];
398 [self addOrRemoveErrorMessage:errorMessage 493 [self addOrRemoveErrorMessage:errorMessage
399 inSectionWithIdentifier:field.sectionIdentifier]; 494 inSectionWithIdentifier:field.sectionIdentifier];
400 if (errorMessage.length) 495 if (errorMessage.length)
401 return NO; 496 return NO;
402
403 field.value = item.textFieldValue;
404 } 497 }
405 return YES; 498 return YES;
406 } 499 }
407 500
408 - (void)loadHeaderItems {
409 }
410
411 - (void)loadFooterItems { 501 - (void)loadFooterItems {
412 CollectionViewModel* model = self.collectionViewModel; 502 CollectionViewModel* model = self.collectionViewModel;
413 503
414 [model addSectionWithIdentifier:SectionIdentifierFooter]; 504 [model addSectionWithIdentifier:SectionIdentifierFooter];
415 CollectionViewFooterItem* footerItem = 505 CollectionViewFooterItem* footerItem =
416 [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter]; 506 [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter];
417 footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE); 507 footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE);
418 [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter]; 508 [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter];
419 } 509 }
420 510
421 - (NSIndexPath*)indexPathForCurrentTextField { 511 - (NSIndexPath*)indexPathForCurrentTextField {
422 DCHECK(_currentEditingCell); 512 DCHECK(_currentEditingCell);
423 NSIndexPath* indexPath = 513 NSIndexPath* indexPath =
424 [[self collectionView] indexPathForCell:_currentEditingCell]; 514 [[self collectionView] indexPathForCell:_currentEditingCell];
425 DCHECK(indexPath); 515 DCHECK(indexPath);
426 return indexPath; 516 return indexPath;
427 } 517 }
428 518
429 - (void)addOrRemoveErrorMessage:(NSString*)errorMessage
430 inSectionWithIdentifier:(NSInteger)sectionIdentifier {
431 CollectionViewModel* model = self.collectionViewModel;
432 if ([model hasItemForItemType:ItemTypeErrorMessage
433 sectionIdentifier:sectionIdentifier]) {
434 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage
435 sectionIdentifier:sectionIdentifier];
436 if (!errorMessage.length) {
437 // Remove the item at the index path.
438 [model removeItemWithType:ItemTypeErrorMessage
439 fromSectionWithIdentifier:sectionIdentifier];
440 [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]];
441 } else {
442 // Reload the item at the index path.
443 PaymentsTextItem* item = base::mac::ObjCCastStrict<PaymentsTextItem>(
444 [model itemAtIndexPath:indexPath]);
445 item.text = errorMessage;
446 [self.collectionView reloadItemsAtIndexPaths:@[ indexPath ]];
447 }
448 } else if (errorMessage.length) {
449 // Insert an item at the index path.
450 PaymentsTextItem* errorMessageItem =
451 [[PaymentsTextItem alloc] initWithType:ItemTypeErrorMessage];
452 errorMessageItem.text = errorMessage;
453 errorMessageItem.image = NativeImage(IDR_IOS_PAYMENTS_WARNING);
454 errorMessageItem.accessibilityIdentifier = kWarningMessageAccessibilityID;
455 [model addItem:errorMessageItem toSectionWithIdentifier:sectionIdentifier];
456 NSIndexPath* indexPath = [model indexPathForItemType:ItemTypeErrorMessage
457 sectionIdentifier:sectionIdentifier];
458 [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]];
459 }
460 }
461
462 @end 519 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698