| Index: ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
|
| diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
|
| index 9e5c00a995e25308d5e5856d0ef6dc219b3511e3..9f58aa8c725f0168bd797b04ba2e35030c492e61 100644
|
| --- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
|
| +++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
|
| @@ -68,18 +68,31 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
|
|
| } // namespace
|
|
|
| -@interface PaymentRequestEditViewController ()<
|
| - AutofillEditAccessoryDelegate,
|
| - UITextFieldDelegate> {
|
| +@interface PaymentRequestEditViewController ()<AutofillEditAccessoryDelegate,
|
| + UITextFieldDelegate,
|
| + UIPickerViewDataSource,
|
| + UIPickerViewDelegate> {
|
| // The currently focused cell. May be nil.
|
| __weak AutofillEditCell* _currentEditingCell;
|
|
|
| AutofillEditAccessoryView* _accessoryView;
|
| }
|
|
|
| +// The map of autofill types to the fields definitions for the editor.
|
| +@property(nonatomic, strong)
|
| + NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap;
|
| +
|
| // The list of field definitions for the editor.
|
| @property(nonatomic, strong) NSArray<EditorField*>* fields;
|
|
|
| +// The map of autofill types to lists of UIPickerView options.
|
| +@property(nonatomic, strong)
|
| + NSMutableDictionary<NSNumber*, NSArray<NSString*>*>* options;
|
| +
|
| +// The map of autofill types to UIPickerView views.
|
| +@property(nonatomic, strong)
|
| + NSMutableDictionary<NSNumber*, UIPickerView*>* pickerViews;
|
| +
|
| // Returns the indexPath for the same row as that of |indexPath| in a section
|
| // with the given offset relative to that of |indexPath|. May return nil.
|
| - (NSIndexPath*)indexPathWithSectionOffset:(NSInteger)offset
|
| @@ -106,12 +119,17 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| @synthesize dataSource = _dataSource;
|
| @synthesize delegate = _delegate;
|
| @synthesize validatorDelegate = _validatorDelegate;
|
| +@synthesize fieldsMap = _fieldsMap;
|
| @synthesize fields = _fields;
|
| +@synthesize options = _options;
|
| +@synthesize pickerViews = _pickerViews;
|
|
|
| - (instancetype)initWithStyle:(CollectionViewControllerStyle)style {
|
| self = [super initWithStyle:style];
|
| if (self) {
|
| _accessoryView = [[AutofillEditAccessoryView alloc] initWithDelegate:self];
|
| + _options = [[NSMutableDictionary alloc] init];
|
| + _pickerViews = [[NSMutableDictionary alloc] init];
|
| }
|
| return self;
|
| }
|
| @@ -139,6 +157,8 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| [super loadModel];
|
| CollectionViewModel* model = self.collectionViewModel;
|
|
|
| + [self.pickerViews removeAllObjects];
|
| +
|
| CollectionViewItem* headerItem = [_dataSource headerItem];
|
| if (headerItem) {
|
| [headerItem setType:ItemTypeHeader];
|
| @@ -147,21 +167,22 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| }
|
|
|
| // Iterate over the fields and add the respective sections and items.
|
| - int sectionIdentifier = static_cast<int>(SectionIdentifierFirstField);
|
| - for (EditorField* field in self.fields) {
|
| + [self.fields enumerateObjectsUsingBlock:^(EditorField* field,
|
| + NSUInteger index, BOOL* stop) {
|
| + NSInteger sectionIdentifier = SectionIdentifierFirstField + index;
|
| [model addSectionWithIdentifier:sectionIdentifier];
|
| switch (field.fieldType) {
|
| case EditorFieldTypeTextField: {
|
| AutofillEditItem* item =
|
| [[AutofillEditItem alloc] initWithType:ItemTypeTextField];
|
| item.textFieldName = field.label;
|
| - item.textFieldEnabled = YES;
|
| + item.textFieldEnabled = field.enabled;
|
| item.textFieldValue = field.value;
|
| item.required = field.isRequired;
|
| item.autofillUIType = field.autofillUIType;
|
| - [model addItem:item
|
| - toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)];
|
| + [model addItem:item toSectionWithIdentifier:sectionIdentifier];
|
| field.item = item;
|
| +
|
| break;
|
| }
|
| case EditorFieldTypeSelector: {
|
| @@ -172,8 +193,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| item.required = field.isRequired;
|
| item.autofillUIType = field.autofillUIType;
|
| item.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
|
| - [model addItem:item
|
| - toSectionWithIdentifier:static_cast<NSInteger>(sectionIdentifier)];
|
| + [model addItem:item toSectionWithIdentifier:sectionIdentifier];
|
| field.item = item;
|
| break;
|
| }
|
| @@ -181,9 +201,8 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| NOTREACHED();
|
| }
|
|
|
| - field.sectionIdentifier = static_cast<NSInteger>(sectionIdentifier);
|
| - ++sectionIdentifier;
|
| - }
|
| + field.sectionIdentifier = sectionIdentifier;
|
| + }];
|
|
|
| [self loadFooterItems];
|
| }
|
| @@ -204,6 +223,42 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
|
|
| - (void)setEditorFields:(NSArray<EditorField*>*)fields {
|
| self.fields = fields;
|
| + self.fieldsMap = [[NSMutableDictionary alloc] initWithCapacity:fields.count];
|
| + // Iterate over the fields and populate the map.
|
| + [self.fields enumerateObjectsUsingBlock:^(EditorField* field,
|
| + NSUInteger index, BOOL* stop) {
|
| + NSNumber* key = [NSNumber numberWithInt:field.autofillUIType];
|
| + [self.fieldsMap setObject:field forKey:key];
|
| + }];
|
| +}
|
| +
|
| +- (void)setOptions:(NSArray<NSString*>*)options
|
| + forEditorField:(EditorField*)field {
|
| + DCHECK(field.fieldType == EditorFieldTypeTextField);
|
| + AutofillEditItem* item =
|
| + base::mac::ObjCCastStrict<AutofillEditItem>(field.item);
|
| +
|
| + // Enable the previously disabled text field and reset its value.
|
| + item.textFieldEnabled = YES;
|
| + item.textFieldValue = nil;
|
| +
|
| + // Cache the options if there are any and set the text field's UIPickerView.
|
| + if (options.count) {
|
| + NSNumber* key = [NSNumber numberWithInt:field.autofillUIType];
|
| + [self.options setObject:options forKey:key];
|
| +
|
| + UIPickerView* pickerView = [[UIPickerView alloc] initWithFrame:CGRectZero];
|
| + pickerView.delegate = self;
|
| + pickerView.dataSource = self;
|
| + [self.pickerViews setObject:pickerView forKey:key];
|
| + item.inputView = pickerView;
|
| + }
|
| +
|
| + // Reload the item.
|
| + NSIndexPath* indexPath =
|
| + [self.collectionViewModel indexPathForItemType:ItemTypeTextField
|
| + sectionIdentifier:field.sectionIdentifier];
|
| + [self.collectionView reloadItemsAtIndexPaths:@[ indexPath ]];
|
| }
|
|
|
| #pragma mark - UITextFieldDelegate
|
| @@ -217,23 +272,20 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| - (void)textFieldDidEndEditing:(UITextField*)textField {
|
| DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField));
|
|
|
| - // Validate the text field.
|
| CollectionViewModel* model = self.collectionViewModel;
|
|
|
| NSIndexPath* indexPath = [self indexPathForCurrentTextField];
|
| AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| [model itemAtIndexPath:indexPath]);
|
|
|
| - // Create a dummy EditorField for validation only.
|
| - EditorField* fieldForValidation =
|
| - [[EditorField alloc] initWithAutofillUIType:item.autofillUIType
|
| - fieldType:EditorFieldTypeTextField
|
| - label:nil
|
| - value:textField.text
|
| - required:item.required];
|
| + // Find and validate the respective editor field.
|
| + NSNumber* key = [NSNumber numberWithInt:item.autofillUIType];
|
| + EditorField* field = self.fieldsMap[key];
|
| + DCHECK(field);
|
| + field.value = textField.text;
|
| NSString* errorMessage =
|
| [_validatorDelegate paymentRequestEditViewController:self
|
| - validateField:fieldForValidation];
|
| + validateField:field];
|
| NSInteger sectionIdentifier =
|
| [model sectionIdentifierForSection:[indexPath section]];
|
| [self addOrRemoveErrorMessage:errorMessage
|
| @@ -272,6 +324,42 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| [[_currentEditingCell textField] resignFirstResponder];
|
| }
|
|
|
| +#pragma mark - UIPickerViewDataSource methods
|
| +
|
| +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)thePickerView {
|
| + return 1;
|
| +}
|
| +
|
| +- (NSInteger)pickerView:(UIPickerView*)thePickerView
|
| + numberOfRowsInComponent:(NSInteger)component {
|
| + NSArray<NSNumber*>* indices =
|
| + [self.pickerViews allKeysForObject:thePickerView];
|
| + DCHECK(indices.count == 1);
|
| + NSArray<NSString*>* options = self.options[indices[0]];
|
| + return options.count;
|
| +}
|
| +
|
| +#pragma mark - UIPickerViewDelegate methods
|
| +
|
| +- (NSString*)pickerView:(UIPickerView*)thePickerView
|
| + titleForRow:(NSInteger)row
|
| + forComponent:(NSInteger)component {
|
| + NSArray<NSNumber*>* indices =
|
| + [self.pickerViews allKeysForObject:thePickerView];
|
| + DCHECK(indices.count == 1);
|
| + NSArray<NSString*>* options = self.options[indices[0]];
|
| + DCHECK(row < static_cast<NSInteger>(options.count));
|
| + return options[row];
|
| +}
|
| +
|
| +- (void)pickerView:(UIPickerView*)thePickerView
|
| + didSelectRow:(NSInteger)row
|
| + inComponent:(NSInteger)component {
|
| + DCHECK(_currentEditingCell);
|
| + _currentEditingCell.textField.text =
|
| + [self pickerView:thePickerView titleForRow:row forComponent:component];
|
| +}
|
| +
|
| #pragma mark - UICollectionViewDataSource
|
|
|
| - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
|
| @@ -332,9 +420,13 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| hasSectionForSectionIdentifier:SectionIdentifierHeader])
|
| index--;
|
| DCHECK(index >= 0 && index < static_cast<NSInteger>(self.fields.count));
|
| - [_delegate
|
| - paymentRequestEditViewController:self
|
| - didSelectField:[self.fields objectAtIndex:index]];
|
| + EditorField* field = [self.fields objectAtIndex:index];
|
| +
|
| + // If a selector field is selected, blur the focused text field.
|
| + if (field.fieldType == EditorFieldTypeSelector)
|
| + [[_currentEditingCell textField] resignFirstResponder];
|
| +
|
| + [_delegate paymentRequestEditViewController:self didSelectField:field];
|
| }
|
|
|
| #pragma mark MDCCollectionViewStylingDelegate
|
|
|