| 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 0e58eb97e8987e4f9cad9e9164398d2166228714..9539bc97e6458619955669b8c18347ebaf21d677 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
|
| @@ -13,10 +13,11 @@
|
| #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
|
| #import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item.h"
|
| #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item+collection_view_controller.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h"
|
| #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
|
| #import "ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.h"
|
| #import "ios/chrome/browser/ui/payments/cells/payments_text_item.h"
|
| -#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller+internal.h"
|
| +#import "ios/chrome/browser/ui/payments/payment_request_edit_view_controller_actions.h"
|
| #import "ios/chrome/browser/ui/payments/payment_request_editor_field.h"
|
| #import "ios/chrome/browser/ui/uikit_ui_util.h"
|
| #include "ios/chrome/grit/ios_theme_resources.h"
|
| @@ -52,6 +53,20 @@ AutofillEditCell* AutofillEditCellForTextField(UITextField* textField) {
|
| return nil;
|
| }
|
|
|
| +CollectionViewSwitchCell* CollectionViewSwitchCellForSwitchField(
|
| + UISwitch* switchField) {
|
| + for (UIView* view = switchField; view; view = [view superview]) {
|
| + CollectionViewSwitchCell* cell =
|
| + base::mac::ObjCCast<CollectionViewSwitchCell>(view);
|
| + if (cell)
|
| + return cell;
|
| + }
|
| +
|
| + // There should be a cell associated with this switch field.
|
| + NOTREACHED();
|
| + return nil;
|
| +}
|
| +
|
| typedef NS_ENUM(NSInteger, SectionIdentifier) {
|
| SectionIdentifierHeader = kSectionIdentifierEnumZero,
|
| SectionIdentifierFooter,
|
| @@ -63,22 +78,25 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| ItemTypeFooter,
|
| ItemTypeTextField, // This is a repeated item type.
|
| ItemTypeSelectorField, // This is a repeated item type.
|
| + ItemTypeSwitchField, // This is a repeated item type.
|
| ItemTypeErrorMessage, // This is a repeated item type.
|
| };
|
|
|
| } // namespace
|
|
|
| -@interface PaymentRequestEditViewController ()<AutofillEditAccessoryDelegate,
|
| - UITextFieldDelegate,
|
| - UIPickerViewDataSource,
|
| - UIPickerViewDelegate> {
|
| +@interface PaymentRequestEditViewController ()<
|
| + AutofillEditAccessoryDelegate,
|
| + PaymentRequestEditViewControllerActions,
|
| + UIPickerViewDataSource,
|
| + UIPickerViewDelegate,
|
| + UITextFieldDelegate> {
|
| // The currently focused cell. May be nil.
|
| __weak AutofillEditCell* _currentEditingCell;
|
|
|
| AutofillEditAccessoryView* _accessoryView;
|
| }
|
|
|
| -// The map of autofill types to the fields definitions for the editor.
|
| +// The map of section identifiers to the fields definitions for the editor.
|
| @property(nonatomic, strong)
|
| NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap;
|
|
|
| @@ -112,6 +130,16 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| - (void)addOrRemoveErrorMessage:(NSString*)errorMessage
|
| inSectionWithIdentifier:(NSInteger)sectionIdentifier;
|
|
|
| +// Validates each field. If there is a validation error, displays an error
|
| +// message item in the same section as the field and returns NO. Otherwise
|
| +// removes the error message item in that section if one exists and sets the
|
| +// value on the field. Returns YES if all the fields are validated successfully.
|
| +- (BOOL)validateForm;
|
| +
|
| +// Returns the index path for the cell associated with the currently focused
|
| +// text field.
|
| +- (NSIndexPath*)indexPathForCurrentTextField;
|
| +
|
| @end
|
|
|
| @implementation PaymentRequestEditViewController
|
| @@ -200,6 +228,9 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| [model addItem:headerItem toSectionWithIdentifier:SectionIdentifierHeader];
|
| }
|
|
|
| + self.fieldsMap =
|
| + [[NSMutableDictionary alloc] initWithCapacity:self.fields.count];
|
| +
|
| // Iterate over the fields and add the respective sections and items.
|
| [self.fields enumerateObjectsUsingBlock:^(EditorField* field,
|
| NSUInteger index, BOOL* stop) {
|
| @@ -214,6 +245,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| item.textFieldValue = field.value;
|
| item.required = field.isRequired;
|
| item.autofillUIType = field.autofillUIType;
|
| + item.identifyingIcon = [_dataSource iconIdentifyingEditorField:field];
|
| [model addItem:item toSectionWithIdentifier:sectionIdentifier];
|
| field.item = item;
|
|
|
| @@ -231,14 +263,29 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| field.item = item;
|
| break;
|
| }
|
| + case EditorFieldTypeSwitch: {
|
| + CollectionViewSwitchItem* item =
|
| + [[CollectionViewSwitchItem alloc] initWithType:ItemTypeSwitchField];
|
| + item.text = field.label;
|
| + item.on = [field.value boolValue];
|
| + [model addItem:item toSectionWithIdentifier:sectionIdentifier];
|
| + field.item = item;
|
| + break;
|
| + }
|
| default:
|
| NOTREACHED();
|
| }
|
|
|
| field.sectionIdentifier = sectionIdentifier;
|
| + NSNumber* key = [NSNumber numberWithInt:sectionIdentifier];
|
| + [self.fieldsMap setObject:field forKey:key];
|
| }];
|
|
|
| - [self loadFooterItems];
|
| + [model addSectionWithIdentifier:SectionIdentifierFooter];
|
| + CollectionViewFooterItem* footerItem =
|
| + [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter];
|
| + footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE);
|
| + [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter];
|
| }
|
|
|
| - (void)viewDidLoad {
|
| @@ -257,13 +304,6 @@ 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
|
| @@ -304,22 +344,18 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| - (void)textFieldDidEndEditing:(UITextField*)textField {
|
| DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField));
|
|
|
| - CollectionViewModel* model = self.collectionViewModel;
|
| -
|
| NSIndexPath* indexPath = [self indexPathForCurrentTextField];
|
| - AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| - [model itemAtIndexPath:indexPath]);
|
| + NSInteger sectionIdentifier = [self.collectionViewModel
|
| + sectionIdentifierForSection:[indexPath section]];
|
|
|
| - // Find and validate the respective editor field.
|
| - NSNumber* key = [NSNumber numberWithInt:item.autofillUIType];
|
| + // Find the respective editor field, update its value, and validate it.
|
| + NSNumber* key = [NSNumber numberWithInt:sectionIdentifier];
|
| EditorField* field = self.fieldsMap[key];
|
| DCHECK(field);
|
| field.value = textField.text;
|
| NSString* errorMessage =
|
| [_validatorDelegate paymentRequestEditViewController:self
|
| validateField:field];
|
| - NSInteger sectionIdentifier =
|
| - [model sectionIdentifierForSection:[indexPath section]];
|
| [self addOrRemoveErrorMessage:errorMessage
|
| inSectionWithIdentifier:sectionIdentifier];
|
|
|
| @@ -338,6 +374,44 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| return NO;
|
| }
|
|
|
| +// This method is called as the text is being typed in, pasted, or deleted. Asks
|
| +// the delegate if the text should be changed. Should always return YES. During
|
| +// typing/pasting text, |newText| contains one or more new characters. When user
|
| +// deletes text, |newText| is empty. |range| is the range of characters to be
|
| +// replaced.
|
| +- (BOOL)textField:(UITextField*)textField
|
| + shouldChangeCharactersInRange:(NSRange)range
|
| + replacementString:(NSString*)newText {
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + DCHECK(_currentEditingCell == AutofillEditCellForTextField(textField));
|
| +
|
| + NSIndexPath* indexPath = [self indexPathForCurrentTextField];
|
| + NSInteger sectionIdentifier =
|
| + [model sectionIdentifierForSection:[indexPath section]];
|
| + AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| + [model itemAtIndexPath:indexPath]);
|
| +
|
| + // Find the respective editor field and update its value.
|
| + NSNumber* key = [NSNumber numberWithInt:sectionIdentifier];
|
| + EditorField* field = self.fieldsMap[key];
|
| + DCHECK(field);
|
| + // Obtain the text being typed.
|
| + NSString* updatedText =
|
| + [textField.text stringByReplacingCharactersInRange:range
|
| + withString:newText];
|
| + field.value = updatedText;
|
| +
|
| + // Get the icon that identifies the field value and reload the cell if the
|
| + // icon changes.
|
| + UIImage* oldIcon = item.identifyingIcon;
|
| + item.identifyingIcon = [_dataSource iconIdentifyingEditorField:field];
|
| + if (item.identifyingIcon != oldIcon)
|
| + [self reconfigureCellsForItems:@[ item ]];
|
| +
|
| + return YES;
|
| +}
|
| +
|
| #pragma mark - AutofillEditAccessoryDelegate
|
|
|
| - (void)nextPressed {
|
| @@ -414,6 +488,14 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| [[MDCPalette cr_bluePalette] tint600];
|
| break;
|
| }
|
| + case ItemTypeSwitchField: {
|
| + CollectionViewSwitchCell* switchCell =
|
| + base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell);
|
| + [switchCell.switchView addTarget:self
|
| + action:@selector(switchToggled:)
|
| + forControlEvents:UIControlEventValueChanged];
|
| + break;
|
| + }
|
| case ItemTypeErrorMessage: {
|
| PaymentsTextCell* errorMessageCell =
|
| base::mac::ObjCCastStrict<PaymentsTextCell>(cell);
|
| @@ -471,6 +553,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| case ItemTypeHeader:
|
| case ItemTypeFooter:
|
| case ItemTypeTextField:
|
| + case ItemTypeSwitchField:
|
| case ItemTypeErrorMessage:
|
| return [MDCCollectionViewCell
|
| cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
|
| @@ -490,6 +573,8 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| case ItemTypeHeader:
|
| case ItemTypeFooter:
|
| case ItemTypeErrorMessage:
|
| + case ItemTypeTextField:
|
| + case ItemTypeSwitchField:
|
| return YES;
|
| default:
|
| return NO;
|
| @@ -582,20 +667,6 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| }
|
| }
|
|
|
| -#pragma mark - Keyboard handling
|
| -
|
| -- (void)keyboardDidShow {
|
| - [self.collectionView
|
| - scrollToItemAtIndexPath:[self.collectionView
|
| - indexPathForCell:_currentEditingCell]
|
| - atScrollPosition:UICollectionViewScrollPositionCenteredVertically
|
| - animated:YES];
|
| -}
|
| -
|
| -@end
|
| -
|
| -@implementation PaymentRequestEditViewController (Internal)
|
| -
|
| - (BOOL)validateForm {
|
| for (EditorField* field in self.fields) {
|
| NSString* errorMessage =
|
| @@ -609,16 +680,6 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| return YES;
|
| }
|
|
|
| -- (void)loadFooterItems {
|
| - CollectionViewModel* model = self.collectionViewModel;
|
| -
|
| - [model addSectionWithIdentifier:SectionIdentifierFooter];
|
| - CollectionViewFooterItem* footerItem =
|
| - [[CollectionViewFooterItem alloc] initWithType:ItemTypeFooter];
|
| - footerItem.text = l10n_util::GetNSString(IDS_PAYMENTS_REQUIRED_FIELD_MESSAGE);
|
| - [model addItem:footerItem toSectionWithIdentifier:SectionIdentifierFooter];
|
| -}
|
| -
|
| - (NSIndexPath*)indexPathForCurrentTextField {
|
| DCHECK(_currentEditingCell);
|
| NSIndexPath* indexPath =
|
| @@ -627,13 +688,48 @@ typedef NS_ENUM(NSInteger, ItemType) {
|
| return indexPath;
|
| }
|
|
|
| +#pragma mark - Keyboard handling
|
| +
|
| +- (void)keyboardDidShow {
|
| + [self.collectionView
|
| + scrollToItemAtIndexPath:[self.collectionView
|
| + indexPathForCell:_currentEditingCell]
|
| + atScrollPosition:UICollectionViewScrollPositionCenteredVertically
|
| + animated:YES];
|
| +}
|
| +
|
| +#pragma mark Switch Actions
|
| +
|
| +- (void)switchToggled:(UISwitch*)sender {
|
| + CollectionViewSwitchCell* switchCell =
|
| + CollectionViewSwitchCellForSwitchField(sender);
|
| + NSIndexPath* indexPath = [[self collectionView] indexPathForCell:switchCell];
|
| + DCHECK(indexPath);
|
| +
|
| + NSInteger sectionIdentifier = [self.collectionViewModel
|
| + sectionIdentifierForSection:[indexPath section]];
|
| +
|
| + // Update editor field's value.
|
| + NSNumber* key = [NSNumber numberWithInt:sectionIdentifier];
|
| + EditorField* field = self.fieldsMap[key];
|
| + DCHECK(field);
|
| + field.value = [sender isOn] ? @"YES" : @"NO";
|
| +}
|
| +
|
| #pragma mark - PaymentRequestEditViewControllerActions methods
|
|
|
| - (void)onCancel {
|
| + [self.delegate paymentRequestEditViewControllerDidCancel:self];
|
| }
|
|
|
| - (void)onDone {
|
| [_currentEditingCell.textField resignFirstResponder];
|
| +
|
| + if (![self validateForm])
|
| + return;
|
| +
|
| + [self.delegate paymentRequestEditViewController:self
|
| + didFinishEditingFields:self.fields];
|
| }
|
|
|
| @end
|
|
|