Star-count button in SendFilesBox/ShareBox.

This commit is contained in:
John Preston 2025-02-28 12:08:26 +04:00
parent 63fdc1f876
commit b3f9a77ba7
11 changed files with 128 additions and 27 deletions

View file

@ -1484,9 +1484,12 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
? tr::lng_group_invite_copied(tr::now)
: copied);
};
auto countMessagesCallback = [=](const TextWithTags &comment) {
return 1;
};
auto submitCallback = [=](
std::vector<not_null<Data::Thread*>> &&result,
Fn<bool(int messages)> checkPaid,
Fn<bool()> checkPaid,
TextWithTags &&comment,
Api::SendOptions options,
Data::ForwardOptions) {
@ -1504,7 +1507,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
result.size() > 1));
}
return;
} else if (!checkPaid(1)) {
} else if (!checkPaid()) {
return;
}
@ -1542,6 +1545,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
auto object = Box<ShareBox>(ShareBox::Descriptor{
.session = session,
.copyCallback = std::move(copyCallback),
.countMessagesCallback = std::move(countMessagesCallback),
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),

View file

@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/peer_bubble.h"
#include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_credits.h"
#include "styles/style_giveaway.h"
#include "styles/style_info.h" // inviteLinkSubscribeBoxTerms
@ -511,11 +512,8 @@ TextWithEntities CreditsEmoji(not_null<Main::Session*> session) {
}
TextWithEntities CreditsEmojiSmall(not_null<Main::Session*> session) {
return Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::starIconSmall,
st::starIconSmallPadding,
true),
return Ui::Text::IconEmoji(
&st::boxStarIconEmoji,
QString(QChar(0x2B50)));
}

View file

