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 |