diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index 55daafd4d..5fe1a2df4 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -634,6 +634,7 @@ void SendConfirmedFile( .replyTo = file->to.replyTo, .date = NewMessageDate(file->to.options), .shortcutId = file->to.options.shortcutId, + .starsPaid = file->to.options.starsApproved, .postAuthor = NewMessagePostAuthor(action), .groupedId = groupId, .effectId = file->to.options.effectId, diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index f571964b3..1509fd8de 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3532,6 +3532,7 @@ void ApiWrap::sendSharedContact( .replyTo = action.replyTo, .date = NewMessageDate(action.options), .shortcutId = action.options.shortcutId, + .starsPaid = action.options.starsApproved, .postAuthor = NewMessagePostAuthor(action), .effectId = action.options.effectId, }, TextWithEntities(), MTP_messageMediaContact( diff --git a/Telegram/SourceFiles/data/data_chat_participant_status.h b/Telegram/SourceFiles/data/data_chat_participant_status.h index 912f580fe..8de7df333 100644 --- a/Telegram/SourceFiles/data/data_chat_participant_status.h +++ b/Telegram/SourceFiles/data/data_chat_participant_status.h @@ -189,26 +189,17 @@ struct SendError { struct Args { QString text; - int paidStars = 0; - int paidMessages = 0; int boostsToLift = 0; - bool resolving = false; bool premiumToLift = false; }; SendError(Args &&args) : text(std::move(args.text)) - , paidStars(args.paidStars) - , paidMessages(args.paidMessages) , boostsToLift(args.boostsToLift) - , resolving(args.resolving) , premiumToLift(args.premiumToLift) { } QString text; - int paidStars = 0; - int paidMessages = 0; int boostsToLift = 0; - bool resolving = false; bool premiumToLift = false; [[nodiscard]] SendError value_or(SendError other) const { diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index e3ac2a4e7..5e8c8d779 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -60,6 +60,33 @@ bool PeerCallKnown(not_null peer) { } // namespace +int ComputeSendingMessagesCount( + not_null history, + const SendingErrorRequest &request) { + auto result = 0; + if (request.text && !request.text->empty()) { + auto sending = TextWithEntities(); + auto left = TextWithEntities{ + request.text->text, + TextUtilities::ConvertTextTagsToEntities(request.text->tags) + }; + auto prepareFlags = Ui::ItemTextOptions( + history, + history->session().user()).flags; + TextUtilities::PrepareForSending(left, prepareFlags); + + while (TextUtilities::CutPart(sending, left, MaxMessageSize)) { + ++result; + } + if (!result) { + ++result; + } + } + return result + + (request.story ? 1 : 0) + + (request.forward ? int(request.forward->size()) : 0); +} + Data::SendError GetErrorForSending( not_null peer, SendingErrorRequest request) { @@ -93,33 +120,10 @@ Data::SendError GetErrorForSending( return tr::lng_forward_cant(tr::now); } } - const auto countMessages = [&] { - auto result = 0; - if (hasText) { - auto sending = TextWithEntities(); - auto left = TextWithEntities{ - request.text->text, - TextUtilities::ConvertTextTagsToEntities(request.text->tags) - }; - auto prepareFlags = Ui::ItemTextOptions( - thread->owningHistory(), - peer->session().user()).flags; - TextUtilities::PrepareForSending(left, prepareFlags); - - while (TextUtilities::CutPart(sending, left, MaxMessageSize)) { - ++result; - } - if (!result) { - ++result; - } - } - return result - + (request.story ? 1 : 0) - + (request.mediaMessage ? 1 : 0) - + (request.forward ? int(request.forward->size()) : 0); - }; if (peer->slowmodeApplied()) { - const auto count = countMessages(); + const auto count = request.messagesCount + ? request.messagesCount + : ComputeSendingMessagesCount(thread->owningHistory(), request); if (const auto history = peer->owner().historyLoaded(peer)) { if (!request.ignoreSlowmodeCountdown && (history->latestSendingMessage() != nullptr) @@ -157,29 +161,6 @@ Data::SendError GetErrorForSending( Ui::FormatDurationWordsSlowmode(left)); } } - - if (const auto user = peer->asUser()) { - if (user->hasStarsPerMessage() - && !user->messageMoneyRestrictionsKnown()) { - user->updateFull(); - return Data::SendError({ .resolving = true }); - } - } else if (const auto channel = peer->asChannel()) { - if (!channel->isFullLoaded()) { - channel->updateFull(); - return Data::SendError({ .resolving = true }); - } - } - if (!peer->session().credits().loaded()) { - peer->session().credits().load(); - return Data::SendError({ .resolving = true }); - } else if (const auto perMessage = peer->starsPerMessageChecked()) { - const auto count = countMessages(); - return Data::SendError({ - .paidStars = count * perMessage, - .paidMessages = count, - }); - } return {}; } @@ -201,6 +182,34 @@ Data::SendErrorWithThread GetErrorForSending( } return {}; } + +std::optional ComputePaymentDetails( + not_null peer, + int messagesCount) { + if (const auto user = peer->asUser()) { + if (user->hasStarsPerMessage() + && !user->messageMoneyRestrictionsKnown()) { + user->updateFull(); + return {}; + } + } else if (const auto channel = peer->asChannel()) { + if (!channel->isFullLoaded()) { + channel->updateFull(); + return {}; + } + } + if (!peer->session().credits().loaded()) { + peer->session().credits().load(); + return {}; + } else if (const auto perMessage = peer->starsPerMessageChecked()) { + return SendPaymentDetails{ + .messages = messagesCount, + .stars = messagesCount * perMessage, + }; + } + return SendPaymentDetails(); +} + object_ptr MakeSendErrorBox( const Data::SendErrorWithThread &error, bool withTitle) { diff --git a/Telegram/SourceFiles/history/history_item_helpers.h b/Telegram/SourceFiles/history/history_item_helpers.h index 20d78579d..e462d3bd9 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.h +++ b/Telegram/SourceFiles/history/history_item_helpers.h @@ -114,9 +114,12 @@ struct SendingErrorRequest { const HistoryItemsList *forward = nullptr; const Data::Story *story = nullptr; const TextWithTags *text = nullptr; + int messagesCount = 0; bool ignoreSlowmodeCountdown = false; - bool mediaMessage = false; }; +[[nodiscard]] int ComputeSendingMessagesCount( + not_null history, + const SendingErrorRequest &request); [[nodiscard]] Data::SendError GetErrorForSending( not_null peer, SendingErrorRequest request); @@ -124,6 +127,14 @@ struct SendingErrorRequest { not_null thread, SendingErrorRequest request); +struct SendPaymentDetails { + int messages = 0; + int stars = 0; +}; +[[nodiscard]] std::optional ComputePaymentDetails( + not_null peer, + int messagesCount); + [[nodiscard]] Data::SendErrorWithThread GetErrorForSending( const std::vector> &threads, SendingErrorRequest request); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 6b4abe9cc..f2095aac4 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -4351,13 +4351,11 @@ void HistoryWidget::sendVoice(const VoiceToSend &data) { copy.options.starsApproved = approved; sendVoice(copy); }; - const auto ignoreSlowmodeCountdown = data.options.scheduled != 0; - if (showSendMessageError( - {}, - ignoreSlowmodeCountdown, - crl::guard(this, withPaymentApproved), - data.options.starsApproved, - true)) { + const auto checked = checkSendPayment( + 1 + int(_forwardPanel->items().size()), + data.options.starsApproved, + withPaymentApproved); + if (!checked) { return; } @@ -5904,28 +5902,38 @@ bool HistoryWidget::showSendMessageError( return false; } const auto topicRootId = resolveReplyToTopicRootId(); - const auto error = GetErrorForSending( - _peer, - { - .topicRootId = topicRootId, - .forward = &_forwardPanel->items(), - .text = &textWithTags, - .ignoreSlowmodeCountdown = ignoreSlowmodeCountdown, - .mediaMessage = mediaMessage, - }); - if (resend && error.resolving) { + auto request = SendingErrorRequest{ + .topicRootId = topicRootId, + .forward = &_forwardPanel->items(), + .text = &textWithTags, + .ignoreSlowmodeCountdown = ignoreSlowmodeCountdown, + }; + request.messagesCount = ComputeSendingMessagesCount(_history, request) + + (mediaMessage ? 1 : 0); + const auto error = GetErrorForSending(_peer, request); + if (error) { + Data::ShowSendErrorToast(controller(), _peer, error); + return true; + } + return resend + && !checkSendPayment(request.messagesCount, starsApproved, resend); +} + +bool HistoryWidget::checkSendPayment( + int messagesCount, + int starsApproved, + Fn resend) { + const auto details = ComputePaymentDetails(_peer, messagesCount); + if (!details) { _resendOnFullUpdated = [=] { resend(starsApproved); }; return true; - } else if (resend && error.paidStars > starsApproved) { + } else if (const auto stars = details->stars) { Data::ShowSendPaidConfirm(controller(), _peer, error, [=] { - resend(error.paidStars); + resend(stars); }); return true; - } else if (!error) { - return false; } - Data::ShowSendErrorToast(controller(), _peer, error); - return true; + return false; } bool HistoryWidget::confirmSendingFiles(const QStringList &files) { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 0b487ea74..96abc7e1e 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -474,6 +474,10 @@ private: Fn resend = nullptr, int starsApproved = 0, bool mediaMessage = false); + bool checkSendPayment( + int messagesCount, + int starsApproved, + Fn resend); void sendingFilesConfirmed( Ui::PreparedList &&list,