@ -59,9 +59,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "core/application.h"
#include "core/core_settings.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_layers.h"
#include <QtCore/QMimeData>
@ -714,6 +714,18 @@ void SendFilesBox::openDialogToAddFileToAlbum() {
crl::guard(this, callback));
}
void SendFilesBox::refreshMessagesCount() {
const auto way = _sendWay.current();
const auto withCaption = _list.canAddCaption(
way.groupFiles() && way.sendImagesAsPhotos(),
way.sendImagesAsPhotos());
const auto withComment = !withCaption
&& _caption
&& !_caption->isHidden()
&& !_caption->getTextWithTags().text.isEmpty();
_messagesCount = _list.files.size() + (withComment ? 1 : 0);
}
void SendFilesBox::refreshButtons() {
clearButtons();
@ -722,6 +734,19 @@ void SendFilesBox::refreshButtons() {
? tr::lng_send_button()
: tr::lng_create_group_next()),
[=] { send({}); });
refreshMessagesCount();
const auto perMessage = _captionToPeer
? _captionToPeer->starsPerMessageChecked()
: 0;
if (perMessage > 0) {
_send->setText(_messagesCount.value(
) | rpl::map([=](int count) {
const auto stars = count * perMessage;
return Ui::Text::IconEmoji(&st::boxStarIconEmoji).append(
Lang::FormatCountToShort(stars).string);
}));
}
if (_sendType == Api::SendType::Normal) {
SendMenu::SetupMenuAndShortcuts(
_send,
@ -1451,6 +1476,7 @@ void SendFilesBox::setupCaption() {
_caption->changes()
) | rpl::start_with_next([=] {
checkCharsLimitation();
refreshMessagesCount();
}, _caption->lifetime());
}

View file

@ -246,6 +246,7 @@ private:
void addPreparedAsyncFile(Ui::PreparedFile &&file);
void checkCharsLimitation();
void refreshMessagesCount();
[[nodiscard]] Fn<MenuDetails()> prepareSendMenuDetails(
const SendFilesBoxDescriptor &descriptor);
@ -261,6 +262,7 @@ private:
Ui::PreparedList _list;
std::optional<int> _removingIndex;
rpl::variable<int> _messagesCount;
SendFilesLimits _limits = {};
Fn<MenuDetails()> _sendMenuDetails;

View file

@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/core_settings.h"
#include "styles/style_calls.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
#include "styles/style_menu_icons.h"
@ -620,6 +621,13 @@ void ShareBox::createButtons() {
showMenu(send);
}
}, send->lifetime());
send->setText(_starsToSend.value() | rpl::map([=](int stars) {
using namespace Ui;
return stars
? Text::IconEmoji(&st::boxStarIconEmoji).append(
Lang::FormatCountToShort(stars).string)
: tr::lng_share_confirm(tr::now, Text::WithEntities);
}));
} else if (_descriptor.copyCallback) {
addButton(_copyLinkText.value(), [=] { copyLink(); });
}
@ -667,13 +675,19 @@ void ShareBox::submit(Api::SendOptions options) {
auto threads = _inner->selected();
const auto weak = Ui::MakeWeak(this);
const auto checkPaid = [=](int messagesCount) {
const auto field = _comment->entity();
auto comment = field->getTextWithAppliedMarkdown();
const auto checkPaid = [=] {
if (!_descriptor.countMessagesCallback) {
return true;
}
const auto withPaymentApproved = crl::guard(weak, [=](int approved) {
auto copy = options;
copy.starsApproved = approved;
submit(copy);
});
const auto messagesCount = _descriptor.countMessagesCallback(
comment);
const auto alreadyApproved = options.starsApproved;
auto paid = std::vector<not_null<PeerData*>>();
auto waiting = base::flat_set<not_null<PeerData*>>();
@ -734,7 +748,7 @@ void ShareBox::submit(Api::SendOptions options) {
onstack(
std::move(threads),
checkPaid,
_comment->entity()->getTextWithAppliedMarkdown(),
std::move(comment),
options,
forwardOptions);
}
@ -754,9 +768,23 @@ void ShareBox::selectedChanged() {
_comment->toggle(_hasSelected, anim::type::normal);
_comment->resizeToWidth(st::boxWideWidth);
}
computeStarsCount();
update();
}
void ShareBox::computeStarsCount() {
auto perMessage = 0;
for (const auto &thread : _inner->selected()) {
perMessage += thread->peer()->starsPerMessageChecked();
}
const auto messagesCount = _descriptor.countMessagesCallback
? _descriptor.countMessagesCallback(_comment
? _comment->entity()->getTextWithTags()
: TextWithTags())
: 0;
_starsToSend = perMessage * messagesCount;
}
void ShareBox::scrollTo(Ui::ScrollToRequest request) {
scrollToY(request.ymin, request.ymax);
//auto scrollTop = scrollArea()->scrollTop(), scrollBottom = scrollTop + scrollArea()->height();
@ -1568,6 +1596,15 @@ ChatHelpers::ForwardedMessagePhraseArgs CreateForwardedMessagePhraseArgs(
};
}
ShareBox::CountMessagesCallback ShareBox::DefaultForwardCountMessages(
not_null<History*> history,
MessageIdsList msgIds) {
return [=](const TextWithTags &comment) {
const auto items = history->owner().idsToItems(msgIds);
return int(items.size()) + (comment.empty() ? 0 : 1);
};
}
ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
std::shared_ptr<Ui::Show> show,
not_null<History*> history,
@ -1579,7 +1616,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
const auto state = std::make_shared<State>();
return [=](
std::vector<not_null<Data::Thread*>> &&result,
Fn<bool(int messagesCount)> checkPaid,
Fn<bool()> checkPaid,
TextWithTags comment,
Api::SendOptions options,
Data::ForwardOptions forwardOptions) {
@ -1593,14 +1630,13 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
return;
}
auto messagesCount = int(items.size()) + (comment.empty() ? 0 : 1);
const auto error = GetErrorForSending(
result,
{ .forward = &items, .text = &comment });
if (error.error) {
show->showBox(MakeSendErrorBox(error, result.size() > 1));
return;
} else if (!checkPaid(messagesCount)) {
} else if (!checkPaid()) {
return;
}
@ -1811,6 +1847,9 @@ void FastShareMessage(
show->show(Box<ShareBox>(ShareBox::Descriptor{
.session = session,
.copyCallback = std::move(copyLinkCallback),
.countMessagesCallback = ShareBox::DefaultForwardCountMessages(
history,
msgIds),
.submitCallback = ShareBox::DefaultForwardCallback(
show,
history,
@ -1850,9 +1889,12 @@ void FastShareLink(
QGuiApplication::clipboard()->setText(url);
show->showToast(tr::lng_background_link_copied(tr::now));
};
auto countMessagesCallback = [=](const TextWithTags &comment) {
return 1;
};
auto submitCallback = [=](
std::vector<not_null<::Data::Thread*>> &&result,
Fn<bool(int messages)> checkPaid,
Fn<bool()> checkPaid,
TextWithTags &&comment,
Api::SendOptions options,
::Data::ForwardOptions) {
@ -1869,7 +1911,7 @@ void FastShareLink(
MakeSendErrorBox(error, result.size() > 1));
}
return;
} else if (!checkPaid(1)) {
} else if (!checkPaid()) {
return;
}
@ -1908,6 +1950,7 @@ void FastShareLink(
Box<ShareBox>(ShareBox::Descriptor{
.session = &show->session(),
.copyCallback = std::move(copyCallback),
.countMessagesCallback = std::move(countMessagesCallback),
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.st = st,

View file

@ -95,14 +95,18 @@ struct RecipientMoneyRestrictionError;
class ShareBox final : public Ui::BoxContent {
public:
using CopyCallback = Fn<void()>;
using CountMessagesCallback = Fn<int(const TextWithTags&)>;
using SubmitCallback = Fn<void(
std::vector<not_null<Data::Thread*>>&&,
Fn<bool(int messages)> checkPaid,
Fn<bool()> checkPaid,
TextWithTags&&,
Api::SendOptions,
Data::ForwardOptions)>;
using FilterCallback = Fn<bool(not_null<Data::Thread*>)>;
[[nodiscard]] static auto DefaultForwardCountMessages(
not_null<History*> history,
MessageIdsList msgIds) -> CountMessagesCallback;
[[nodiscard]] static SubmitCallback DefaultForwardCallback(
std::shared_ptr<Ui::Show> show,
not_null<History*> history,
@ -112,6 +116,7 @@ public:
struct Descriptor {
not_null<Main::Session*> session;
CopyCallback copyCallback;
CountMessagesCallback countMessagesCallback;
SubmitCallback submitCallback;
FilterCallback filterCallback;
object_ptr<Ui::RpWidget> bottomWidget = { nullptr };
@ -152,6 +157,7 @@ private:
void needSearchByUsername();
void applyFilterUpdate(const QString &query);
void selectedChanged();
void computeStarsCount();
void createButtons();
int getTopScrollSkip() const;
int getBottomScrollSkip() const;
@ -183,6 +189,7 @@ private:
bool _hasSelected = false;
rpl::variable<QString> _copyLinkText;
rpl::variable<int> _starsToSend;
base::Timer _searchTimer;
QString _peopleQuery;

View file

@ -132,9 +132,12 @@ object_ptr<ShareBox> ShareInviteLinkBox(
QGuiApplication::clipboard()->setText(currentLink());
show->showToast(tr::lng_group_invite_copied(tr::now));
};
auto countMessagesCallback = [=](const TextWithTags &comment) {
return 1;
};
auto submitCallback = [=](
std::vector<not_null<Data::Thread*>> &&result,
Fn<bool(int messages)> checkPaid,
Fn<bool()> checkPaid,
TextWithTags &&comment,
Api::SendOptions options,
Data::ForwardOptions) {
@ -151,7 +154,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
MakeSendErrorBox(error, result.size() > 1));
}
return;
} else if (!checkPaid(1)) {
} else if (!checkPaid()) {
return;
}
@ -192,6 +195,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
auto result = Box<ShareBox>(ShareBox::Descriptor{
.session = &peer->session(),
.copyCallback = std::move(copyCallback),
.countMessagesCallback = std::move(countMessagesCallback),
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.bottomWidget = std::move(bottom),

View file

@ -1364,6 +1364,11 @@ defaultComposeControls: ComposeControls {
restrictionLabel: defaultRestrictionLabel;
}
boxStarIconEmoji: IconEmoji {
icon: icon{{ "payments/small_star", windowFg }};
padding: margins(0px, -2px, 0px, 0px);
}
moreChatsBarHeight: 48px;
moreChatsBarTextPosition: point(12px, 4px);
moreChatsBarStatusPosition: point(12px, 24px);

View file

@ -76,9 +76,12 @@ namespace Media::Stories {
auto copyLinkCallback = canCopyLink
? Fn<void()>(std::move(copyCallback))
: Fn<void()>();
auto countMessagesCallback = [=](const TextWithTags &comment) {
return comment.text.isEmpty() ? 1 : 2;
};
auto submitCallback = [=](
std::vector<not_null<Data::Thread*>> &&result,
Fn<bool(int messages)> checkPaid,
Fn<bool()> checkPaid,
TextWithTags &&comment,
Api::SendOptions options,
Data::ForwardOptions forwardOptions) {
@ -96,7 +99,7 @@ namespace Media::Stories {
if (error.error) {
show->showBox(MakeSendErrorBox(error, result.size() > 1));
return;
} else if (!checkPaid(comment.text.isEmpty() ? 1 : 2)) {
} else if (!checkPaid()) {
return;
}
@ -187,6 +190,7 @@ namespace Media::Stories {
return Box<ShareBox>(ShareBox::Descriptor{
.session = session,
.copyCallback = std::move(copyLinkCallback),
.countMessagesCallback = std::move(countMessagesCallback),
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.st = st.shareBox ? *st.shareBox : ShareBoxStyleOverrides(),
@ -254,6 +258,9 @@ object_ptr<Ui::BoxContent> PrepareShareAtTimeBox(
return Box<ShareBox>(ShareBox::Descriptor{
.session = session,
.copyCallback = std::move(copyLinkCallback),
.countMessagesCallback = ShareBox::DefaultForwardCountMessages(
history,
{ id }),
.submitCallback = ShareBox::DefaultForwardCallback(
show,
history,

View file

@ -2463,15 +2463,21 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
tr::lng_photos_comment()),
st::shareCommentPadding);
const auto history = session->data().message(msgIds.front())->history();
const auto send = ShareBox::DefaultForwardCallback(
show,
session->data().message(msgIds.front())->history(),
history,
msgIds);
const auto countMessages = ShareBox::DefaultForwardCountMessages(
history,
msgIds);
const auto weak = Ui::MakeWeak(state->box);
const auto field = comment->entity();
state->submit = [=](Api::SendOptions options) {
const auto peers = state->box->collectSelectedRows();
const auto checkPaid = [=](int messagesCount) {
auto comment = field->getTextWithAppliedMarkdown();
const auto checkPaid = [=] {
const auto withPaymentApproved = crl::guard(weak, [=](
int approved) {
auto copy = options;
@ -2482,6 +2488,7 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
});
const auto alreadyApproved = options.starsApproved;
const auto messagesCount = countMessages(comment);
auto paid = std::vector<not_null<PeerData*>>();
auto waiting = base::flat_set<not_null<PeerData*>>();
auto totalStars = 0;
@ -2532,7 +2539,7 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
return peer->owner().history(peer);
}) | ranges::to_vector,
checkPaid,
comment->entity()->getTextWithAppliedMarkdown(),
std::move(comment),
options,
state->box->forwardOptionsData());
if (!state->submit && successCallback) {
@ -2628,8 +2635,6 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
state->box->setBottomSkip(comment->isHidden() ? 0 : commentHeight);
}, comment->lifetime());
const auto field = comment->entity();
field->submits(
) | rpl::start_with_next([=] {
if (const auto onstack = state->submit) {

@ -1 +1 @@
Subproject commit 2a5d66fb1b9f97eacc3e73c324944a8d77c38e51
Subproject commit cfecbd3df4c1d0bfba3d708dfb49387c8ae2127b