| Index: ios/chrome/browser/payments/credit_card_edit_view_controller.mm
|
| diff --git a/ios/chrome/browser/payments/credit_card_edit_view_controller.mm b/ios/chrome/browser/payments/credit_card_edit_view_controller.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d6e97eae1adae4fdc5fcf581dfe256b238cda7c7
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/payments/credit_card_edit_view_controller.mm
|
| @@ -0,0 +1,561 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#import "ios/chrome/browser/payments/credit_card_edit_view_controller.h"
|
| +
|
| +#include "base/guid.h"
|
| +#import "base/mac/foundation_util.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "components/autofill/core/browser/autofill_data_util.h"
|
| +#include "components/autofill/core/browser/credit_card.h"
|
| +#include "components/autofill/core/browser/field_types.h"
|
| +#include "components/autofill/core/browser/personal_data_manager.h"
|
| +#include "components/autofill/core/common/autofill_constants.h"
|
| +#import "components/autofill/ios/browser/credit_card_util.h"
|
| +#include "components/strings/grit/components_strings.h"
|
| +#include "ios/chrome/browser/application_context.h"
|
| +#import "ios/chrome/browser/payments/cells/payments_text_item.h"
|
| +#import "ios/chrome/browser/payments/payment_request_util.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h"
|
| +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_item.h"
|
| +#import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
|
| +#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
|
| +#import "ios/chrome/browser/ui/settings/cells/autofill_edit_item.h"
|
| +#import "ios/chrome/browser/ui/uikit_ui_util.h"
|
| +#include "ios/chrome/grit/ios_strings.h"
|
| +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +
|
| +#if !defined(__has_feature) || !__has_feature(objc_arc)
|
| +#error "This file requires ARC support."
|
| +#endif
|
| +
|
| +namespace {
|
| +
|
| +NSString* const kCreditCardEditCollectionViewId =
|
| + @"kCreditCardEditCollectionViewId";
|
| +
|
| +const CGFloat kSeparatorEdgeInset = 14;
|
| +
|
| +const CGFloat kCardTypeIconDimension = 25.0;
|
| +
|
| +typedef NS_ENUM(NSInteger, SectionIdentifier) {
|
| + SectionIdentifierCardNumber = kSectionIdentifierEnumZero,
|
| + SectionIdentifierCardholderName,
|
| + SectionIdentifierExpirationMonth,
|
| + SectionIdentifierExpirationYear,
|
| + SectionIdentifierBillingAddress,
|
| +};
|
| +
|
| +typedef NS_ENUM(NSInteger, ItemType) {
|
| + ItemTypeCardNumber = kItemTypeEnumZero,
|
| + ItemTypeCardholderName,
|
| + ItemTypeExpirationMonth,
|
| + ItemTypeExpirationYear,
|
| + ItemTypeBillingAddress,
|
| + ItemTypeErrorMessage,
|
| +};
|
| +
|
| +using ::payment_request_util::GetBillingAddressLabelFromAutofillProfile;
|
| +
|
| +} // namespace
|
| +
|
| +@interface CreditCardEditViewController () {
|
| + UIBarButtonItem* _cancelButton;
|
| + UIBarButtonItem* _doneButton;
|
| +
|
| + // The PaymentRequest object owning an instance of web::PaymentRequest as
|
| + // provided by the page invoking the Payment Request API. This is a weak
|
| + // pointer and should outlive this class.
|
| + PaymentRequest* _paymentRequest;
|
| +
|
| + // The credit card to be edited, if any. This is a weak pointer and should
|
| + // outlive this class.
|
| + autofill::CreditCard* _creditCard;
|
| +
|
| + // GUID of the credit card's billing address, if there is one.
|
| + std::string _billingAddressGUID;
|
| +}
|
| +
|
| +@end
|
| +
|
| +@implementation CreditCardEditViewController
|
| +
|
| +@synthesize delegate = _delegate;
|
| +
|
| +#pragma mark - Initialization
|
| +
|
| +- (instancetype)initWithPaymentRequest:(PaymentRequest*)paymentRequest
|
| + creditCard:(autofill::CreditCard*)creditCard {
|
| + self = [super initWithPaymentRequest:paymentRequest];
|
| + if (self) {
|
| + DCHECK(paymentRequest);
|
| + _paymentRequest = paymentRequest;
|
| + _creditCard = creditCard;
|
| +
|
| + // TODO(crbug.com/602666): Title varies depending on the missing fields.
|
| + NSString* title = creditCard
|
| + ? l10n_util::GetNSString(IDS_PAYMENTS_EDIT_CARD)
|
| + : l10n_util::GetNSString(IDS_PAYMENTS_ADD_CARD_LABEL);
|
| + [self setTitle:title];
|
| +
|
| + // Set up leading (cancel) button.
|
| + _cancelButton = [[UIBarButtonItem alloc]
|
| + initWithTitle:l10n_util::GetNSString(IDS_CANCEL)
|
| + style:UIBarButtonItemStylePlain
|
| + target:nil
|
| + action:@selector(onReturn)];
|
| + [_cancelButton setTitleTextAttributes:@{
|
| + NSForegroundColorAttributeName : [UIColor lightGrayColor]
|
| + }
|
| + forState:UIControlStateDisabled];
|
| + [_cancelButton
|
| + setAccessibilityLabel:l10n_util::GetNSString(IDS_ACCNAME_CANCEL)];
|
| + [self navigationItem].leftBarButtonItem = _cancelButton;
|
| +
|
| + // Set up trailing (done) button.
|
| + _doneButton =
|
| + [[UIBarButtonItem alloc] initWithTitle:l10n_util::GetNSString(IDS_DONE)
|
| + style:UIBarButtonItemStylePlain
|
| + target:nil
|
| + action:@selector(onConfirm)];
|
| + [_doneButton setTitleTextAttributes:@{
|
| + NSForegroundColorAttributeName : [UIColor lightGrayColor]
|
| + }
|
| + forState:UIControlStateDisabled];
|
| + [_doneButton
|
| + setAccessibilityLabel:l10n_util::GetNSString(IDS_ACCNAME_DONE)];
|
| + [self navigationItem].rightBarButtonItem = _doneButton;
|
| + }
|
| +
|
| + return self;
|
| +}
|
| +
|
| +- (void)onReturn {
|
| + [_delegate creditCardEditViewControllerDidReturn:self];
|
| +}
|
| +
|
| +- (void)onConfirm {
|
| + [self validateAndSubmitForm];
|
| +}
|
| +
|
| +- (void)validateAndSubmitForm {
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + // Creat an empty credit card. If a credit card is being edited, copy over the
|
| + // information.
|
| + autofill::CreditCard creditCard("", autofill::kSettingsOrigin);
|
| + if (_creditCard)
|
| + creditCard = *_creditCard;
|
| +
|
| + // Validate card number, card holder name, expiration month, and expiration
|
| + // year. If there are validation errors, display an error message item in the
|
| + // same section as the field and return. Otherwise remove the error message
|
| + // item in that section and set the information on the credit card.
|
| + for (const auto& field : [self editorFields]) {
|
| + NSIndexPath* indexPath = [model indexPathForItemType:field.item_type
|
| + sectionIdentifier:field.section_id];
|
| + AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| + [model itemAtIndexPath:indexPath]);
|
| +
|
| + NSString* errorMessage = [self validateValue:item.textFieldValue
|
| + autofillType:field.data_type
|
| + required:field.required];
|
| + [self addOrRemoveErrorItemWithType:ItemTypeErrorMessage
|
| + errorMessage:errorMessage
|
| + inSectionWithIdentifier:field.section_id];
|
| + if (errorMessage.length != 0) {
|
| + return;
|
| + }
|
| +
|
| + creditCard.SetRawInfo(field.data_type,
|
| + base::SysNSStringToUTF16(item.textFieldValue));
|
| + }
|
| +
|
| + // Validate and set the billing address GUID like the rest of the fields.
|
| + NSString* errorMessage =
|
| + _billingAddressGUID.empty()
|
| + ? l10n_util::GetNSString(
|
| + IDS_PAYMENTS_FIELD_REQUIRED_VALIDATION_MESSAGE)
|
| + : @"";
|
| + [self addOrRemoveErrorItemWithType:ItemTypeErrorMessage
|
| + errorMessage:errorMessage
|
| + inSectionWithIdentifier:SectionIdentifierBillingAddress];
|
| + if (errorMessage.length != 0) {
|
| + return;
|
| + }
|
| +
|
| + creditCard.set_billing_address_id(_billingAddressGUID);
|
| +
|
| + if (!_creditCard) {
|
| + // The new credit card does not yet have a valid GUID.
|
| + creditCard.set_guid(base::GenerateGUID());
|
| +
|
| + // Add the credit card to the local credit cards managed by
|
| + // autofill::PersonalDataManager.
|
| + _paymentRequest->GetPersonalDataManager()->AddCreditCard(creditCard);
|
| +
|
| + // Add the credit card to the list of credit cards in |_paymentRequest|. Do
|
| + // this manually to avoid waiting for autofill::PersonalDataManager to get
|
| + // updated. |_paymentRequest| takes ownership of the instance.
|
| + std::unique_ptr<autofill::CreditCard> new_card =
|
| + base::MakeUnique<autofill::CreditCard>(creditCard);
|
| + _creditCard = new_card.get();
|
| + _paymentRequest->AddCreditCard(std::move(new_card));
|
| + } else {
|
| + // Update the original credit card instance that is being edited.
|
| + *_creditCard = creditCard;
|
| +
|
| + if (autofill::IsCreditCardLocal(creditCard)) {
|
| + _paymentRequest->GetPersonalDataManager()->UpdateCreditCard(creditCard);
|
| + } else {
|
| + // Update server credit card's billing address.
|
| + _paymentRequest->GetPersonalDataManager()->UpdateServerCardMetadata(
|
| + creditCard);
|
| + }
|
| + }
|
| +
|
| + [_delegate creditCardEditViewController:self
|
| + didFinishEditingCreditCard:_creditCard];
|
| +}
|
| +
|
| +- (std::vector<EditorField>)editorFields {
|
| + // Serve credit cards are not editable.
|
| + if (_creditCard && !autofill::IsCreditCardLocal(*_creditCard))
|
| + return std::vector<EditorField>();
|
| +
|
| + return std::vector<EditorField>{
|
| + {autofill::CREDIT_CARD_NUMBER,
|
| + l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_CARD_NUMBER),
|
| + /* required= */ true, ItemTypeCardNumber, SectionIdentifierCardNumber},
|
| + {autofill::CREDIT_CARD_NAME_FULL,
|
| + l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_CARDHOLDER),
|
| + /* required= */ true, ItemTypeCardholderName,
|
| + SectionIdentifierCardholderName},
|
| + {autofill::CREDIT_CARD_EXP_MONTH,
|
| + l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_EXP_MONTH),
|
| + /* required= */ true, ItemTypeExpirationMonth,
|
| + SectionIdentifierExpirationMonth},
|
| + {autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR,
|
| + l10n_util::GetStringUTF16(IDS_IOS_AUTOFILL_EXP_YEAR),
|
| + /* required= */ true, ItemTypeExpirationYear,
|
| + SectionIdentifierExpirationYear}};
|
| +}
|
| +
|
| +#pragma mark - CollectionViewController methods
|
| +
|
| +- (void)loadModel {
|
| + // Card number, card holder name, expiration month, and expiration year
|
| + // sections are added in the parent class.
|
| + [super loadModel];
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + // Billing Address section.
|
| + [model addSectionWithIdentifier:SectionIdentifierBillingAddress];
|
| + CollectionViewDetailItem* billingAddressItem =
|
| + [[CollectionViewDetailItem alloc] initWithType:ItemTypeBillingAddress];
|
| + billingAddressItem.text =
|
| + [NSString stringWithFormat:@"%@*", l10n_util::GetNSString(
|
| + IDS_IOS_AUTOFILL_BILLING_ADDRESS)];
|
| + billingAddressItem.accessoryType =
|
| + MDCCollectionViewCellAccessoryDisclosureIndicator;
|
| + [model addItem:billingAddressItem
|
| + toSectionWithIdentifier:SectionIdentifierBillingAddress];
|
| +
|
| + if (_creditCard) {
|
| + for (const auto& field : [self editorFields]) {
|
| + NSIndexPath* indexPath = [model indexPathForItemType:field.item_type
|
| + sectionIdentifier:field.section_id];
|
| + AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| + [model itemAtIndexPath:indexPath]);
|
| + switch (field.item_type) {
|
| + case ItemTypeCardNumber: {
|
| + NSString* cardNumber =
|
| + base::SysUTF16ToNSString(_creditCard->number());
|
| + item.textFieldValue = cardNumber;
|
| + item.cardTypeIcon = [self cardTypeIconFromCardNumber:cardNumber];
|
| + break;
|
| + }
|
| + case ItemTypeCardholderName: {
|
| + item.textFieldValue = autofill::GetCreditCardName(
|
| + *_creditCard, GetApplicationContext()->GetApplicationLocale());
|
| + break;
|
| + }
|
| + case ItemTypeExpirationMonth: {
|
| + item.textFieldValue = [NSString
|
| + stringWithFormat:@"%02d", _creditCard->expiration_month()];
|
| + break;
|
| + }
|
| + case ItemTypeExpirationYear: {
|
| + item.textFieldValue = [NSString
|
| + stringWithFormat:@"%04d", _creditCard->expiration_year()];
|
| + break;
|
| + }
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (!_creditCard->billing_address_id().empty()) {
|
| + _billingAddressGUID = _creditCard->billing_address_id();
|
| + autofill::AutofillProfile* billingAddress =
|
| + autofill::PersonalDataManager::GetProfileFromProfilesByGUID(
|
| + _creditCard->billing_address_id(),
|
| + _paymentRequest->billing_profiles());
|
| + DCHECK(billingAddress);
|
| + billingAddressItem.detailText =
|
| + GetBillingAddressLabelFromAutofillProfile(*billingAddress);
|
| + }
|
| + }
|
| +}
|
| +
|
| +- (void)viewDidLoad {
|
| + [super viewDidLoad];
|
| + self.collectionView.accessibilityIdentifier = kCreditCardEditCollectionViewId;
|
| +
|
| + // Customize collection view settings.
|
| + self.styler.cellStyle = MDCCollectionViewCellStyleCard;
|
| + self.styler.separatorInset =
|
| + UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset);
|
| +}
|
| +
|
| +#pragma mark - UITextFieldDelegate
|
| +
|
| +// 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 {
|
| + NSIndexPath* indexPath = [self indexPathForCurrentTextField];
|
| + AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| + [self.collectionViewModel itemAtIndexPath:indexPath]);
|
| +
|
| + // If the user is typing in the credit card number field, update the card type
|
| + // icon (e.g. "Visa") to reflect the number being typed.
|
| + if (item.autofillType == autofill::CREDIT_CARD_NUMBER) {
|
| + // Obtain the text being typed.
|
| + NSString* updatedText =
|
| + [textField.text stringByReplacingCharactersInRange:range
|
| + withString:newText];
|
| + item.cardTypeIcon = [self cardTypeIconFromCardNumber:updatedText];
|
| + // Update the cell.
|
| + [self reconfigureCellsForItems:@[ item ]
|
| + inSectionWithIdentifier:SectionIdentifierCardNumber];
|
| + }
|
| +
|
| + return YES;
|
| +}
|
| +
|
| +- (void)textFieldDidEndEditing:(UITextField*)textField {
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + NSIndexPath* indexPath = [self indexPathForCurrentTextField];
|
| + AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>(
|
| + [model itemAtIndexPath:indexPath]);
|
| +
|
| + // Validate the text field. If there is a validation error, display an error
|
| + // message item in the same section as the field. Otherwise remove the error
|
| + // message item in that section
|
| + NSString* errorMessage = [self validateValue:textField.text
|
| + autofillType:item.autofillType
|
| + required:item.required];
|
| + NSInteger sectionIdentifier =
|
| + [model sectionIdentifierForSection:[indexPath section]];
|
| + [self addOrRemoveErrorItemWithType:ItemTypeErrorMessage
|
| + errorMessage:errorMessage
|
| + inSectionWithIdentifier:sectionIdentifier];
|
| +
|
| + [super textFieldDidEndEditing:textField];
|
| +}
|
| +
|
| +#pragma mark - UICollectionViewDataSource
|
| +
|
| +- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
|
| + cellForItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + UICollectionViewCell* cell =
|
| + [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
| +
|
| + NSInteger itemType =
|
| + [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| + switch (itemType) {
|
| + case ItemTypeCardNumber: {
|
| + AutofillEditCell* textFieldCell =
|
| + base::mac::ObjCCast<AutofillEditCell>(cell);
|
| + textFieldCell.textField.delegate = self;
|
| + textFieldCell.textField.autocapitalizationType =
|
| + UITextAutocapitalizationTypeSentences;
|
| + textFieldCell.textField.keyboardType = UIKeyboardTypeNumberPad;
|
| + textFieldCell.textField.returnKeyType = UIReturnKeyNext;
|
| + textFieldCell.textField.clearButtonMode = UITextFieldViewModeNever;
|
| + textFieldCell.textLabel.font = [MDCTypography body2Font];
|
| + textFieldCell.textLabel.textColor = [[MDCPalette greyPalette] tint900];
|
| + textFieldCell.textField.font = [MDCTypography body1Font];
|
| + textFieldCell.textField.textColor = [[MDCPalette cr_bluePalette] tint600];
|
| + break;
|
| + }
|
| + case ItemTypeCardholderName: {
|
| + AutofillEditCell* textFieldCell =
|
| + base::mac::ObjCCast<AutofillEditCell>(cell);
|
| + textFieldCell.textField.delegate = self;
|
| + textFieldCell.textField.autocapitalizationType =
|
| + UITextAutocapitalizationTypeWords;
|
| + textFieldCell.textField.keyboardType = UIKeyboardTypeDefault;
|
| + textFieldCell.textField.returnKeyType = UIReturnKeyNext;
|
| + textFieldCell.textField.clearButtonMode = UITextFieldViewModeNever;
|
| + textFieldCell.textLabel.font = [MDCTypography body2Font];
|
| + textFieldCell.textLabel.textColor = [[MDCPalette greyPalette] tint900];
|
| + textFieldCell.textField.font = [MDCTypography body1Font];
|
| + textFieldCell.textField.textColor = [[MDCPalette cr_bluePalette] tint600];
|
| + break;
|
| + }
|
| + case ItemTypeExpirationMonth: {
|
| + AutofillEditCell* textFieldCell =
|
| + base::mac::ObjCCast<AutofillEditCell>(cell);
|
| + textFieldCell.textField.delegate = self;
|
| + textFieldCell.textField.autocapitalizationType =
|
| + UITextAutocapitalizationTypeSentences;
|
| + textFieldCell.textField.keyboardType = UIKeyboardTypeNumberPad;
|
| + textFieldCell.textField.returnKeyType = UIReturnKeyNext;
|
| + textFieldCell.textField.clearButtonMode = UITextFieldViewModeNever;
|
| + textFieldCell.textLabel.font = [MDCTypography body2Font];
|
| + textFieldCell.textLabel.textColor = [[MDCPalette greyPalette] tint900];
|
| + textFieldCell.textField.font = [MDCTypography body1Font];
|
| + textFieldCell.textField.textColor = [[MDCPalette cr_bluePalette] tint600];
|
| + break;
|
| + }
|
| + case ItemTypeExpirationYear: {
|
| + AutofillEditCell* textFieldCell =
|
| + base::mac::ObjCCast<AutofillEditCell>(cell);
|
| + textFieldCell.textField.delegate = self;
|
| + textFieldCell.textField.autocapitalizationType =
|
| + UITextAutocapitalizationTypeSentences;
|
| + textFieldCell.textField.keyboardType = UIKeyboardTypeNumberPad;
|
| + textFieldCell.textField.returnKeyType = UIReturnKeyDone;
|
| + textFieldCell.textField.clearButtonMode = UITextFieldViewModeNever;
|
| + textFieldCell.textLabel.font = [MDCTypography body2Font];
|
| + textFieldCell.textLabel.textColor = [[MDCPalette greyPalette] tint900];
|
| + textFieldCell.textField.font = [MDCTypography body1Font];
|
| + textFieldCell.textField.textColor = [[MDCPalette cr_bluePalette] tint600];
|
| + break;
|
| + }
|
| + case ItemTypeBillingAddress: {
|
| + CollectionViewDetailCell* billingCell =
|
| + base::mac::ObjCCastStrict<CollectionViewDetailCell>(cell);
|
| + billingCell.textLabel.font = [MDCTypography body2Font];
|
| + billingCell.textLabel.textColor = [[MDCPalette greyPalette] tint900];
|
| + billingCell.detailTextLabel.font = [MDCTypography body1Font];
|
| + billingCell.detailTextLabel.textColor =
|
| + [[MDCPalette cr_bluePalette] tint600];
|
| + break;
|
| + }
|
| + case ItemTypeErrorMessage: {
|
| + PaymentsTextCell* messageCell =
|
| + base::mac::ObjCCastStrict<PaymentsTextCell>(cell);
|
| + messageCell.textLabel.font = [MDCTypography body1Font];
|
| + messageCell.textLabel.textColor = [[MDCPalette cr_redPalette] tint600];
|
| + break;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + return cell;
|
| +}
|
| +
|
| +#pragma mark UICollectionViewDelegate
|
| +
|
| +- (void)collectionView:(UICollectionView*)collectionView
|
| + didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
|
| + [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
|
| + CollectionViewModel* model = self.collectionViewModel;
|
| +
|
| + CollectionViewItem* item = [model itemAtIndexPath:indexPath];
|
| + switch (item.type) {
|
| + case ItemTypeCardNumber:
|
| + case ItemTypeCardholderName:
|
| + case ItemTypeExpirationMonth:
|
| + case ItemTypeExpirationYear:
|
| + case ItemTypeErrorMessage:
|
| + break;
|
| + case ItemTypeBillingAddress: {
|
| + // TODO(crbug.com/602666): This is wrong! Done this way to make submitting
|
| + // the form possible. Display a list of billing addresses instead.
|
| + autofill::AutofillProfile* billingAddress =
|
| + _paymentRequest->selected_shipping_profile();
|
| + DCHECK(billingAddress);
|
| + _billingAddressGUID = billingAddress->guid();
|
| +
|
| + CollectionViewDetailItem* billingAddressItem =
|
| + base::mac::ObjCCastStrict<CollectionViewDetailItem>(item);
|
| + billingAddressItem.detailText =
|
| + GetBillingAddressLabelFromAutofillProfile(*billingAddress);
|
| + // Update the cell.
|
| + [self reconfigureCellsForItems:@[ billingAddressItem ]
|
| + inSectionWithIdentifier:SectionIdentifierBillingAddress];
|
| + break;
|
| + }
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| +}
|
| +
|
| +#pragma mark MDCCollectionViewStylingDelegate
|
| +
|
| +- (CGFloat)collectionView:(UICollectionView*)collectionView
|
| + cellHeightAtIndexPath:(NSIndexPath*)indexPath {
|
| + CollectionViewItem* item =
|
| + [self.collectionViewModel itemAtIndexPath:indexPath];
|
| + switch (item.type) {
|
| + case ItemTypeCardNumber:
|
| + case ItemTypeCardholderName:
|
| + case ItemTypeExpirationMonth:
|
| + case ItemTypeExpirationYear:
|
| + case ItemTypeErrorMessage:
|
| + return [MDCCollectionViewCell
|
| + cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
|
| + forItem:item];
|
| + case ItemTypeBillingAddress:
|
| + return MDCCellDefaultOneLineHeight;
|
| + default:
|
| + NOTREACHED();
|
| + return MDCCellDefaultOneLineHeight;
|
| + }
|
| +}
|
| +
|
| +- (BOOL)collectionView:(UICollectionView*)collectionView
|
| + hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
|
| + NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
|
| + switch (type) {
|
| + case ItemTypeErrorMessage:
|
| + return YES;
|
| + default:
|
| + return NO;
|
| + }
|
| +}
|
| +
|
| +#pragma mark - Helper methods
|
| +
|
| +- (UIImage*)cardTypeIconFromCardNumber:(NSString*)cardNumber {
|
| + const char* cardType = autofill::CreditCard::GetCreditCardType(
|
| + base::SysNSStringToUTF16(cardNumber));
|
| + if (cardType != autofill::kGenericCard) {
|
| + int resourceID =
|
| + autofill::data_util::GetPaymentRequestData(cardType).icon_resource_id;
|
| + // Resize and return the card type icon.
|
| + CGFloat dimension = kCardTypeIconDimension;
|
| + return ResizeImage(NativeImage(resourceID),
|
| + CGSizeMake(dimension, dimension),
|
| + ProjectionMode::kAspectFillNoClipping);
|
| + } else {
|
| + return nil;
|
| + }
|
| +}
|
| +
|
| +@end
|
|
|