Chromium Code Reviews| Index: chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc |
| diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc |
| index 917c31686d5b422511df638cc3d1ada310d8a759..02df2f2bc337d53c41cb2d8b8fc3a3da86460f0b 100644 |
| --- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc |
| +++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc |
| @@ -54,6 +54,10 @@ namespace { |
| // year dropdown. |
| const int kNumberOfExpirationYears = 10; |
| +// Opacity of card network icons when they are not selected and are displayed |
| +// alongside a selected icon. |
| +const float kDimmedCardIconOpacity = 0.33f; |
|
anthonyvd
2017/05/23 15:59:42
Didn't Bruno specify 50%?
|
| + |
| // This is not quite right but is the closest server type that wasn't already |
| // used. |
| const auto kBillingAddressType = autofill::ADDRESS_BILLING_LINE1; |
| @@ -101,8 +105,11 @@ bool IsCardExpired(const base::string16& month, |
| class ExpirationDateValidationDelegate : public ValidationDelegate { |
| public: |
| ExpirationDateValidationDelegate(EditorViewController* controller, |
| - const std::string& app_locale) |
| - : controller_(controller), app_locale_(app_locale) {} |
| + const std::string& app_locale, |
| + bool initially_valid) |
| + : controller_(controller), |
| + app_locale_(app_locale), |
| + initially_valid_(initially_valid) {} |
| bool IsValidTextfield(views::Textfield* textfield) override { |
| NOTREACHED(); |
| @@ -110,9 +117,13 @@ class ExpirationDateValidationDelegate : public ValidationDelegate { |
| } |
| bool IsValidCombobox(views::Combobox* combobox) override { |
| - // Get the combined date from the month and year dropdowns. |
| + // View will have no parent if it's not been attached yet. Use initial |
| + // validity state. |
| views::View* view_parent = combobox->parent(); |
| + if (!view_parent) |
| + return initially_valid_; |
| + // Get the combined date from the month and year dropdowns. |
| views::Combobox* month_combobox = static_cast<views::Combobox*>( |
| view_parent->GetViewByID(EditorViewController::GetInputFieldViewId( |
| autofill::CREDIT_CARD_EXP_MONTH))); |
| @@ -132,7 +143,8 @@ class ExpirationDateValidationDelegate : public ValidationDelegate { |
| return !is_expired; |
| } |
| - bool TextfieldValueChanged(views::Textfield* textfield) override { |
| + bool TextfieldValueChanged(views::Textfield* textfield, |
| + bool was_blurred) override { |
| NOTREACHED(); |
| return true; |
| } |
| @@ -152,6 +164,7 @@ class ExpirationDateValidationDelegate : public ValidationDelegate { |
| private: |
| EditorViewController* controller_; |
| const std::string app_locale_; |
| + bool initially_valid_; |
| DISALLOW_COPY_AND_ASSIGN(ExpirationDateValidationDelegate); |
| }; |
| @@ -214,18 +227,32 @@ CreditCardEditorViewController::CreateHeaderView() { |
| views::BoxLayout::kHorizontal, 0, 0, kPaddingBetweenCardIcons); |
| icons_row->SetLayoutManager(icons_layout); |
| + std::string selected_network = |
| + credit_card_to_edit_ ? autofill::data_util::GetPaymentRequestData( |
| + credit_card_to_edit_->network()) |
| + .basic_card_issuer_network |
| + : ""; |
| constexpr gfx::Size kCardIconSize = gfx::Size(30, 18); |
| for (const std::string& supported_network : |
| spec()->supported_card_networks()) { |
| const std::string autofill_card_type = |
| autofill::data_util::GetIssuerNetworkForBasicCardIssuerNetwork( |
| supported_network); |
| + // Icon is fully opaque if no network is selected, or if it is the selected |
| + // network. |
| + float opacity = |
| + selected_network.empty() || selected_network == supported_network |
| + ? 1.0f |
| + : kDimmedCardIconOpacity; |
| std::unique_ptr<views::ImageView> card_icon_view = CreateInstrumentIconView( |
| autofill::data_util::GetPaymentRequestData(autofill_card_type) |
| .icon_resource_id, |
| - base::UTF8ToUTF16(supported_network)); |
| + base::UTF8ToUTF16(supported_network), opacity); |
| card_icon_view->SetImageSize(kCardIconSize); |
| + // Keep track of this card icon to later adjust opacity. |
| + card_icons_[supported_network] = card_icon_view.get(); |
| + |
| icons_row->AddChildView(card_icon_view.release()); |
| } |
| view->AddChildView(icons_row.release()); |
| @@ -280,7 +307,7 @@ CreditCardEditorViewController::CreateCustomFieldView( |
| GetInitialValueForType(autofill::CREDIT_CARD_EXP_MONTH); |
| base::string16 year = |
| GetInitialValueForType(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR); |
| - *valid = IsCardExpired(month, year, state()->GetApplicationLocale()); |
| + *valid = !IsCardExpired(month, year, state()->GetApplicationLocale()); |
| return view; |
| } |
| @@ -414,12 +441,17 @@ bool CreditCardEditorViewController::ValidateModelAndSave() { |
| std::unique_ptr<ValidationDelegate> |
| CreditCardEditorViewController::CreateValidationDelegate( |
| const EditorField& field) { |
| - // The supported card networks for non-cc-number types are not passed to avoid |
| - // the data copy in the delegate. |
| if (field.type == autofill::CREDIT_CARD_EXP_MONTH || |
| - field.type == autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR) |
| + field.type == autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR) { |
| + bool initially_valid = |
| + credit_card_to_edit_ |
| + ? !credit_card_to_edit_->IsExpired(autofill::AutofillClock::Now()) |
| + : true; |
| return base::MakeUnique<ExpirationDateValidationDelegate>( |
| - this, state()->GetApplicationLocale()); |
| + this, state()->GetApplicationLocale(), initially_valid); |
| + } |
| + // The supported card networks for non-cc-number types are not passed to avoid |
| + // the data copy in the delegate. |
| return base::MakeUnique< |
| CreditCardEditorViewController::CreditCardValidationDelegate>( |
| field, this, |
| @@ -456,6 +488,23 @@ CreditCardEditorViewController::GetComboboxModelForType( |
| return std::unique_ptr<ui::ComboboxModel>(); |
| } |
| +void CreditCardEditorViewController::SelectBasicCardNetworkIcon( |
| + const std::string& basic_card_network) { |
| + // If empty string was passed or if the icon representing |basic_card_network| |
| + // is not present (i.e. not supported), all icons have full opacity. |
| + bool full_opacity = |
| + card_icons_.find(basic_card_network) == card_icons_.end() || |
| + basic_card_network.empty(); |
| + for (auto network_icon_it : card_icons_) { |
| + float target_opacity = |
| + full_opacity || network_icon_it.first == basic_card_network |
| + ? 1.0f |
| + : kDimmedCardIconOpacity; |
| + network_icon_it.second->layer()->SetOpacity(target_opacity); |
| + network_icon_it.second->layer()->ScheduleDraw(); |
| + } |
| +} |
| + |
| void CreditCardEditorViewController::FillContentView( |
| views::View* content_view) { |
| EditorViewController::FillContentView(content_view); |
| @@ -517,7 +566,7 @@ void CreditCardEditorViewController::AddAndSelectNewBillingAddress( |
| CreditCardEditorViewController::CreditCardValidationDelegate:: |
| CreditCardValidationDelegate( |
| const EditorField& field, |
| - EditorViewController* controller, |
| + CreditCardEditorViewController* controller, |
| const std::vector<std::string>& supported_card_networks) |
| : field_(field), |
| controller_(controller), |
| @@ -537,10 +586,25 @@ bool CreditCardEditorViewController::CreditCardValidationDelegate:: |
| } |
| bool CreditCardEditorViewController::CreditCardValidationDelegate:: |
| - TextfieldValueChanged(views::Textfield* textfield) { |
| + TextfieldValueChanged(views::Textfield* textfield, bool was_blurred) { |
| + // The only behavior pre-blur is selecting the card icon. |
| + if (field_.type == autofill::CREDIT_CARD_NUMBER) { |
| + std::string basic_card_network = |
| + autofill::data_util::GetPaymentRequestData( |
| + autofill::CreditCard::GetCardNetwork(textfield->text())) |
| + .basic_card_issuer_network; |
| + controller_->SelectBasicCardNetworkIcon(basic_card_network); |
| + } |
| + |
| + // We return true if the field was not yet blurred, because validation should |
| + // not occur yet. |
| + if (!was_blurred) |
| + return true; |
| + |
| base::string16 error_message; |
| bool is_valid = ValidateValue(textfield->text(), &error_message); |
| controller_->DisplayErrorMessageForField(field_.type, error_message); |
| + |
| return is_valid; |
| } |