Displays picker view for exp month and year fields in PR card editor - FIXED
This CL creates the exact same change as CL 522946 with a small fix. The
change 522946 was reverted by CL 527894 because it broke the test:
PaymentRequestCreditCardEditCoordinatorTest.DidFinishEditing. The reason
The former CL broke this test was because that test created a blank
credit card with no month or year information. That caused the credit
card to have a month value of "00." In the picker view there was no row
for "00," the only possible values ranged from "01" to "12." The
setOptions method of the payment_request_edit_view_controller attempted
to set the default row to the month value. However since "00" was not
a valid option an exception was raised. To get around this issue I have
added a check in this new CL that ensures that default value to select
in the picker view must always be between "01" and "12". This is the only
difference between this CL and CL 522946.
Bug: 602666
Change-Id: Id2e2e9dabf028eaa96c5f3676724c0a80cef57cf
Reviewed-on: https://chromium-review.googlesource.com/528054
Commit-Queue: Randall Raymond <rayraymond@google.com>
Reviewed-by: mahmadi <mahmadi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#478075}
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
index 814e302..3630dd38 100644
--- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
+++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
@@ -49,6 +49,14 @@
@property(nonatomic, strong)
NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap;
+// The reference to the autofill::CREDIT_CARD_EXP_MONTH field, if any (i.e if
+// we are dealing with a server card this will not exist).
+@property(nonatomic, strong) EditorField* creditCardExpMonthField;
+
+// The reference to the autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR field, if any
+// (i.e. if we are dealing with a server card this will not exist).
+@property(nonatomic, strong) EditorField* creditCardExpYearField;
+
@end
@implementation CreditCardEditViewControllerMediator
@@ -59,6 +67,8 @@
@synthesize paymentRequest = _paymentRequest;
@synthesize creditCard = _creditCard;
@synthesize fieldsMap = _fieldsMap;
+@synthesize creditCardExpMonthField = _creditCardExpMonthField;
+@synthesize creditCardExpYearField = _creditCardExpYearField;
- (instancetype)initWithPaymentRequest:(PaymentRequest*)paymentRequest
creditCard:(autofill::CreditCard*)creditCard {
@@ -83,7 +93,14 @@
- (void)setConsumer:(id<PaymentRequestEditConsumer>)consumer {
_consumer = consumer;
+
[self.consumer setEditorFields:[self createEditorFields]];
+ if (self.creditCardExpMonthField) {
+ [self loadMonths];
+ }
+ if (self.creditCardExpYearField) {
+ [self loadYears];
+ }
}
- (void)setBillingProfile:(autofill::AutofillProfile*)billingProfile {
@@ -155,6 +172,55 @@
#pragma mark - Helper methods
+// Queries the month numbers.
+- (void)loadMonths {
+ NSMutableArray<NSString*>* months = [[NSMutableArray alloc] init];
+
+ for (int month = 1; month <= 12; month++) {
+ NSString* monthString = [NSString stringWithFormat:@"%02d", month];
+ [months addObject:monthString];
+ }
+
+ // Notify the view controller asynchronously to allow for the view to update.
+ __weak CreditCardEditViewControllerMediator* weakSelf = self;
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [weakSelf.consumer setOptions:months
+ forEditorField:weakSelf.creditCardExpMonthField];
+ });
+}
+
+// Queries the year numbers.
+- (void)loadYears {
+ NSMutableArray<NSString*>* years = [[NSMutableArray alloc] init];
+
+ NSDateComponents* dateComponents =
+ [[NSCalendar currentCalendar] components:NSCalendarUnitYear
+ fromDate:[NSDate date]];
+
+ int currentYear = [dateComponents year];
+ bool foundCardExpirationYear = false;
+ for (int year = currentYear; year < currentYear + 10; year++) {
+ NSString* yearString = [NSString stringWithFormat:@"%04d", year];
+ if ([yearString isEqualToString:_creditCardExpYearField.value])
+ foundCardExpirationYear = true;
+ [years addObject:yearString];
+ }
+
+ // Ensure that the expiration year on a user's saved card is
+ // always available as one of the options to select from. This is
+ // useful in the case that the user's card is expired.
+ if (!foundCardExpirationYear) {
+ [years insertObject:_creditCardExpYearField.value atIndex:0];
+ }
+
+ // Notify the view controller asynchronously to allow for the view to update.
+ __weak CreditCardEditViewControllerMediator* weakSelf = self;
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [weakSelf.consumer setOptions:years
+ forEditorField:weakSelf.creditCardExpYearField];
+ });
+}
+
- (NSArray<EditorField*>*)createEditorFields {
NSMutableArray<EditorField*>* fields = [[NSMutableArray alloc] init];
@@ -220,11 +286,18 @@
}
[fields addObject:creditCardNameField];
+ NSDateComponents* dateComponents = [[NSCalendar currentCalendar]
+ components:NSCalendarUnitMonth | NSCalendarUnitYear
+ fromDate:[NSDate date]];
+
+ int currentMonth = [dateComponents month];
+
// Expiration month field.
NSString* creditCardExpMonth =
- _creditCard
+ _creditCard && (_creditCard->expiration_month() >= 1 &&
+ _creditCard->expiration_month() <= 12)
? [NSString stringWithFormat:@"%02d", _creditCard->expiration_month()]
- : nil;
+ : [NSString stringWithFormat:@"%02d", currentMonth];
fieldKey = [NSNumber numberWithInt:AutofillUITypeCreditCardExpMonth];
EditorField* expirationMonthField = self.fieldsMap[fieldKey];
if (!expirationMonthField) {
@@ -236,13 +309,15 @@
required:YES];
[self.fieldsMap setObject:expirationMonthField forKey:fieldKey];
}
+ self.creditCardExpMonthField = expirationMonthField;
[fields addObject:expirationMonthField];
// Expiration year field.
+ int currentYear = [dateComponents year];
NSString* creditCardExpYear =
_creditCard
? [NSString stringWithFormat:@"%04d", _creditCard->expiration_year()]
- : nil;
+ : [NSString stringWithFormat:@"%04d", currentYear];
fieldKey = [NSNumber numberWithInt:AutofillUITypeCreditCardExpYear];
EditorField* expirationYearField = self.fieldsMap[fieldKey];
if (!expirationYearField) {
@@ -254,6 +329,7 @@
required:YES];
[self.fieldsMap setObject:expirationYearField forKey:fieldKey];
}
+ self.creditCardExpYearField = expirationYearField;
[fields addObject:expirationYearField];
// The billing address field appears after the expiration year field.