Improve checkout main page design.
BIN
Telegram/Resources/icons/payments/payment_address.png
Normal file
After Width: | Height: | Size: 802 B |
BIN
Telegram/Resources/icons/payments/payment_address@2x.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Telegram/Resources/icons/payments/payment_address@3x.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
Telegram/Resources/icons/payments/payment_card.png
Normal file
After Width: | Height: | Size: 357 B |
BIN
Telegram/Resources/icons/payments/payment_card@2x.png
Normal file
After Width: | Height: | Size: 560 B |
BIN
Telegram/Resources/icons/payments/payment_card@3x.png
Normal file
After Width: | Height: | Size: 985 B |
BIN
Telegram/Resources/icons/payments/payment_email.png
Normal file
After Width: | Height: | Size: 949 B |
BIN
Telegram/Resources/icons/payments/payment_email@2x.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Telegram/Resources/icons/payments/payment_email@3x.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Telegram/Resources/icons/payments/payment_name.png
Normal file
After Width: | Height: | Size: 473 B |
BIN
Telegram/Resources/icons/payments/payment_name@2x.png
Normal file
After Width: | Height: | Size: 884 B |
BIN
Telegram/Resources/icons/payments/payment_name@3x.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
Telegram/Resources/icons/payments/payment_phone.png
Normal file
After Width: | Height: | Size: 711 B |
BIN
Telegram/Resources/icons/payments/payment_phone@2x.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
Telegram/Resources/icons/payments/payment_phone@3x.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
Telegram/Resources/icons/payments/payment_shipping.png
Normal file
After Width: | Height: | Size: 526 B |
BIN
Telegram/Resources/icons/payments/payment_shipping@2x.png
Normal file
After Width: | Height: | Size: 1022 B |
BIN
Telegram/Resources/icons/payments/payment_shipping@3x.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
@ -1865,24 +1865,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_payments_pay_amount" = "Pay {amount}";
|
"lng_payments_pay_amount" = "Pay {amount}";
|
||||||
"lng_payments_payment_method" = "Payment Method";
|
"lng_payments_payment_method" = "Payment Method";
|
||||||
"lng_payments_new_card" = "New Card...";
|
"lng_payments_new_card" = "New Card...";
|
||||||
"lng_payments_payment_method_ph" = "Enter your card details";
|
"lng_payments_shipping_address" = "Shipping Address";
|
||||||
"lng_payments_shipping_address" = "Shipping Information";
|
"lng_payments_receiver_information" = "Receiver";
|
||||||
"lng_payments_shipping_address_ph" = "Enter your shipping information";
|
"lng_payments_address_street1" = "Address 1";
|
||||||
|
"lng_payments_address_street2" = "Address 2";
|
||||||
|
"lng_payments_address_city" = "City";
|
||||||
|
"lng_payments_address_state" = "State";
|
||||||
|
"lng_payments_address_country" = "Country";
|
||||||
|
"lng_payments_address_postcode" = "Postcode";
|
||||||
|
|
||||||
"lng_payments_shipping_method" = "Shipping Method";
|
"lng_payments_shipping_method" = "Shipping Method";
|
||||||
"lng_payments_shipping_method_ph" = "Choose your shipping method";
|
|
||||||
"lng_payments_info_name" = "Name";
|
"lng_payments_info_name" = "Name";
|
||||||
"lng_payments_info_name_ph" = "Enter your name";
|
|
||||||
"lng_payments_info_email" = "Email";
|
"lng_payments_info_email" = "Email";
|
||||||
"lng_payments_info_email_ph" = "Enter your email";
|
|
||||||
"lng_payments_info_phone" = "Phone";
|
"lng_payments_info_phone" = "Phone";
|
||||||
"lng_payments_info_phone_ph" = "Enter your phone number";
|
|
||||||
"lng_payments_shipping_address_title" = "Shipping Address";
|
"lng_payments_shipping_address_title" = "Shipping Address";
|
||||||
"lng_payments_save_shipping_about" = "You can save your shipping information for future use.";
|
"lng_payments_save_shipping_about" = "You can save your shipping information for future use.";
|
||||||
"lng_payments_payment_card" = "Payment Card";
|
"lng_payments_card_title" = "New Card";
|
||||||
"lng_payments_cardholder_title" = "Cardholder";
|
"lng_payments_card_number" = "Card Number";
|
||||||
"lng_payments_cardholder_about" = "Cardholder Name";
|
"lng_payments_card_holder" = "Cardholder name";
|
||||||
"lng_payments_billing_address" = "Billing Address";
|
"lng_payments_billing_address" = "Billing Information";
|
||||||
"lng_payments_zip_code" = "Zip Code";
|
"lng_payments_billing_country" = "Country";
|
||||||
|
"lng_payments_billing_zip_code" = "Zip Code";
|
||||||
"lng_payments_save_payment_about" = "You can save your payment information for future use.";
|
"lng_payments_save_payment_about" = "You can save your payment information for future use.";
|
||||||
"lng_payments_save_information" = "Save Information";
|
"lng_payments_save_information" = "Save Information";
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "storage/storage_domain.h"
|
#include "storage/storage_domain.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
|
#include "data/data_user.h" // UserData::isBot.
|
||||||
#include "core/local_url_handlers.h" // TryConvertUrlToLocal.
|
#include "core/local_url_handlers.h" // TryConvertUrlToLocal.
|
||||||
#include "core/file_utilities.h" // File::OpenUrl.
|
#include "core/file_utilities.h" // File::OpenUrl.
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
@ -105,6 +106,8 @@ void CheckoutProcess::handleFormUpdate(const FormUpdate &update) {
|
|||||||
if (!_initialSilentValidation) {
|
if (!_initialSilentValidation) {
|
||||||
showForm();
|
showForm();
|
||||||
}
|
}
|
||||||
|
}, [&](const ThumbnailUpdated &data) {
|
||||||
|
_panel->updateFormThumbnail(data.thumbnail);
|
||||||
}, [&](const ValidateFinished &) {
|
}, [&](const ValidateFinished &) {
|
||||||
if (_initialSilentValidation) {
|
if (_initialSilentValidation) {
|
||||||
_initialSilentValidation = false;
|
_initialSilentValidation = false;
|
||||||
@ -114,16 +117,16 @@ void CheckoutProcess::handleFormUpdate(const FormUpdate &update) {
|
|||||||
_submitState = SubmitState::Validated;
|
_submitState = SubmitState::Validated;
|
||||||
panelSubmit();
|
panelSubmit();
|
||||||
}
|
}
|
||||||
}, [&](const PaymentMethodUpdate&) {
|
}, [&](const PaymentMethodUpdate &) {
|
||||||
showForm();
|
showForm();
|
||||||
}, [&](const VerificationNeeded &info) {
|
}, [&](const VerificationNeeded &data) {
|
||||||
if (!_panel->showWebview(info.url, false)) {
|
if (!_panel->showWebview(data.url, false)) {
|
||||||
File::OpenUrl(info.url);
|
File::OpenUrl(data.url);
|
||||||
panelCloseSure();
|
panelCloseSure();
|
||||||
}
|
}
|
||||||
}, [&](const PaymentFinished &result) {
|
}, [&](const PaymentFinished &data) {
|
||||||
const auto weak = base::make_weak(this);
|
const auto weak = base::make_weak(this);
|
||||||
_session->api().applyUpdates(result.updates);
|
_session->api().applyUpdates(data.updates);
|
||||||
if (weak) {
|
if (weak) {
|
||||||
panelCloseSure();
|
panelCloseSure();
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
|
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "apiwrap.h"
|
#include "data/data_media_types.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "data/data_photo.h"
|
||||||
|
#include "data/data_photo_media.h"
|
||||||
|
#include "data/data_file_origin.h"
|
||||||
|
#include "history/history_item.h"
|
||||||
#include "stripe/stripe_api_client.h"
|
#include "stripe/stripe_api_client.h"
|
||||||
#include "stripe/stripe_error.h"
|
#include "stripe/stripe_error.h"
|
||||||
#include "stripe/stripe_token.h"
|
#include "stripe/stripe_token.h"
|
||||||
|
#include "ui/image/image.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "styles/style_payments.h" // paymentsThumbnailSize.
|
||||||
|
|
||||||
#include <QtCore/QJsonDocument>
|
#include <QtCore/QJsonDocument>
|
||||||
#include <QtCore/QJsonObject>
|
#include <QtCore/QJsonObject>
|
||||||
@ -82,15 +90,110 @@ namespace {
|
|||||||
Form::Form(not_null<Main::Session*> session, FullMsgId itemId)
|
Form::Form(not_null<Main::Session*> session, FullMsgId itemId)
|
||||||
: _session(session)
|
: _session(session)
|
||||||
, _api(&_session->mtp())
|
, _api(&_session->mtp())
|
||||||
, _msgId(itemId.msg) {
|
, _msgId(itemId) {
|
||||||
|
fillInvoiceFromMessage();
|
||||||
requestForm();
|
requestForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
Form::~Form() = default;
|
Form::~Form() = default;
|
||||||
|
|
||||||
|
void Form::fillInvoiceFromMessage() {
|
||||||
|
if (const auto item = _session->data().message(_msgId)) {
|
||||||
|
if (const auto media = item->media()) {
|
||||||
|
if (const auto invoice = media->invoice()) {
|
||||||
|
_invoice.cover = Ui::Cover{
|
||||||
|
.title = invoice->title,
|
||||||
|
.description = invoice->description,
|
||||||
|
};
|
||||||
|
if (const auto photo = invoice->photo) {
|
||||||
|
loadThumbnail(photo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Form::loadThumbnail(not_null<PhotoData*> photo) {
|
||||||
|
Expects(!_thumbnailLoadProcess);
|
||||||
|
|
||||||
|
auto view = photo->createMediaView();
|
||||||
|
if (auto good = prepareGoodThumbnail(view); !good.isNull()) {
|
||||||
|
_invoice.cover.thumbnail = std::move(good);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_thumbnailLoadProcess = std::make_unique<ThumbnailLoadProcess>();
|
||||||
|
if (auto blurred = prepareBlurredThumbnail(view); !blurred.isNull()) {
|
||||||
|
_invoice.cover.thumbnail = std::move(blurred);
|
||||||
|
_thumbnailLoadProcess->blurredSet = true;
|
||||||
|
} else {
|
||||||
|
_invoice.cover.thumbnail = prepareEmptyThumbnail();
|
||||||
|
}
|
||||||
|
_thumbnailLoadProcess->view = std::move(view);
|
||||||
|
photo->load(Data::PhotoSize::Thumbnail, _msgId);
|
||||||
|
_session->downloaderTaskFinished(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
const auto &view = _thumbnailLoadProcess->view;
|
||||||
|
if (auto good = prepareGoodThumbnail(view); !good.isNull()) {
|
||||||
|
_invoice.cover.thumbnail = std::move(good);
|
||||||
|
_thumbnailLoadProcess = nullptr;
|
||||||
|
} else if (_thumbnailLoadProcess->blurredSet) {
|
||||||
|
return;
|
||||||
|
} else if (auto blurred = prepareBlurredThumbnail(view)
|
||||||
|
; !blurred.isNull()) {
|
||||||
|
_invoice.cover.thumbnail = std::move(blurred);
|
||||||
|
_thumbnailLoadProcess->blurredSet = true;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_updates.fire(ThumbnailUpdated{ _invoice.cover.thumbnail });
|
||||||
|
}, _thumbnailLoadProcess->lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage Form::prepareGoodThumbnail(
|
||||||
|
const std::shared_ptr<Data::PhotoMedia> &view) const {
|
||||||
|
using Size = Data::PhotoSize;
|
||||||
|
if (const auto large = view->image(Size::Large)) {
|
||||||
|
return prepareThumbnail(large);
|
||||||
|
} else if (const auto thumbnail = view->image(Size::Thumbnail)) {
|
||||||
|
return prepareThumbnail(thumbnail);
|
||||||
|
}
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage Form::prepareBlurredThumbnail(
|
||||||
|
const std::shared_ptr<Data::PhotoMedia> &view) const {
|
||||||
|
if (const auto small = view->image(Data::PhotoSize::Small)) {
|
||||||
|
return prepareThumbnail(small, true);
|
||||||
|
} else if (const auto blurred = view->thumbnailInline()) {
|
||||||
|
return prepareThumbnail(blurred, true);
|
||||||
|
}
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage Form::prepareThumbnail(
|
||||||
|
not_null<const Image*> image,
|
||||||
|
bool blurred) const {
|
||||||
|
auto result = image->original().scaled(
|
||||||
|
st::paymentsThumbnailSize * cIntRetinaFactor(),
|
||||||
|
Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
Images::prepareRound(result, ImageRoundRadius::Large);
|
||||||
|
result.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage Form::prepareEmptyThumbnail() const {
|
||||||
|
auto result = QImage(
|
||||||
|
st::paymentsThumbnailSize * cIntRetinaFactor(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
result.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
result.fill(Qt::transparent);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void Form::requestForm() {
|
void Form::requestForm() {
|
||||||
_api.request(MTPpayments_GetPaymentForm(
|
_api.request(MTPpayments_GetPaymentForm(
|
||||||
MTP_int(_msgId)
|
MTP_int(_msgId.msg)
|
||||||
)).done([=](const MTPpayments_PaymentForm &result) {
|
)).done([=](const MTPpayments_PaymentForm &result) {
|
||||||
result.match([&](const auto &data) {
|
result.match([&](const auto &data) {
|
||||||
processForm(data);
|
processForm(data);
|
||||||
@ -123,6 +226,8 @@ void Form::processForm(const MTPDpayments_paymentForm &data) {
|
|||||||
|
|
||||||
void Form::processInvoice(const MTPDinvoice &data) {
|
void Form::processInvoice(const MTPDinvoice &data) {
|
||||||
_invoice = Ui::Invoice{
|
_invoice = Ui::Invoice{
|
||||||
|
.cover = std::move(_invoice.cover),
|
||||||
|
|
||||||
.prices = ParsePrices(data.vprices()),
|
.prices = ParsePrices(data.vprices()),
|
||||||
.currency = qs(data.vcurrency()),
|
.currency = qs(data.vcurrency()),
|
||||||
|
|
||||||
@ -154,6 +259,11 @@ void Form::processDetails(const MTPDpayments_paymentForm &data) {
|
|||||||
.canSaveCredentials = data.is_can_save_credentials(),
|
.canSaveCredentials = data.is_can_save_credentials(),
|
||||||
.passwordMissing = data.is_password_missing(),
|
.passwordMissing = data.is_password_missing(),
|
||||||
};
|
};
|
||||||
|
if (_details.botId) {
|
||||||
|
if (const auto bot = _session->data().userLoaded(_details.botId)) {
|
||||||
|
_invoice.cover.seller = bot->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Form::processSavedInformation(const MTPDpaymentRequestedInfo &data) {
|
void Form::processSavedInformation(const MTPDpaymentRequestedInfo &data) {
|
||||||
@ -240,7 +350,7 @@ void Form::submit() {
|
|||||||
| (_shippingOptions.selectedId.isEmpty()
|
| (_shippingOptions.selectedId.isEmpty()
|
||||||
? Flag(0)
|
? Flag(0)
|
||||||
: Flag::f_shipping_option_id)),
|
: Flag::f_shipping_option_id)),
|
||||||
MTP_int(_msgId),
|
MTP_int(_msgId.msg),
|
||||||
MTP_string(_requestedInformationId),
|
MTP_string(_requestedInformationId),
|
||||||
MTP_string(_shippingOptions.selectedId),
|
MTP_string(_shippingOptions.selectedId),
|
||||||
MTP_inputPaymentCredentials(
|
MTP_inputPaymentCredentials(
|
||||||
@ -267,7 +377,7 @@ void Form::validateInformation(const Ui::RequestedInformation &information) {
|
|||||||
_validatedInformation = information;
|
_validatedInformation = information;
|
||||||
_validateRequestId = _api.request(MTPpayments_ValidateRequestedInfo(
|
_validateRequestId = _api.request(MTPpayments_ValidateRequestedInfo(
|
||||||
MTP_flags(0), // #TODO payments save information
|
MTP_flags(0), // #TODO payments save information
|
||||||
MTP_int(_msgId),
|
MTP_int(_msgId.msg),
|
||||||
Serialize(information)
|
Serialize(information)
|
||||||
)).done([=](const MTPpayments_ValidatedRequestedInfo &result) {
|
)).done([=](const MTPpayments_ValidatedRequestedInfo &result) {
|
||||||
_validateRequestId = 0;
|
_validateRequestId = 0;
|
||||||
|
@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
|
|
||||||
|
class Image;
|
||||||
|
|
||||||
namespace Stripe {
|
namespace Stripe {
|
||||||
class APIClient;
|
class APIClient;
|
||||||
} // namespace Stripe
|
} // namespace Stripe
|
||||||
@ -19,6 +21,10 @@ namespace Main {
|
|||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
class PhotoMedia;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
namespace Payments {
|
namespace Payments {
|
||||||
|
|
||||||
struct FormDetails {
|
struct FormDetails {
|
||||||
@ -38,6 +44,12 @@ struct FormDetails {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ThumbnailLoadProcess {
|
||||||
|
std::shared_ptr<Data::PhotoMedia> view;
|
||||||
|
bool blurredSet = false;
|
||||||
|
rpl::lifetime lifetime;
|
||||||
|
};
|
||||||
|
|
||||||
struct SavedCredentials {
|
struct SavedCredentials {
|
||||||
QString id;
|
QString id;
|
||||||
QString title;
|
QString title;
|
||||||
@ -88,6 +100,9 @@ struct PaymentMethod {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct FormReady {};
|
struct FormReady {};
|
||||||
|
struct ThumbnailUpdated {
|
||||||
|
QImage thumbnail;
|
||||||
|
};
|
||||||
struct ValidateFinished {};
|
struct ValidateFinished {};
|
||||||
struct PaymentMethodUpdate {};
|
struct PaymentMethodUpdate {};
|
||||||
struct VerificationNeeded {
|
struct VerificationNeeded {
|
||||||
@ -109,6 +124,7 @@ struct Error {
|
|||||||
|
|
||||||
struct FormUpdate : std::variant<
|
struct FormUpdate : std::variant<
|
||||||
FormReady,
|
FormReady,
|
||||||
|
ThumbnailUpdated,
|
||||||
ValidateFinished,
|
ValidateFinished,
|
||||||
PaymentMethodUpdate,
|
PaymentMethodUpdate,
|
||||||
VerificationNeeded,
|
VerificationNeeded,
|
||||||
@ -149,6 +165,18 @@ public:
|
|||||||
void submit();
|
void submit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void fillInvoiceFromMessage();
|
||||||
|
|
||||||
|
void loadThumbnail(not_null<PhotoData*> photo);
|
||||||
|
[[nodiscard]] QImage prepareGoodThumbnail(
|
||||||
|
const std::shared_ptr<Data::PhotoMedia> &view) const;
|
||||||
|
[[nodiscard]] QImage prepareBlurredThumbnail(
|
||||||
|
const std::shared_ptr<Data::PhotoMedia> &view) const;
|
||||||
|
[[nodiscard]] QImage prepareThumbnail(
|
||||||
|
not_null<const Image*> image,
|
||||||
|
bool blurred = false) const;
|
||||||
|
[[nodiscard]] QImage prepareEmptyThumbnail() const;
|
||||||
|
|
||||||
void requestForm();
|
void requestForm();
|
||||||
void processForm(const MTPDpayments_paymentForm &data);
|
void processForm(const MTPDpayments_paymentForm &data);
|
||||||
void processInvoice(const MTPDinvoice &data);
|
void processInvoice(const MTPDinvoice &data);
|
||||||
@ -167,9 +195,10 @@ private:
|
|||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
MsgId _msgId = 0;
|
FullMsgId _msgId;
|
||||||
|
|
||||||
Ui::Invoice _invoice;
|
Ui::Invoice _invoice;
|
||||||
|
std::unique_ptr<ThumbnailLoadProcess> _thumbnailLoadProcess;
|
||||||
FormDetails _details;
|
FormDetails _details;
|
||||||
Ui::RequestedInformation _savedInformation;
|
Ui::RequestedInformation _savedInformation;
|
||||||
PaymentMethod _paymentMethod;
|
PaymentMethod _paymentMethod;
|
||||||
|
@ -7,12 +7,52 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
*/
|
*/
|
||||||
using "ui/basic.style";
|
using "ui/basic.style";
|
||||||
|
|
||||||
using "passport/passport.style";
|
using "info/info.style";
|
||||||
|
|
||||||
paymentsFormPricePadding: margins(22px, 7px, 22px, 6px);
|
paymentsPanelSubmit: RoundButton(defaultActiveButton) {
|
||||||
paymentsPanelSubmit: RoundButton(passportPasswordSubmit) {
|
|
||||||
width: 0px;
|
width: 0px;
|
||||||
height: 49px;
|
height: 49px;
|
||||||
padding: margins(0px, -3px, 0px, 0px);
|
padding: margins(0px, -3px, 0px, 0px);
|
||||||
textTop: 16px;
|
textTop: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
paymentsCoverPadding: margins(26px, 0px, 26px, 13px);
|
||||||
|
paymentsDescription: FlatLabel(defaultFlatLabel) {
|
||||||
|
minWidth: 160px;
|
||||||
|
textFg: windowFg;
|
||||||
|
}
|
||||||
|
paymentsTitle: FlatLabel(paymentsDescription) {
|
||||||
|
style: semiboldTextStyle;
|
||||||
|
}
|
||||||
|
paymentsSeller: FlatLabel(paymentsDescription) {
|
||||||
|
textFg: windowSubTextFg;
|
||||||
|
}
|
||||||
|
paymentsPriceLabel: paymentsDescription;
|
||||||
|
paymentsPriceAmount: defaultFlatLabel;
|
||||||
|
paymentsFullPriceLabel: paymentsTitle;
|
||||||
|
paymentsFullPriceAmount: FlatLabel(defaultFlatLabel) {
|
||||||
|
style: semiboldTextStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentsTitleTop: 0px;
|
||||||
|
paymentsDescriptionTop: 3px;
|
||||||
|
paymentsSellerTop: 4px;
|
||||||
|
|
||||||
|
paymentsThumbnailSize: size(80px, 80px);
|
||||||
|
paymentsThumbnailSkip: 18px;
|
||||||
|
|
||||||
|
paymentsPricesTopSkip: 12px;
|
||||||
|
paymentsPricesBottomSkip: 13px;
|
||||||
|
paymentsPricePadding: margins(28px, 6px, 28px, 5px);
|
||||||
|
|
||||||
|
paymentsSectionsTopSkip: 11px;
|
||||||
|
paymentsSectionButton: SettingsButton(infoProfileButton) {
|
||||||
|
padding: margins(68px, 11px, 14px, 9px);
|
||||||
|
}
|
||||||
|
|
||||||
|
paymentsIconPaymentMethod: icon {{ "payments/payment_card", menuIconFg }};
|
||||||
|
paymentsIconShippingAddress: icon {{ "payments/payment_address", menuIconFg }};
|
||||||
|
paymentsIconName: icon {{ "payments/payment_name", menuIconFg }};
|
||||||
|
paymentsIconEmail: icon {{ "payments/payment_email", menuIconFg }};
|
||||||
|
paymentsIconPhone: icon {{ "payments/payment_phone", menuIconFg }};
|
||||||
|
paymentsIconShippingMethod: icon {{ "payments/payment_shipping", menuIconFg }};
|
||||||
|
@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "payments/ui/payments_form_summary.h"
|
#include "payments/ui/payments_form_summary.h"
|
||||||
|
|
||||||
#include "payments/ui/payments_panel_delegate.h"
|
#include "payments/ui/payments_panel_delegate.h"
|
||||||
#include "passport/ui/passport_form_row.h"
|
#include "settings/settings_common.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
@ -22,7 +22,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
namespace Payments::Ui {
|
namespace Payments::Ui {
|
||||||
|
|
||||||
using namespace ::Ui;
|
using namespace ::Ui;
|
||||||
using namespace Passport::Ui;
|
|
||||||
|
|
||||||
class PanelDelegate;
|
class PanelDelegate;
|
||||||
|
|
||||||
@ -45,16 +44,24 @@ FormSummary::FormSummary(
|
|||||||
this,
|
this,
|
||||||
tr::lng_payments_pay_amount(
|
tr::lng_payments_pay_amount(
|
||||||
lt_amount,
|
lt_amount,
|
||||||
rpl::single(computeTotalAmount())),
|
rpl::single(formatAmount(computeTotalAmount()))),
|
||||||
st::paymentsPanelSubmit) {
|
st::paymentsPanelSubmit) {
|
||||||
setupControls();
|
setupControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FormSummary::computeAmount(int64 amount) const {
|
void FormSummary::updateThumbnail(const QImage &thumbnail) {
|
||||||
return FillAmountAndCurrency(amount, _invoice.currency);
|
_invoice.cover.thumbnail = thumbnail;
|
||||||
|
_thumbnails.fire_copy(thumbnail);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FormSummary::computeTotalAmount() const {
|
QString FormSummary::formatAmount(int64 amount) const {
|
||||||
|
const auto base = FillAmountAndCurrency(
|
||||||
|
std::abs(amount),
|
||||||
|
_invoice.currency);
|
||||||
|
return (amount > 0) ? base : (QString::fromUtf8("\xe2\x88\x92") + base);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 FormSummary::computeTotalAmount() const {
|
||||||
const auto total = ranges::accumulate(
|
const auto total = ranges::accumulate(
|
||||||
_invoice.prices,
|
_invoice.prices,
|
||||||
int64(0),
|
int64(0),
|
||||||
@ -71,7 +78,7 @@ QString FormSummary::computeTotalAmount() const {
|
|||||||
std::plus<>(),
|
std::plus<>(),
|
||||||
&LabeledPrice::price)
|
&LabeledPrice::price)
|
||||||
: int64(0);
|
: int64(0);
|
||||||
return computeAmount(total + shipping);
|
return total + shipping;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormSummary::setupControls() {
|
void FormSummary::setupControls() {
|
||||||
@ -92,22 +99,125 @@ void FormSummary::setupControls() {
|
|||||||
_1 + _2 < _3));
|
_1 + _2 < _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<Ui::RpWidget*> FormSummary::setupContent() {
|
void FormSummary::setupCover(not_null<VerticalLayout*> layout) {
|
||||||
const auto inner = _scroll->setOwnedWidget(
|
struct State {
|
||||||
object_ptr<Ui::VerticalLayout>(this));
|
QImage thumbnail;
|
||||||
|
FlatLabel *title = nullptr;
|
||||||
|
FlatLabel *description = nullptr;
|
||||||
|
FlatLabel *seller = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
_scroll->widthValue(
|
const auto cover = layout->add(object_ptr<RpWidget>(layout));
|
||||||
) | rpl::start_with_next([=](int width) {
|
const auto state = cover->lifetime().make_state<State>();
|
||||||
inner->resizeToWidth(width);
|
state->title = CreateChild<FlatLabel>(
|
||||||
}, inner->lifetime());
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
for (const auto &price : _invoice.prices) {
|
||||||
inner->add(
|
add(price.label, price.price);
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
inner,
|
|
||||||
price.label + ": " + computeAmount(price.price),
|
|
||||||
st::passportFormPolicy),
|
|
||||||
st::paymentsFormPricePadding);
|
|
||||||
}
|
}
|
||||||
const auto selected = ranges::find(
|
const auto selected = ranges::find(
|
||||||
_options.list,
|
_options.list,
|
||||||
@ -115,44 +225,35 @@ not_null<Ui::RpWidget*> FormSummary::setupContent() {
|
|||||||
&ShippingOption::id);
|
&ShippingOption::id);
|
||||||
if (selected != end(_options.list)) {
|
if (selected != end(_options.list)) {
|
||||||
for (const auto &price : selected->prices) {
|
for (const auto &price : selected->prices) {
|
||||||
inner->add(
|
add(price.label, price.price);
|
||||||
object_ptr<Ui::FlatLabel>(
|
|
||||||
inner,
|
|
||||||
price.label + ": " + computeAmount(price.price),
|
|
||||||
st::passportFormPolicy),
|
|
||||||
st::paymentsFormPricePadding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inner->add(
|
add(tr::lng_payments_total_label(tr::now), computeTotalAmount(), true);
|
||||||
object_ptr<Ui::FlatLabel>(
|
Settings::AddSkip(layout, st::paymentsPricesBottomSkip);
|
||||||
inner,
|
}
|
||||||
"Total: " + computeTotalAmount(),
|
|
||||||
st::passportFormHeader),
|
|
||||||
st::passportFormHeaderPadding);
|
|
||||||
|
|
||||||
inner->add(
|
void FormSummary::setupSections(not_null<VerticalLayout*> layout) {
|
||||||
object_ptr<Ui::BoxContentDivider>(
|
Settings::AddSkip(layout, st::paymentsSectionsTopSkip);
|
||||||
inner,
|
|
||||||
st::passportFormDividerHeight),
|
|
||||||
{ 0, 0, 0, st::passportFormHeaderPadding.top() });
|
|
||||||
|
|
||||||
const auto method = inner->add(object_ptr<FormRow>(inner));
|
const auto add = [&](
|
||||||
method->addClickHandler([=] {
|
rpl::producer<QString> title,
|
||||||
_delegate->panelEditPaymentMethod();
|
const QString &label,
|
||||||
});
|
const style::icon *icon,
|
||||||
method->updateContent(
|
Fn<void()> handler) {
|
||||||
tr::lng_payments_payment_method(tr::now),
|
Settings::AddButtonWithLabel(
|
||||||
(_method.ready
|
layout,
|
||||||
? _method.title
|
std::move(title),
|
||||||
: tr::lng_payments_payment_method_ph(tr::now)),
|
rpl::single(label),
|
||||||
_method.ready,
|
st::paymentsSectionButton,
|
||||||
false,
|
icon
|
||||||
anim::type::instant);
|
)->addClickHandler(std::move(handler));
|
||||||
|
};
|
||||||
|
add(
|
||||||
|
tr::lng_payments_payment_method(),
|
||||||
|
_method.title,
|
||||||
|
&st::paymentsIconPaymentMethod,
|
||||||
|
[=] { _delegate->panelEditPaymentMethod(); });
|
||||||
if (_invoice.isShippingAddressRequested) {
|
if (_invoice.isShippingAddressRequested) {
|
||||||
const auto info = inner->add(object_ptr<FormRow>(inner));
|
|
||||||
info->addClickHandler([=] {
|
|
||||||
_delegate->panelEditShippingInformation();
|
|
||||||
});
|
|
||||||
auto list = QStringList();
|
auto list = QStringList();
|
||||||
const auto push = [&](const QString &value) {
|
const auto push = [&](const QString &value) {
|
||||||
if (!value.isEmpty()) {
|
if (!value.isEmpty()) {
|
||||||
@ -165,65 +266,61 @@ not_null<Ui::RpWidget*> FormSummary::setupContent() {
|
|||||||
push(_information.shippingAddress.state);
|
push(_information.shippingAddress.state);
|
||||||
push(_information.shippingAddress.countryIso2);
|
push(_information.shippingAddress.countryIso2);
|
||||||
push(_information.shippingAddress.postcode);
|
push(_information.shippingAddress.postcode);
|
||||||
info->updateContent(
|
add(
|
||||||
tr::lng_payments_shipping_address(tr::now),
|
tr::lng_payments_shipping_address(),
|
||||||
(list.isEmpty()
|
list.join(", "),
|
||||||
? tr::lng_payments_shipping_address_ph(tr::now)
|
&st::paymentsIconShippingAddress,
|
||||||
: list.join(", ")),
|
[=] { _delegate->panelEditShippingInformation(); });
|
||||||
!list.isEmpty(),
|
|
||||||
false,
|
|
||||||
anim::type::instant);
|
|
||||||
}
|
}
|
||||||
if (!_options.list.empty()) {
|
if (!_options.list.empty()) {
|
||||||
const auto options = inner->add(object_ptr<FormRow>(inner));
|
const auto selected = ranges::find(
|
||||||
options->addClickHandler([=] {
|
_options.list,
|
||||||
_delegate->panelChooseShippingOption();
|
_options.selectedId,
|
||||||
});
|
&ShippingOption::id);
|
||||||
options->updateContent(
|
add(
|
||||||
tr::lng_payments_shipping_method(tr::now),
|
tr::lng_payments_shipping_method(),
|
||||||
(selected != end(_options.list)
|
(selected != end(_options.list)) ? selected->title : QString(),
|
||||||
? selected->title
|
&st::paymentsIconShippingMethod,
|
||||||
: tr::lng_payments_shipping_method_ph(tr::now)),
|
[=] { _delegate->panelChooseShippingOption(); });
|
||||||
(selected != end(_options.list)),
|
|
||||||
false,
|
|
||||||
anim::type::instant);
|
|
||||||
}
|
}
|
||||||
if (_invoice.isNameRequested) {
|
if (_invoice.isNameRequested) {
|
||||||
const auto name = inner->add(object_ptr<FormRow>(inner));
|
add(
|
||||||
name->addClickHandler([=] { _delegate->panelEditName(); });
|
tr::lng_payments_info_name(),
|
||||||
name->updateContent(
|
_information.name,
|
||||||
tr::lng_payments_info_name(tr::now),
|
&st::paymentsIconName,
|
||||||
(_information.name.isEmpty()
|
[=] { _delegate->panelEditName(); });
|
||||||
? tr::lng_payments_info_name_ph(tr::now)
|
|
||||||
: _information.name),
|
|
||||||
!_information.name.isEmpty(),
|
|
||||||
false,
|
|
||||||
anim::type::instant);
|
|
||||||
}
|
}
|
||||||
if (_invoice.isEmailRequested) {
|
if (_invoice.isEmailRequested) {
|
||||||
const auto email = inner->add(object_ptr<FormRow>(inner));
|
add(
|
||||||
email->addClickHandler([=] { _delegate->panelEditEmail(); });
|
tr::lng_payments_info_email(),
|
||||||
email->updateContent(
|
_information.email,
|
||||||
tr::lng_payments_info_email(tr::now),
|
&st::paymentsIconEmail,
|
||||||
(_information.email.isEmpty()
|
[=] { _delegate->panelEditEmail(); });
|
||||||
? tr::lng_payments_info_email_ph(tr::now)
|
|
||||||
: _information.email),
|
|
||||||
!_information.email.isEmpty(),
|
|
||||||
false,
|
|
||||||
anim::type::instant);
|
|
||||||
}
|
}
|
||||||
if (_invoice.isPhoneRequested) {
|
if (_invoice.isPhoneRequested) {
|
||||||
const auto phone = inner->add(object_ptr<FormRow>(inner));
|
add(
|
||||||
phone->addClickHandler([=] { _delegate->panelEditPhone(); });
|
tr::lng_payments_info_phone(),
|
||||||
phone->updateContent(
|
_information.phone,
|
||||||
tr::lng_payments_info_phone(tr::now),
|
&st::paymentsIconPhone,
|
||||||
(_information.phone.isEmpty()
|
[=] { _delegate->panelEditPhone(); });
|
||||||
? tr::lng_payments_info_phone_ph(tr::now)
|
|
||||||
: _information.phone),
|
|
||||||
!_information.phone.isEmpty(),
|
|
||||||
false,
|
|
||||||
anim::type::instant);
|
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
Settings::AddDivider(inner);
|
||||||
|
setupPrices(inner);
|
||||||
|
Settings::AddDivider(inner);
|
||||||
|
setupSections(inner);
|
||||||
|
|
||||||
return inner;
|
return inner;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ namespace Ui {
|
|||||||
class ScrollArea;
|
class ScrollArea;
|
||||||
class FadeShadow;
|
class FadeShadow;
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
class VerticalLayout;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Payments::Ui {
|
namespace Payments::Ui {
|
||||||
@ -33,15 +34,20 @@ public:
|
|||||||
const ShippingOptions &options,
|
const ShippingOptions &options,
|
||||||
not_null<PanelDelegate*> delegate);
|
not_null<PanelDelegate*> delegate);
|
||||||
|
|
||||||
|
void updateThumbnail(const QImage &thumbnail);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
void setupControls();
|
void setupControls();
|
||||||
[[nodiscard]] not_null<Ui::RpWidget*> setupContent();
|
[[nodiscard]] not_null<Ui::RpWidget*> setupContent();
|
||||||
|
void setupCover(not_null<VerticalLayout*> layout);
|
||||||
|
void setupPrices(not_null<VerticalLayout*> layout);
|
||||||
|
void setupSections(not_null<VerticalLayout*> layout);
|
||||||
void updateControlsGeometry();
|
void updateControlsGeometry();
|
||||||
|
|
||||||
[[nodiscard]] QString computeAmount(int64 amount) const;
|
[[nodiscard]] QString formatAmount(int64 amount) const;
|
||||||
[[nodiscard]] QString computeTotalAmount() const;
|
[[nodiscard]] int64 computeTotalAmount() const;
|
||||||
|
|
||||||
const not_null<PanelDelegate*> _delegate;
|
const not_null<PanelDelegate*> _delegate;
|
||||||
Invoice _invoice;
|
Invoice _invoice;
|
||||||
@ -52,6 +58,7 @@ private:
|
|||||||
object_ptr<FadeShadow> _topShadow;
|
object_ptr<FadeShadow> _topShadow;
|
||||||
object_ptr<FadeShadow> _bottomShadow;
|
object_ptr<FadeShadow> _bottomShadow;
|
||||||
object_ptr<RoundButton> _submit;
|
object_ptr<RoundButton> _submit;
|
||||||
|
rpl::event_stream<QImage> _thumbnails;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,17 +52,24 @@ void Panel::showForm(
|
|||||||
const RequestedInformation ¤t,
|
const RequestedInformation ¤t,
|
||||||
const PaymentMethodDetails &method,
|
const PaymentMethodDetails &method,
|
||||||
const ShippingOptions &options) {
|
const ShippingOptions &options) {
|
||||||
_widget->showInner(
|
auto form = base::make_unique_q<FormSummary>(
|
||||||
base::make_unique_q<FormSummary>(
|
_widget.get(),
|
||||||
_widget.get(),
|
invoice,
|
||||||
invoice,
|
current,
|
||||||
current,
|
method,
|
||||||
method,
|
options,
|
||||||
options,
|
_delegate);
|
||||||
_delegate));
|
_weakFormSummary = form.get();
|
||||||
|
_widget->showInner(std::move(form));
|
||||||
_widget->setBackAllowed(false);
|
_widget->setBackAllowed(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Panel::updateFormThumbnail(const QImage &thumbnail) {
|
||||||
|
if (_weakFormSummary) {
|
||||||
|
_weakFormSummary->updateThumbnail(thumbnail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::showEditInformation(
|
void Panel::showEditInformation(
|
||||||
const Invoice &invoice,
|
const Invoice &invoice,
|
||||||
const RequestedInformation ¤t,
|
const RequestedInformation ¤t,
|
||||||
|
@ -28,6 +28,7 @@ struct RequestedInformation;
|
|||||||
struct ShippingOptions;
|
struct ShippingOptions;
|
||||||
enum class InformationField;
|
enum class InformationField;
|
||||||
enum class CardField;
|
enum class CardField;
|
||||||
|
class FormSummary;
|
||||||
class EditInformation;
|
class EditInformation;
|
||||||
class EditCard;
|
class EditCard;
|
||||||
struct PaymentMethodDetails;
|
struct PaymentMethodDetails;
|
||||||
@ -45,6 +46,7 @@ public:
|
|||||||
const RequestedInformation ¤t,
|
const RequestedInformation ¤t,
|
||||||
const PaymentMethodDetails &method,
|
const PaymentMethodDetails &method,
|
||||||
const ShippingOptions &options);
|
const ShippingOptions &options);
|
||||||
|
void updateFormThumbnail(const QImage &thumbnail);
|
||||||
void showEditInformation(
|
void showEditInformation(
|
||||||
const Invoice &invoice,
|
const Invoice &invoice,
|
||||||
const RequestedInformation ¤t,
|
const RequestedInformation ¤t,
|
||||||
@ -78,6 +80,7 @@ private:
|
|||||||
const not_null<PanelDelegate*> _delegate;
|
const not_null<PanelDelegate*> _delegate;
|
||||||
std::unique_ptr<SeparatePanel> _widget;
|
std::unique_ptr<SeparatePanel> _widget;
|
||||||
std::unique_ptr<Webview::Window> _webview;
|
std::unique_ptr<Webview::Window> _webview;
|
||||||
|
QPointer<FormSummary> _weakFormSummary;
|
||||||
QPointer<EditInformation> _weakEditInformation;
|
QPointer<EditInformation> _weakEditInformation;
|
||||||
QPointer<EditCard> _weakEditCard;
|
QPointer<EditCard> _weakEditCard;
|
||||||
|
|
||||||
|
@ -14,7 +14,16 @@ struct LabeledPrice {
|
|||||||
int64 price = 0;
|
int64 price = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Cover {
|
||||||
|
QString title;
|
||||||
|
QString description;
|
||||||
|
QString seller;
|
||||||
|
QImage thumbnail;
|
||||||
|
};
|
||||||
|
|
||||||
struct Invoice {
|
struct Invoice {
|
||||||
|
Cover cover;
|
||||||
|
|
||||||
std::vector<LabeledPrice> prices;
|
std::vector<LabeledPrice> prices;
|
||||||
QString currency;
|
QString currency;
|
||||||
|
|
||||||
|