tdesktop/Telegram/SourceFiles/payments/ui/payments_edit_information.cpp

283 lines
8.2 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "payments/ui/payments_edit_information.h"
#include "payments/ui/payments_panel_delegate.h"
#include "payments/ui/payments_field.h"
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/checkbox.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/fade_wrap.h"
#include "lang/lang_keys.h"
#include "styles/style_payments.h"
#include "styles/style_passport.h"
namespace Payments::Ui {
namespace {
constexpr auto kMaxStreetSize = 64;
constexpr auto kMaxPostcodeSize = 10;
constexpr auto kMaxNameSize = 64;
constexpr auto kMaxEmailSize = 128;
constexpr auto kMaxPhoneSize = 16;
constexpr auto kMinCitySize = 2;
constexpr auto kMaxCitySize = 64;
} // namespace
EditInformation::EditInformation(
QWidget *parent,
const Invoice &invoice,
const RequestedInformation &current,
InformationField field,
not_null<PanelDelegate*> delegate)
: _delegate(delegate)
, _invoice(invoice)
, _information(current)
, _scroll(this, st::passportPanelScroll)
, _topShadow(this)
, _bottomShadow(this)
, _submit(
this,
tr::lng_settings_save(),
st::paymentsPanelButton)
, _cancel(
this,
tr::lng_cancel(),
st::paymentsPanelButton) {
setupControls();
}
EditInformation::~EditInformation() = default;
void EditInformation::setFocus(InformationField field) {
_focusField = field;
if (const auto control = lookupField(field)) {
_scroll->ensureWidgetVisible(control->widget());
control->setFocus();
}
}
void EditInformation::setFocusFast(InformationField field) {
_focusField = field;
if (const auto control = lookupField(field)) {
_scroll->ensureWidgetVisible(control->widget());
control->setFocusFast();
}
}
void EditInformation::showError(InformationField field) {
if (const auto control = lookupField(field)) {
_scroll->ensureWidgetVisible(control->widget());
control->showError();
}
}
void EditInformation::setupControls() {
const auto inner = setupContent();
_submit->addClickHandler([=] {
_delegate->panelValidateInformation(collect());
});
_cancel->addClickHandler([=] {
_delegate->panelCancelEdit();
});
using namespace rpl::mappers;
_topShadow->toggleOn(
_scroll->scrollTopValue() | rpl::map(_1 > 0));
_bottomShadow->toggleOn(rpl::combine(
_scroll->scrollTopValue(),
_scroll->heightValue(),
inner->heightValue(),
_1 + _2 < _3));
}
not_null<RpWidget*> EditInformation::setupContent() {
const auto inner = _scroll->setOwnedWidget(
object_ptr<VerticalLayout>(this));
_scroll->widthValue(
) | rpl::start_with_next([=](int width) {
inner->resizeToWidth(width);
}, inner->lifetime());
const auto showBox = [=](object_ptr<BoxContent> box) {
_delegate->panelShowBox(std::move(box));
};
auto last = (Field*)nullptr;
const auto add = [&](FieldConfig &&config) {
auto result = std::make_unique<Field>(inner, std::move(config));
inner->add(result->ownedWidget(), st::paymentsFieldPadding);
if (last) {
last->setNextField(result.get());
result->setPreviousField(last);
}
last = result.get();
return result;
};
if (_invoice.isShippingAddressRequested) {
_street1 = add({
.placeholder = tr::lng_payments_address_street1(),
.value = _information.shippingAddress.address1,
.validator = RangeLengthValidator(1, kMaxStreetSize),
});
_street2 = add({
.placeholder = tr::lng_payments_address_street2(),
.value = _information.shippingAddress.address2,
.validator = MaxLengthValidator(kMaxStreetSize),
});
_city = add({
.placeholder = tr::lng_payments_address_city(),
.value = _information.shippingAddress.city,
.validator = RangeLengthValidator(kMinCitySize, kMaxCitySize),
});
_state = add({
.placeholder = tr::lng_payments_address_state(),
.value = _information.shippingAddress.state,
});
_country = add({
.type = FieldType::Country,
.placeholder = tr::lng_payments_address_country(),
.value = _information.shippingAddress.countryIso2,
.validator = RequiredFinishedValidator(),
.showBox = showBox,
.defaultCountry = _information.defaultCountry,
});
_postcode = add({
.placeholder = tr::lng_payments_address_postcode(),
.value = _information.shippingAddress.postcode,
.validator = RangeLengthValidator(1, kMaxPostcodeSize),
});
}
if (_invoice.isNameRequested) {
_name = add({
.placeholder = tr::lng_payments_info_name(),
.value = _information.name,
.validator = RangeLengthValidator(1, kMaxNameSize),
});
}
if (_invoice.isEmailRequested) {
_email = add({
.type = FieldType::Email,
.placeholder = tr::lng_payments_info_email(),
.value = _information.email,
.validator = RangeLengthValidator(1, kMaxEmailSize),
});
}
if (_invoice.isPhoneRequested) {
_phone = add({
.type = FieldType::Phone,
.placeholder = tr::lng_payments_info_phone(),
.value = _information.phone,
.validator = RangeLengthValidator(1, kMaxPhoneSize),
.defaultPhone = _information.defaultPhone,
});
}
const auto emailToProvider = _invoice.isEmailRequested
&& _invoice.emailSentToProvider;
const auto phoneToProvider = _invoice.isPhoneRequested
&& _invoice.phoneSentToProvider;
if (emailToProvider || phoneToProvider) {
inner->add(
object_ptr<Ui::FlatLabel>(
inner,
((emailToProvider && phoneToProvider)
? tr::lng_payments_to_provider_phone_email
: emailToProvider
? tr::lng_payments_to_provider_email
: tr::lng_payments_to_provider_phone)(
lt_provider,
rpl::single(_invoice.provider)),
st::paymentsToProviderLabel),
st::paymentsToProviderPadding);
}
_save = inner->add(
object_ptr<Ui::Checkbox>(
inner,
tr::lng_payments_save_information(tr::now),
true),
st::paymentsSaveCheckboxPadding);
if (last) {
last->submitted(
) | rpl::start_with_next([=] {
_delegate->panelValidateInformation(collect());
}, lifetime());
}
return inner;
}
void EditInformation::resizeEvent(QResizeEvent *e) {
updateControlsGeometry();
}
void EditInformation::focusInEvent(QFocusEvent *e) {
if (const auto control = lookupField(_focusField)) {
control->setFocus();
}
}
void EditInformation::updateControlsGeometry() {
const auto &padding = st::paymentsPanelPadding;
const auto buttonsHeight = padding.top()
+ _cancel->height()
+ padding.bottom();
const auto buttonsTop = height() - buttonsHeight;
_scroll->setGeometry(0, 0, width(), buttonsTop);
_topShadow->resizeToWidth(width());
_topShadow->moveToLeft(0, 0);
_bottomShadow->resizeToWidth(width());
_bottomShadow->moveToLeft(0, buttonsTop - st::lineWidth);
auto right = padding.right();
_submit->moveToRight(right, buttonsTop + padding.top());
right += _submit->width() + padding.left();
_cancel->moveToRight(right, buttonsTop + padding.top());
_scroll->updateBars();
}
auto EditInformation::lookupField(InformationField field) const -> Field* {
switch (field) {
case InformationField::ShippingStreet: return _street1.get();
case InformationField::ShippingCity: return _city.get();
case InformationField::ShippingState: return _state.get();
case InformationField::ShippingCountry: return _country.get();
case InformationField::ShippingPostcode: return _postcode.get();
case InformationField::Name: return _name.get();
case InformationField::Email: return _email.get();
case InformationField::Phone: return _phone.get();
}
Unexpected("Unknown field in EditInformation::lookupField.");
}
RequestedInformation EditInformation::collect() const {
return {
.defaultPhone = _information.defaultPhone,
.defaultCountry = _information.defaultCountry,
.save = _save->checked(),
.name = _name ? _name->value() : QString(),
.phone = _phone ? _phone->value() : QString(),
.email = _email ? _email->value() : QString(),
.shippingAddress = {
.address1 = _street1 ? _street1->value() : QString(),
.address2 = _street2 ? _street2->value() : QString(),
.city = _city ? _city->value() : QString(),
.state = _state ? _state->value() : QString(),
.countryIso2 = _country ? _country->value() : QString(),
.postcode = _postcode ? _postcode->value() : QString(),
},
};
}
} // namespace Payments::Ui