mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add support for inline invoices.
This commit is contained in:
parent
8889329415
commit
00c915e58d
9 changed files with 149 additions and 76 deletions
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/notifications_manager.h"
|
#include "window/notifications_manager.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
|
#include "payments/payments_checkout_process.h" // CheckoutProcess::Start.
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/text/text_options.h"
|
#include "ui/text/text_options.h"
|
||||||
|
|
||||||
|
@ -522,18 +523,28 @@ bool HistoryService::updateDependent(bool force) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dependent->lnk) {
|
if (!dependent->lnk) {
|
||||||
dependent->lnk = goToMessageClickHandler(history()->peer, dependent->msgId);
|
dependent->lnk = goToMessageClickHandler(
|
||||||
|
(dependent->peerId
|
||||||
|
? history()->owner().peer(dependent->peerId)
|
||||||
|
: history()->peer),
|
||||||
|
dependent->msgId);
|
||||||
}
|
}
|
||||||
auto gotDependencyItem = false;
|
auto gotDependencyItem = false;
|
||||||
if (!dependent->msg) {
|
if (!dependent->msg) {
|
||||||
dependent->msg = history()->owner().message(channelId(), dependent->msgId);
|
dependent->msg = history()->owner().message(
|
||||||
|
(dependent->peerId
|
||||||
|
? peerToChannel(dependent->peerId)
|
||||||
|
: channelId()),
|
||||||
|
dependent->msgId);
|
||||||
if (dependent->msg) {
|
if (dependent->msg) {
|
||||||
if (dependent->msg->isEmpty()) {
|
if (dependent->msg->isEmpty()) {
|
||||||
// Really it is deleted.
|
// Really it is deleted.
|
||||||
dependent->msg = nullptr;
|
dependent->msg = nullptr;
|
||||||
force = true;
|
force = true;
|
||||||
} else {
|
} else {
|
||||||
history()->owner().registerDependentMessage(this, dependent->msg);
|
history()->owner().registerDependentMessage(
|
||||||
|
this,
|
||||||
|
dependent->msg);
|
||||||
gotDependencyItem = true;
|
gotDependencyItem = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,14 +760,14 @@ HistoryService::PreparedText HistoryService::preparePaymentSentText() {
|
||||||
auto payment = Get<HistoryServicePayment>();
|
auto payment = Get<HistoryServicePayment>();
|
||||||
|
|
||||||
auto invoiceTitle = [&] {
|
auto invoiceTitle = [&] {
|
||||||
if (payment && payment->msg) {
|
if (payment->msg) {
|
||||||
if (const auto media = payment->msg->media()) {
|
if (const auto media = payment->msg->media()) {
|
||||||
if (const auto invoice = media->invoice()) {
|
if (const auto invoice = media->invoice()) {
|
||||||
return invoice->title;
|
return textcmdLink(1, invoice->title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tr::lng_deleted_message(tr::now);
|
return tr::lng_deleted_message(tr::now);
|
||||||
} else if (payment && payment->msgId) {
|
} else if (payment->msgId) {
|
||||||
return tr::lng_contacts_loading(tr::now);
|
return tr::lng_contacts_loading(tr::now);
|
||||||
}
|
}
|
||||||
return QString();
|
return QString();
|
||||||
|
@ -766,6 +777,9 @@ HistoryService::PreparedText HistoryService::preparePaymentSentText() {
|
||||||
result.text = tr::lng_action_payment_done(tr::now, lt_amount, payment->amount, lt_user, history()->peer->name);
|
result.text = tr::lng_action_payment_done(tr::now, lt_amount, payment->amount, lt_user, history()->peer->name);
|
||||||
} else {
|
} else {
|
||||||
result.text = tr::lng_action_payment_done_for(tr::now, lt_amount, payment->amount, lt_user, history()->peer->name, lt_invoice, invoiceTitle);
|
result.text = tr::lng_action_payment_done_for(tr::now, lt_amount, payment->amount, lt_user, history()->peer->name, lt_invoice, invoiceTitle);
|
||||||
|
if (payment && payment->msg) {
|
||||||
|
result.links.push_back(payment->lnk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -958,9 +972,16 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
||||||
UpdateComponents(HistoryServicePayment::Bit());
|
UpdateComponents(HistoryServicePayment::Bit());
|
||||||
const auto amount = data.vtotal_amount().v;
|
const auto amount = data.vtotal_amount().v;
|
||||||
const auto currency = qs(data.vcurrency());
|
const auto currency = qs(data.vcurrency());
|
||||||
Get<HistoryServicePayment>()->amount = Ui::FillAmountAndCurrency(
|
const auto payment = Get<HistoryServicePayment>();
|
||||||
amount,
|
const auto id = fullId();
|
||||||
currency);
|
const auto owner = &history()->owner();
|
||||||
|
payment->amount = Ui::FillAmountAndCurrency(amount, currency);
|
||||||
|
payment->invoiceLink = std::make_shared<LambdaClickHandler>([=] {
|
||||||
|
using namespace Payments;
|
||||||
|
if (const auto item = owner->message(id)) {
|
||||||
|
CheckoutProcess::Start(item, Mode::Receipt);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (message.vaction().type() == mtpc_messageActionGroupCall) {
|
} else if (message.vaction().type() == mtpc_messageActionGroupCall) {
|
||||||
const auto &data = message.vaction().c_messageActionGroupCall();
|
const auto &data = message.vaction().c_messageActionGroupCall();
|
||||||
if (data.vduration()) {
|
if (data.vduration()) {
|
||||||
|
@ -1020,21 +1041,22 @@ void HistoryService::createFromMtp(const MTPDmessageService &message) {
|
||||||
}
|
}
|
||||||
if (const auto replyTo = message.vreply_to()) {
|
if (const auto replyTo = message.vreply_to()) {
|
||||||
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
replyTo->match([&](const MTPDmessageReplyHeader &data) {
|
||||||
const auto peer = data.vreply_to_peer_id()
|
const auto peerId = data.vreply_to_peer_id()
|
||||||
? peerFromMTP(*data.vreply_to_peer_id())
|
? peerFromMTP(*data.vreply_to_peer_id())
|
||||||
: history()->peer->id;
|
: history()->peer->id;
|
||||||
if (!peer || peer == history()->peer->id) {
|
if (message.vaction().type() == mtpc_messageActionPinMessage) {
|
||||||
if (message.vaction().type() == mtpc_messageActionPinMessage) {
|
UpdateComponents(HistoryServicePinned::Bit());
|
||||||
UpdateComponents(HistoryServicePinned::Bit());
|
}
|
||||||
}
|
if (const auto dependent = GetDependentData()) {
|
||||||
if (const auto dependent = GetDependentData()) {
|
dependent->peerId = (peerId != history()->peer->id)
|
||||||
dependent->msgId = data.vreply_to_msg_id().v;
|
? peerId
|
||||||
if (!updateDependent()) {
|
: 0;
|
||||||
history()->session().api().requestMessageData(
|
dependent->msgId = data.vreply_to_msg_id().v;
|
||||||
history()->peer->asChannel(),
|
if (!updateDependent()) {
|
||||||
dependent->msgId,
|
history()->session().api().requestMessageData(
|
||||||
HistoryDependentItemCallback(this));
|
history()->peer->asChannel(),
|
||||||
}
|
dependent->msgId,
|
||||||
|
HistoryDependentItemCallback(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Service;
|
||||||
} // namespace HistoryView
|
} // namespace HistoryView
|
||||||
|
|
||||||
struct HistoryServiceDependentData {
|
struct HistoryServiceDependentData {
|
||||||
|
PeerId peerId = 0;
|
||||||
MsgId msgId = 0;
|
MsgId msgId = 0;
|
||||||
HistoryItem *msg = nullptr;
|
HistoryItem *msg = nullptr;
|
||||||
ClickHandlerPtr lnk;
|
ClickHandlerPtr lnk;
|
||||||
|
@ -34,6 +35,7 @@ struct HistoryServicePayment
|
||||||
: public RuntimeComponent<HistoryServicePayment, HistoryItem>
|
: public RuntimeComponent<HistoryServicePayment, HistoryItem>
|
||||||
, public HistoryServiceDependentData {
|
, public HistoryServiceDependentData {
|
||||||
QString amount;
|
QString amount;
|
||||||
|
ClickHandlerPtr invoiceLink;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HistoryServiceSelfDestruct
|
struct HistoryServiceSelfDestruct
|
||||||
|
|
|
@ -523,7 +523,7 @@ TextState Service::textState(QPoint point, StateRequest request) const {
|
||||||
if (!result.link
|
if (!result.link
|
||||||
&& result.cursor == CursorState::Text
|
&& result.cursor == CursorState::Text
|
||||||
&& g.contains(point)) {
|
&& g.contains(point)) {
|
||||||
result.link = payment->lnk;
|
result.link = payment->invoiceLink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (media) {
|
} else if (media) {
|
||||||
|
|
|
@ -696,24 +696,24 @@ void Video::initDimensions() {
|
||||||
const auto withThumb = withThumbnail();
|
const auto withThumb = withThumbnail();
|
||||||
|
|
||||||
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
||||||
int32 textWidth = _maxw - (withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0);
|
const auto textWidth = _maxw - (st::inlineThumbSize + st::inlineThumbSkip);
|
||||||
TextParseOptions titleOpts = { 0, _maxw, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
TextParseOptions titleOpts = { 0, textWidth, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
||||||
auto title = TextUtilities::SingleLine(_result->getLayoutTitle());
|
auto title = TextUtilities::SingleLine(_result->getLayoutTitle());
|
||||||
if (title.isEmpty()) {
|
if (title.isEmpty()) {
|
||||||
title = tr::lng_media_video(tr::now);
|
title = tr::lng_media_video(tr::now);
|
||||||
}
|
}
|
||||||
_title.setText(st::semiboldTextStyle, title, titleOpts);
|
_title.setText(st::semiboldTextStyle, title, titleOpts);
|
||||||
int32 titleHeight = qMin(_title.countHeight(_maxw), 2 * st::semiboldFont->height);
|
int32 titleHeight = qMin(_title.countHeight(textWidth), 2 * st::semiboldFont->height);
|
||||||
|
|
||||||
int32 descriptionLines = withThumb ? (titleHeight > st::semiboldFont->height ? 1 : 2) : 3;
|
int32 descriptionLines = withThumb ? (titleHeight > st::semiboldFont->height ? 1 : 2) : 3;
|
||||||
|
|
||||||
TextParseOptions descriptionOpts = { TextParseMultiline, _maxw, descriptionLines * st::normalFont->height, Qt::LayoutDirectionAuto };
|
TextParseOptions descriptionOpts = { TextParseMultiline, textWidth, descriptionLines * st::normalFont->height, Qt::LayoutDirectionAuto };
|
||||||
QString description = _result->getLayoutDescription();
|
QString description = _result->getLayoutDescription();
|
||||||
if (description.isEmpty()) {
|
if (description.isEmpty()) {
|
||||||
description = _duration;
|
description = _duration;
|
||||||
}
|
}
|
||||||
_description.setText(st::defaultTextStyle, description, descriptionOpts);
|
_description.setText(st::defaultTextStyle, description, descriptionOpts);
|
||||||
int32 descriptionHeight = qMin(_description.countHeight(_maxw), descriptionLines * st::normalFont->height);
|
int32 descriptionHeight = qMin(_description.countHeight(textWidth), descriptionLines * st::normalFont->height);
|
||||||
|
|
||||||
_minh = st::inlineThumbSize;
|
_minh = st::inlineThumbSize;
|
||||||
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||||
|
@ -1073,13 +1073,13 @@ Contact::Contact(not_null<Context*> context, not_null<Result*> result)
|
||||||
void Contact::initDimensions() {
|
void Contact::initDimensions() {
|
||||||
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
||||||
int32 textWidth = _maxw - (st::inlineThumbSize + st::inlineThumbSkip);
|
int32 textWidth = _maxw - (st::inlineThumbSize + st::inlineThumbSkip);
|
||||||
TextParseOptions titleOpts = { 0, _maxw, st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
TextParseOptions titleOpts = { 0, textWidth, st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
||||||
_title.setText(st::semiboldTextStyle, TextUtilities::SingleLine(_result->getLayoutTitle()), titleOpts);
|
_title.setText(st::semiboldTextStyle, TextUtilities::SingleLine(_result->getLayoutTitle()), titleOpts);
|
||||||
int32 titleHeight = qMin(_title.countHeight(_maxw), st::semiboldFont->height);
|
int32 titleHeight = qMin(_title.countHeight(textWidth), st::semiboldFont->height);
|
||||||
|
|
||||||
TextParseOptions descriptionOpts = { TextParseMultiline, _maxw, st::normalFont->height, Qt::LayoutDirectionAuto };
|
TextParseOptions descriptionOpts = { TextParseMultiline, textWidth, st::normalFont->height, Qt::LayoutDirectionAuto };
|
||||||
_description.setText(st::defaultTextStyle, _result->getLayoutDescription(), descriptionOpts);
|
_description.setText(st::defaultTextStyle, _result->getLayoutDescription(), descriptionOpts);
|
||||||
int32 descriptionHeight = qMin(_description.countHeight(_maxw), st::normalFont->height);
|
int32 descriptionHeight = qMin(_description.countHeight(textWidth), st::normalFont->height);
|
||||||
|
|
||||||
_minh = st::inlineFileSize;
|
_minh = st::inlineFileSize;
|
||||||
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
_minh += st::inlineRowMargin * 2 + st::inlineRowBorder;
|
||||||
|
@ -1170,7 +1170,7 @@ Article::Article(
|
||||||
|
|
||||||
void Article::initDimensions() {
|
void Article::initDimensions() {
|
||||||
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
_maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft;
|
||||||
int32 textWidth = _maxw - (_withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0);
|
int32 textWidth = _maxw - (_withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : (st::emojiPanHeaderLeft - st::inlineResultsLeft));
|
||||||
TextParseOptions titleOpts = { 0, textWidth, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
TextParseOptions titleOpts = { 0, textWidth, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto };
|
||||||
_title.setText(st::semiboldTextStyle, TextUtilities::SingleLine(_result->getLayoutTitle()), titleOpts);
|
_title.setText(st::semiboldTextStyle, TextUtilities::SingleLine(_result->getLayoutTitle()), titleOpts);
|
||||||
int32 titleHeight = qMin(_title.countHeight(textWidth), 2 * st::semiboldFont->height);
|
int32 titleHeight = qMin(_title.countHeight(textWidth), 2 * st::semiboldFont->height);
|
||||||
|
@ -1192,8 +1192,9 @@ int32 Article::resizeGetHeight(int32 width) {
|
||||||
if (_url) {
|
if (_url) {
|
||||||
_urlText = getResultUrl();
|
_urlText = getResultUrl();
|
||||||
_urlWidth = st::normalFont->width(_urlText);
|
_urlWidth = st::normalFont->width(_urlText);
|
||||||
if (_urlWidth > _width - st::inlineThumbSize - st::inlineThumbSkip) {
|
int32 textWidth = _width - (_withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : (st::emojiPanHeaderLeft - st::inlineResultsLeft));
|
||||||
_urlText = st::normalFont->elided(_urlText, _width - st::inlineThumbSize - st::inlineThumbSkip);
|
if (_urlWidth > textWidth) {
|
||||||
|
_urlText = st::normalFont->elided(_urlText, textWidth);
|
||||||
_urlWidth = st::normalFont->width(_urlText);
|
_urlWidth = st::normalFont->width(_urlText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ Result::Result(not_null<Main::Session*> session, const Creator &creator)
|
||||||
std::unique_ptr<Result> Result::Create(
|
std::unique_ptr<Result> Result::Create(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
uint64 queryId,
|
uint64 queryId,
|
||||||
const MTPBotInlineResult &mtpData) {
|
const MTPBotInlineResult &data) {
|
||||||
using Type = Result::Type;
|
using Type = Result::Type;
|
||||||
|
|
||||||
const auto type = [&] {
|
const auto type = [&] {
|
||||||
|
@ -69,7 +69,7 @@ std::unique_ptr<Result> Result::Create(
|
||||||
{ u"geo"_q, Type::Geo },
|
{ u"geo"_q, Type::Geo },
|
||||||
{ u"game"_q, Type::Game },
|
{ u"game"_q, Type::Game },
|
||||||
};
|
};
|
||||||
const auto type = mtpData.match([](const auto &data) {
|
const auto type = data.match([](const auto &data) {
|
||||||
return qs(data.vtype());
|
return qs(data.vtype());
|
||||||
});
|
});
|
||||||
const auto i = kStringToTypeMap.find(type);
|
const auto i = kStringToTypeMap.find(type);
|
||||||
|
@ -82,16 +82,13 @@ std::unique_ptr<Result> Result::Create(
|
||||||
auto result = std::make_unique<Result>(
|
auto result = std::make_unique<Result>(
|
||||||
session,
|
session,
|
||||||
Creator{ queryId, type });
|
Creator{ queryId, type });
|
||||||
const MTPBotInlineMessage *message = nullptr;
|
const auto message = data.match([&](const MTPDbotInlineResult &data) {
|
||||||
switch (mtpData.type()) {
|
result->_id = qs(data.vid());
|
||||||
case mtpc_botInlineResult: {
|
result->_title = qs(data.vtitle().value_or_empty());
|
||||||
const auto &r = mtpData.c_botInlineResult();
|
result->_description = qs(data.vdescription().value_or_empty());
|
||||||
result->_id = qs(r.vid());
|
result->_url = qs(data.vurl().value_or_empty());
|
||||||
result->_title = qs(r.vtitle().value_or_empty());
|
|
||||||
result->_description = qs(r.vdescription().value_or_empty());
|
|
||||||
result->_url = qs(r.vurl().value_or_empty());
|
|
||||||
const auto thumbMime = [&] {
|
const auto thumbMime = [&] {
|
||||||
if (const auto thumb = r.vthumb()) {
|
if (const auto thumb = data.vthumb()) {
|
||||||
return thumb->match([&](const auto &data) {
|
return thumb->match([&](const auto &data) {
|
||||||
return data.vmime_type().v;
|
return data.vmime_type().v;
|
||||||
});
|
});
|
||||||
|
@ -99,7 +96,7 @@ std::unique_ptr<Result> Result::Create(
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
}();
|
}();
|
||||||
const auto contentMime = [&] {
|
const auto contentMime = [&] {
|
||||||
if (const auto content = r.vcontent()) {
|
if (const auto content = data.vcontent()) {
|
||||||
return content->match([&](const auto &data) {
|
return content->match([&](const auto &data) {
|
||||||
return data.vmime_type().v;
|
return data.vmime_type().v;
|
||||||
});
|
});
|
||||||
|
@ -109,49 +106,45 @@ std::unique_ptr<Result> Result::Create(
|
||||||
const auto imageThumb = !thumbMime.isEmpty()
|
const auto imageThumb = !thumbMime.isEmpty()
|
||||||
&& (thumbMime != kVideoThumbMime);
|
&& (thumbMime != kVideoThumbMime);
|
||||||
const auto videoThumb = !thumbMime.isEmpty() && !imageThumb;
|
const auto videoThumb = !thumbMime.isEmpty() && !imageThumb;
|
||||||
if (const auto content = r.vcontent()) {
|
if (const auto content = data.vcontent()) {
|
||||||
result->_content_url = GetContentUrl(*content);
|
result->_content_url = GetContentUrl(*content);
|
||||||
if (result->_type == Type::Photo) {
|
if (result->_type == Type::Photo) {
|
||||||
result->_photo = session->data().photoFromWeb(
|
result->_photo = session->data().photoFromWeb(
|
||||||
*content,
|
*content,
|
||||||
(imageThumb
|
(imageThumb
|
||||||
? Images::FromWebDocument(*r.vthumb())
|
? Images::FromWebDocument(*data.vthumb())
|
||||||
: ImageLocation()));
|
: ImageLocation()));
|
||||||
} else if (contentMime != "text/html"_q) {
|
} else if (contentMime != "text/html"_q) {
|
||||||
result->_document = session->data().documentFromWeb(
|
result->_document = session->data().documentFromWeb(
|
||||||
result->adjustAttributes(*content),
|
result->adjustAttributes(*content),
|
||||||
(imageThumb
|
(imageThumb
|
||||||
? Images::FromWebDocument(*r.vthumb())
|
? Images::FromWebDocument(*data.vthumb())
|
||||||
: ImageLocation()),
|
: ImageLocation()),
|
||||||
(videoThumb
|
(videoThumb
|
||||||
? Images::FromWebDocument(*r.vthumb())
|
? Images::FromWebDocument(*data.vthumb())
|
||||||
: ImageLocation()));
|
: ImageLocation()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!result->_photo && !result->_document && imageThumb) {
|
if (!result->_photo && !result->_document && imageThumb) {
|
||||||
result->_thumbnail.update(result->_session, ImageWithLocation{
|
result->_thumbnail.update(result->_session, ImageWithLocation{
|
||||||
.location = Images::FromWebDocument(*r.vthumb())
|
.location = Images::FromWebDocument(*data.vthumb())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
message = &r.vsend_message();
|
return &data.vsend_message();
|
||||||
} break;
|
}, [&](const MTPDbotInlineMediaResult &data) {
|
||||||
case mtpc_botInlineMediaResult: {
|
result->_id = qs(data.vid());
|
||||||
const auto &r = mtpData.c_botInlineMediaResult();
|
result->_title = qs(data.vtitle().value_or_empty());
|
||||||
result->_id = qs(r.vid());
|
result->_description = qs(data.vdescription().value_or_empty());
|
||||||
result->_title = qs(r.vtitle().value_or_empty());
|
if (const auto photo = data.vphoto()) {
|
||||||
result->_description = qs(r.vdescription().value_or_empty());
|
|
||||||
if (const auto photo = r.vphoto()) {
|
|
||||||
result->_photo = session->data().processPhoto(*photo);
|
result->_photo = session->data().processPhoto(*photo);
|
||||||
}
|
}
|
||||||
if (const auto document = r.vdocument()) {
|
if (const auto document = data.vdocument()) {
|
||||||
result->_document = session->data().processDocument(*document);
|
result->_document = session->data().processDocument(*document);
|
||||||
}
|
}
|
||||||
message = &r.vsend_message();
|
return &data.vsend_message();
|
||||||
} break;
|
});
|
||||||
}
|
|
||||||
if ((result->_photo && result->_photo->isNull())
|
if ((result->_photo && result->_photo->isNull())
|
||||||
|| (result->_document && result->_document->isNull())
|
|| (result->_document && result->_document->isNull())) {
|
||||||
|| !message) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +241,23 @@ std::unique_ptr<Result> Result::Create(
|
||||||
qs(data.vlast_name()),
|
qs(data.vlast_name()),
|
||||||
qs(data.vphone_number()));
|
qs(data.vphone_number()));
|
||||||
}, [&](const MTPDbotInlineMessageMediaInvoice &data) {
|
}, [&](const MTPDbotInlineMessageMediaInvoice &data) {
|
||||||
// #TODO payments
|
using Flag = MTPDmessageMediaInvoice::Flag;
|
||||||
|
const auto media = MTP_messageMediaInvoice(
|
||||||
|
MTP_flags((data.is_shipping_address_requested()
|
||||||
|
? Flag::f_shipping_address_requested
|
||||||
|
: Flag(0))
|
||||||
|
| (data.is_test() ? Flag::f_test : Flag(0))
|
||||||
|
| (data.vphoto() ? Flag::f_photo : Flag(0))),
|
||||||
|
data.vtitle(),
|
||||||
|
data.vdescription(),
|
||||||
|
data.vphoto() ? (*data.vphoto()) : MTPWebDocument(),
|
||||||
|
MTPint(), // receipt_msg_id
|
||||||
|
data.vcurrency(),
|
||||||
|
data.vtotal_amount(),
|
||||||
|
MTP_string(QString())); // start_param
|
||||||
|
result->sendData = std::make_unique<internal::SendInvoice>(
|
||||||
|
session,
|
||||||
|
media);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result->sendData || !result->sendData->isValid()) {
|
if (!result->sendData || !result->sendData->isValid()) {
|
||||||
|
|
|
@ -264,5 +264,15 @@ QString SendGame::getErrorOnSend(
|
||||||
return error.value_or(QString());
|
return error.value_or(QString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto SendInvoice::getSentMessageFields() const -> SentMTPMessageFields {
|
||||||
|
SentMTPMessageFields result;
|
||||||
|
result.media = _media;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SendInvoice::getLayoutDescription(const Result *owner) const {
|
||||||
|
return qs(_media.c_messageMediaInvoice().vdescription());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -351,5 +351,27 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SendInvoice : public SendDataCommon {
|
||||||
|
public:
|
||||||
|
SendInvoice(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
MTPMessageMedia media)
|
||||||
|
: SendDataCommon(session)
|
||||||
|
, _media(media) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid() const override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SentMTPMessageFields getSentMessageFields() const override;
|
||||||
|
|
||||||
|
QString getLayoutDescription(const Result *owner) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MTPMessageMedia _media;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -174,7 +174,8 @@ void CheckoutProcess::handleError(const Error &error) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Error::Type::Validate: {
|
case Error::Type::Validate: {
|
||||||
if (_submitState == SubmitState::Validation) {
|
if (_submitState == SubmitState::Validation
|
||||||
|
|| _submitState == SubmitState::Validated) {
|
||||||
_submitState = SubmitState::None;
|
_submitState = SubmitState::None;
|
||||||
}
|
}
|
||||||
if (_initialSilentValidation) {
|
if (_initialSilentValidation) {
|
||||||
|
@ -281,7 +282,9 @@ void CheckoutProcess::panelCloseSure() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckoutProcess::panelSubmit() {
|
void CheckoutProcess::panelSubmit() {
|
||||||
if (_submitState == SubmitState::Validation
|
if (_form->invoice().receipt.paid) {
|
||||||
|
panelCloseSure();
|
||||||
|
} else if (_submitState == SubmitState::Validation
|
||||||
|| _submitState == SubmitState::Finishing) {
|
|| _submitState == SubmitState::Finishing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,15 @@ FormSummary::FormSummary(
|
||||||
, _topShadow(this)
|
, _topShadow(this)
|
||||||
, _bottomShadow(this)
|
, _bottomShadow(this)
|
||||||
, _submit(
|
, _submit(
|
||||||
this,
|
this,
|
||||||
tr::lng_payments_pay_amount(
|
(_invoice.receipt.paid
|
||||||
|
? tr::lng_about_done()
|
||||||
|
: tr::lng_payments_pay_amount(
|
||||||
lt_amount,
|
lt_amount,
|
||||||
rpl::single(formatAmount(computeTotalAmount()))),
|
rpl::single(formatAmount(computeTotalAmount())))),
|
||||||
st::paymentsPanelSubmit) {
|
(_invoice.receipt.paid
|
||||||
|
? st::passportPanelSaveValue
|
||||||
|
: st::paymentsPanelSubmit)) {
|
||||||
setupControls();
|
setupControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,13 +224,13 @@ void FormSummary::setupPrices(not_null<VerticalLayout*> layout) {
|
||||||
|
|
||||||
Settings::AddSkip(layout, st::paymentsPricesTopSkip);
|
Settings::AddSkip(layout, st::paymentsPricesTopSkip);
|
||||||
if (_invoice.receipt) {
|
if (_invoice.receipt) {
|
||||||
Settings::AddDivider(layout);
|
|
||||||
Settings::AddSkip(layout, st::paymentsPricesBottomSkip);
|
|
||||||
addRow(
|
addRow(
|
||||||
tr::lng_payments_date_label(tr::now),
|
tr::lng_payments_date_label(tr::now),
|
||||||
langDateTime(base::unixtime::parse(_invoice.receipt.date)),
|
langDateTime(base::unixtime::parse(_invoice.receipt.date)),
|
||||||
true);
|
true);
|
||||||
Settings::AddSkip(layout, st::paymentsPricesBottomSkip);
|
Settings::AddSkip(layout, st::paymentsPricesBottomSkip);
|
||||||
|
Settings::AddDivider(layout);
|
||||||
|
Settings::AddSkip(layout, st::paymentsPricesBottomSkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto add = [&](
|
const auto add = [&](
|
||||||
|
|
Loading…
Add table
Reference in a new issue