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

351 lines
9.4 KiB
C++
Raw Normal View History

2021-03-23 12:34:34 +00:00
/*
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_form_summary.h"
#include "payments/ui/payments_panel_delegate.h"
2021-03-26 13:05:31 +00:00
#include "settings/settings_common.h"
2021-03-23 12:34:34 +00:00
#include "ui/widgets/scroll_area.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
2021-03-23 12:34:34 +00:00
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/fade_wrap.h"
#include "ui/text/format_values.h"
2021-03-23 12:34:34 +00:00
#include "lang/lang_keys.h"
#include "styles/style_payments.h"
#include "styles/style_passport.h"
namespace Payments::Ui {
using namespace ::Ui;
class PanelDelegate;
FormSummary::FormSummary(
QWidget *parent,
const Invoice &invoice,
const RequestedInformation &current,
const PaymentMethodDetails &method,
const ShippingOptions &options,
2021-03-23 12:34:34 +00:00
not_null<PanelDelegate*> delegate)
: _delegate(delegate)
, _invoice(invoice)
, _method(method)
, _options(options)
, _information(current)
2021-03-23 12:34:34 +00:00
, _scroll(this, st::passportPanelScroll)
, _topShadow(this)
, _bottomShadow(this)
, _submit(
this,
tr::lng_payments_pay_amount(
lt_amount,
2021-03-26 13:05:31 +00:00
rpl::single(formatAmount(computeTotalAmount()))),
st::paymentsPanelSubmit) {
2021-03-23 12:34:34 +00:00
setupControls();
}
2021-03-26 13:05:31 +00:00
void FormSummary::updateThumbnail(const QImage &thumbnail) {
_invoice.cover.thumbnail = thumbnail;
_thumbnails.fire_copy(thumbnail);
}
2021-03-26 13:05:31 +00:00
QString FormSummary::formatAmount(int64 amount) const {
const auto base = FillAmountAndCurrency(
std::abs(amount),
_invoice.currency);
return (amount < 0) ? (QString::fromUtf8("\xe2\x88\x92") + base) : base;
2021-03-26 13:05:31 +00:00
}
int64 FormSummary::computeTotalAmount() const {
const auto total = ranges::accumulate(
_invoice.prices,
int64(0),
std::plus<>(),
&LabeledPrice::price);
const auto selected = ranges::find(
_options.list,
_options.selectedId,
&ShippingOption::id);
const auto shipping = (selected != end(_options.list))
? ranges::accumulate(
selected->prices,
int64(0),
std::plus<>(),
&LabeledPrice::price)
: int64(0);
2021-03-26 13:05:31 +00:00
return total + shipping;
}
2021-03-23 12:34:34 +00:00
void FormSummary::setupControls() {
const auto inner = setupContent();
_submit->addClickHandler([=] {
_delegate->panelSubmit();
});
if (!_invoice) {
_submit->hide();
}
2021-03-23 12:34:34 +00:00
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));
}
2021-03-26 13:05:31 +00:00
void FormSummary::setupCover(not_null<VerticalLayout*> layout) {
struct State {
QImage thumbnail;
FlatLabel *title = nullptr;
FlatLabel *description = nullptr;
FlatLabel *seller = nullptr;
};
2021-03-23 12:34:34 +00:00
2021-03-26 13:05:31 +00:00
const auto cover = layout->add(object_ptr<RpWidget>(layout));
const auto state = cover->lifetime().make_state<State>();
state->title = CreateChild<FlatLabel>(
cover,
_invoice.cover.title,
st::paymentsTitle);
state->description = CreateChild<FlatLabel>(
cover,
_invoice.cover.description,
st::paymentsDescription);
state->seller = CreateChild<FlatLabel>(
cover,
_invoice.cover.seller,
st::paymentsSeller);
cover->paintRequest(
) | rpl::start_with_next([=](QRect clip) {
if (state->thumbnail.isNull()) {
return;
}
const auto &padding = st::paymentsCoverPadding;
const auto thumbnailSkip = st::paymentsThumbnailSize.width()
+ st::paymentsThumbnailSkip;
const auto left = padding.left();
const auto top = padding.top();
const auto rect = QRect(
QPoint(left, top),
state->thumbnail.size() / state->thumbnail.devicePixelRatio());
if (rect.intersects(clip)) {
QPainter(cover).drawImage(rect, state->thumbnail);
}
}, cover->lifetime());
rpl::combine(
cover->widthValue(),
_thumbnails.events_starting_with_copy(_invoice.cover.thumbnail)
) | rpl::start_with_next([=](int width, QImage &&thumbnail) {
const auto &padding = st::paymentsCoverPadding;
const auto thumbnailSkip = st::paymentsThumbnailSize.width()
+ st::paymentsThumbnailSkip;
const auto left = padding.left()
+ (thumbnail.isNull() ? 0 : thumbnailSkip);
const auto available = width
- padding.left()
- padding.right()
- (thumbnail.isNull() ? 0 : thumbnailSkip);
state->title->resizeToNaturalWidth(available);
state->title->moveToLeft(
left,
padding.top() + st::paymentsTitleTop);
state->description->resizeToNaturalWidth(available);
state->description->moveToLeft(
left,
(state->title->y()
+ state->title->height()
+ st::paymentsDescriptionTop));
state->seller->resizeToNaturalWidth(available);
state->seller->moveToLeft(
left,
(state->description->y()
+ state->description->height()
+ st::paymentsSellerTop));
const auto thumbnailHeight = padding.top()
+ (thumbnail.isNull()
? 0
: int(thumbnail.height() / thumbnail.devicePixelRatio()))
+ padding.bottom();
const auto height = state->seller->y()
+ state->seller->height()
+ padding.bottom();
cover->resize(width, std::max(thumbnailHeight, height));
state->thumbnail = std::move(thumbnail);
cover->update();
}, cover->lifetime());
}
2021-03-23 12:34:34 +00:00
2021-03-26 13:05:31 +00:00
void FormSummary::setupPrices(not_null<VerticalLayout*> layout) {
Settings::AddSkip(layout, st::paymentsPricesTopSkip);
const auto add = [&](
const QString &label,
int64 amount,
bool full = false) {
const auto &st = full
? st::paymentsFullPriceAmount
: st::paymentsPriceAmount;
const auto right = CreateChild<FlatLabel>(
layout.get(),
formatAmount(amount),
st);
const auto &padding = st::paymentsPricePadding;
const auto left = layout->add(
object_ptr<FlatLabel>(
layout,
label,
(full
? st::paymentsFullPriceLabel
: st::paymentsPriceLabel)),
style::margins(
padding.left(),
padding.top(),
(padding.right()
+ right->naturalWidth()
+ 2 * st.style.font->spacew),
padding.bottom()));
rpl::combine(
left->topValue(),
layout->widthValue()
) | rpl::start_with_next([=](int top, int width) {
right->moveToRight(st::paymentsPricePadding.right(), top, width);
}, right->lifetime());
};
for (const auto &price : _invoice.prices) {
2021-03-26 13:05:31 +00:00
add(price.label, price.price);
}
const auto selected = ranges::find(
_options.list,
_options.selectedId,
&ShippingOption::id);
if (selected != end(_options.list)) {
for (const auto &price : selected->prices) {
2021-03-26 13:05:31 +00:00
add(price.label, price.price);
}
}
2021-03-26 13:05:31 +00:00
add(tr::lng_payments_total_label(tr::now), computeTotalAmount(), true);
Settings::AddSkip(layout, st::paymentsPricesBottomSkip);
}
void FormSummary::setupSections(not_null<VerticalLayout*> layout) {
Settings::AddSkip(layout, st::paymentsSectionsTopSkip);
const auto add = [&](
rpl::producer<QString> title,
const QString &label,
const style::icon *icon,
Fn<void()> handler) {
Settings::AddButtonWithLabel(
layout,
std::move(title),
rpl::single(label),
st::paymentsSectionButton,
icon
)->addClickHandler(std::move(handler));
};
add(
tr::lng_payments_payment_method(),
_method.title,
&st::paymentsIconPaymentMethod,
[=] { _delegate->panelEditPaymentMethod(); });
if (_invoice.isShippingAddressRequested) {
auto list = QStringList();
const auto push = [&](const QString &value) {
if (!value.isEmpty()) {
list.push_back(value);
}
};
push(_information.shippingAddress.address1);
push(_information.shippingAddress.address2);
push(_information.shippingAddress.city);
push(_information.shippingAddress.state);
push(_information.shippingAddress.countryIso2);
push(_information.shippingAddress.postcode);
2021-03-26 13:05:31 +00:00
add(
tr::lng_payments_shipping_address(),
list.join(", "),
&st::paymentsIconShippingAddress,
[=] { _delegate->panelEditShippingInformation(); });
}
if (!_options.list.empty()) {
2021-03-26 13:05:31 +00:00
const auto selected = ranges::find(
_options.list,
_options.selectedId,
&ShippingOption::id);
add(
tr::lng_payments_shipping_method(),
(selected != end(_options.list)) ? selected->title : QString(),
&st::paymentsIconShippingMethod,
[=] { _delegate->panelChooseShippingOption(); });
}
if (_invoice.isNameRequested) {
2021-03-26 13:05:31 +00:00
add(
tr::lng_payments_info_name(),
_information.name,
&st::paymentsIconName,
[=] { _delegate->panelEditName(); });
}
if (_invoice.isEmailRequested) {
2021-03-26 13:05:31 +00:00
add(
tr::lng_payments_info_email(),
_information.email,
&st::paymentsIconEmail,
[=] { _delegate->panelEditEmail(); });
}
if (_invoice.isPhoneRequested) {
2021-03-26 13:05:31 +00:00
add(
tr::lng_payments_info_phone(),
_information.phone,
&st::paymentsIconPhone,
[=] { _delegate->panelEditPhone(); });
}
2021-03-26 13:05:31 +00:00
Settings::AddSkip(layout, st::paymentsSectionsTopSkip);
}
not_null<RpWidget*> FormSummary::setupContent() {
const auto inner = _scroll->setOwnedWidget(
object_ptr<VerticalLayout>(this));
_scroll->widthValue(
) | rpl::start_with_next([=](int width) {
inner->resizeToWidth(width);
}, inner->lifetime());
setupCover(inner);
if (_invoice) {
Settings::AddDivider(inner);
setupPrices(inner);
Settings::AddDivider(inner);
setupSections(inner);
}
2021-03-23 12:34:34 +00:00
return inner;
}
void FormSummary::resizeEvent(QResizeEvent *e) {
updateControlsGeometry();
}
void FormSummary::updateControlsGeometry() {
const auto submitTop = height() - _submit->height();
_scroll->setGeometry(0, 0, width(), submitTop);
_topShadow->resizeToWidth(width());
_topShadow->moveToLeft(0, 0);
_bottomShadow->resizeToWidth(width());
_bottomShadow->moveToLeft(0, submitTop - st::lineWidth);
_submit->setFullWidth(width());
_submit->moveToLeft(0, submitTop);
_scroll->updateBars();
}
} // namespace Payments::Ui