blob: b7bc37b3c026443aa5d7175acfae51438916b1a6 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/autofill/payments/migratable_card_view.h"
#include "base/functional/bind.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/autofill/payments/local_card_migration_dialog_state.h"
#include "chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "components/autofill/core/browser/payments/local_card_migration_manager.h"
#include "components/grit/components_scaled_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/animation/ink_drop.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/image_button_factory.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
namespace autofill {
MigratableCardView::MigratableCardView(
const MigratableCreditCard& migratable_credit_card,
LocalCardMigrationDialogView* parent_dialog,
bool should_show_checkbox)
: migratable_credit_card_(migratable_credit_card),
parent_dialog_(parent_dialog) {
ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, gfx::Insets(),
provider->GetDistanceMetric(DISTANCE_CONTENT_LIST_VERTICAL_MULTI)));
AddChildView(GetMigratableCardDescriptionView(migratable_credit_card,
should_show_checkbox)
.release());
checkbox_uncheck_text_container_ =
AddChildView(views::Builder<views::View>()
.SetBackground(views::CreateThemedSolidBackground(
ui::kColorBubbleFooterBackground))
.Build());
views::BoxLayout* layout = checkbox_uncheck_text_container_->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical,
gfx::Insets::VH(provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_VERTICAL),
provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL)),
provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart);
checkbox_uncheck_text_container_->AddChildView(std::make_unique<views::Label>(
l10n_util::GetStringUTF16(
IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_CHECKBOX_UNCHECK_WARNING),
CONTEXT_DIALOG_BODY_TEXT_SMALL, ChromeTextStyle::STYLE_RED));
checkbox_uncheck_text_container_->SetVisible(false);
}
MigratableCardView::~MigratableCardView() = default;
bool MigratableCardView::GetSelected() const {
return !checkbox_ || checkbox_->GetChecked();
}
std::string MigratableCardView::GetGuid() const {
return migratable_credit_card_.credit_card().guid();
}
std::u16string MigratableCardView::GetCardIdentifierString() const {
return migratable_credit_card_.credit_card().CardNameAndLastFourDigits();
}
std::unique_ptr<views::View>
MigratableCardView::GetMigratableCardDescriptionView(
const MigratableCreditCard& migratable_credit_card,
bool should_show_checkbox) {
auto migratable_card_description_view = std::make_unique<views::View>();
ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
migratable_card_description_view->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
provider->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_HORIZONTAL)));
std::unique_ptr<views::Label> card_description =
std::make_unique<views::Label>(GetCardIdentifierString(),
views::style::CONTEXT_LABEL);
card_description->SetMultiLine(true);
card_description->SetHorizontalAlignment(gfx::ALIGN_LEFT);
constexpr int kCardDescriptionMaximumWidth = 260;
card_description->SetMaximumWidth(kCardDescriptionMaximumWidth);
constexpr int kMigrationResultImageSize = 16;
switch (migratable_credit_card.migration_status()) {
case MigratableCreditCard::MigrationStatus::UNKNOWN: {
if (should_show_checkbox) {
checkbox_ = migratable_card_description_view->AddChildView(
std::make_unique<views::Checkbox>(
std::u16string(),
base::BindRepeating(&MigratableCardView::CheckboxPressed,
base::Unretained(this))));
checkbox_->SetChecked(true);
// TODO(crbug/867194): Currently the ink drop animation circle is
// cropped by the border of scroll bar view. Find a way to adjust the
// format.
views::InkDrop::Get(checkbox_->ink_drop_view())
->SetMode(views::InkDropHost::InkDropMode::OFF);
checkbox_->SetAccessibleName(card_description.get());
}
break;
}
case MigratableCreditCard::MigrationStatus::SUCCESS_ON_UPLOAD: {
auto* migration_succeeded_image =
migratable_card_description_view->AddChildView(
std::make_unique<views::ImageView>());
migration_succeeded_image->SetImage(ui::ImageModel::FromVectorIcon(
vector_icons::kCheckCircleIcon, ui::kColorAlertLowSeverity,
kMigrationResultImageSize));
break;
}
case MigratableCreditCard::MigrationStatus::FAILURE_ON_UPLOAD: {
auto* migration_failed_image =
migratable_card_description_view->AddChildView(
std::make_unique<views::ImageView>());
migration_failed_image->SetImage(ui::ImageModel::FromVectorIcon(
vector_icons::kErrorIcon, ui::kColorAlertHighSeverity,
kMigrationResultImageSize));
break;
}
}
std::unique_ptr<views::View> card_network_and_last_four_digits =
std::make_unique<views::View>();
card_network_and_last_four_digits->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
provider->GetDistanceMetric(DISTANCE_RELATED_LABEL_HORIZONTAL_LIST)));
std::unique_ptr<views::ImageView> card_image =
std::make_unique<views::ImageView>();
card_image->SetImage(
ui::ImageModel::FromResourceId(CreditCard::IconResourceId(
migratable_credit_card.credit_card().network())));
card_image->SetAccessibleName(
migratable_credit_card.credit_card().NetworkForDisplay());
card_network_and_last_four_digits->AddChildView(card_image.release());
card_network_and_last_four_digits->AddChildView(card_description.release());
migratable_card_description_view->AddChildView(
card_network_and_last_four_digits.release());
std::unique_ptr<views::Label> card_expiration =
std::make_unique<views::Label>(
migratable_credit_card.credit_card()
.AbbreviatedExpirationDateForDisplay(/*with_prefix=*/true),
views::style::CONTEXT_LABEL, views::style::STYLE_SECONDARY);
card_expiration->SetElideBehavior(gfx::ElideBehavior::NO_ELIDE);
card_expiration->SetMultiLine(true);
migratable_card_description_view->AddChildView(card_expiration.release());
// If card is not successfully uploaded we show the invalid card
// label and the trash can icon.
if (migratable_credit_card.migration_status() ==
MigratableCreditCard::MigrationStatus::FAILURE_ON_UPLOAD) {
migratable_card_description_view->AddChildView(new views::Label(
l10n_util::GetStringUTF16(
IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_LABEL_INVALID_CARDS),
views::style::CONTEXT_LABEL, ChromeTextStyle::STYLE_RED));
auto delete_card_from_local_button =
views::CreateVectorImageButtonWithNativeTheme(
base::BindRepeating(
[](LocalCardMigrationDialogView* parent_dialog,
std::string guid) {
parent_dialog->DeleteCard(std::move(guid));
},
parent_dialog_, GetGuid()),
kTrashCanIcon);
delete_card_from_local_button->SetTooltipText(l10n_util::GetStringUTF16(
IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TRASH_CAN_BUTTON_TOOLTIP));
delete_card_from_local_button->SetFocusBehavior(
FocusBehavior::ACCESSIBLE_ONLY);
delete_card_from_local_button_ =
migratable_card_description_view->AddChildView(
std::move(delete_card_from_local_button));
}
return migratable_card_description_view;
}
void MigratableCardView::CheckboxPressed() {
// If the button clicked is a checkbox. Enable/disable the save
// button if needed.
parent_dialog_->OnCardCheckboxToggled();
// The warning text will be visible only when user unchecks the checkbox.
checkbox_uncheck_text_container_->SetVisible(!checkbox_->GetChecked());
InvalidateLayout();
parent_dialog_->UpdateLayout();
}
BEGIN_METADATA(MigratableCardView)
ADD_READONLY_PROPERTY_METADATA(bool, Selected)
ADD_READONLY_PROPERTY_METADATA(std::string, Guid)
ADD_READONLY_PROPERTY_METADATA(std::u16string, CardIdentifierString)
END_METADATA
} // namespace autofill