Simplify paid stars check.

This commit is contained in:
John Preston 2025-02-19 15:03:11 +04:00
parent fe9bac096b
commit c38982d286
7 changed files with 107 additions and 82 deletions

View file

@ -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,

View file

@ -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(

View file

@ -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 {

View file

@ -60,6 +60,33 @@ bool PeerCallKnown(not_null<PeerData*> peer) {
} // namespace
int ComputeSendingMessagesCount(
not_null<History*> 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<PeerData*> 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<SendPaymentDetails> ComputePaymentDetails(
not_null<PeerData*> 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<Ui::BoxContent> MakeSendErrorBox(
const Data::SendErrorWithThread &error,
bool withTitle) {

View file

@ -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*> history,
const SendingErrorRequest &request);
[[nodiscard]] Data::SendError GetErrorForSending(
not_null<PeerData*> peer,
SendingErrorRequest request);
@ -124,6 +127,14 @@ struct SendingErrorRequest {
not_null<Data::Thread*> thread,
SendingErrorRequest request);
struct SendPaymentDetails {
int messages = 0;
int stars = 0;
};
[[nodiscard]] std::optional<SendPaymentDetails> ComputePaymentDetails(
not_null<PeerData*> peer,
int messagesCount);
[[nodiscard]] Data::SendErrorWithThread GetErrorForSending(
const std::vector<not_null<Data::Thread*>> &threads,
SendingErrorRequest request);

View file

@ -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<void(int starsApproved)> 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) {

View file

@ -474,6 +474,10 @@ private:
Fn<void(int starsApproved)> resend = nullptr,
int starsApproved = 0,
bool mediaMessage = false);
bool checkSendPayment(
int messagesCount,
int starsApproved,
Fn<void(int starsApproved)> resend);
void sendingFilesConfirmed(
Ui::PreparedList &&list,