From 23c0fcada6016c9cfabe15d2dd3b46373905ab15 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 29 Jul 2025 18:15:34 +0400 Subject: [PATCH] Show TON icon in resale gifts. --- .../data/stickers/data_custom_emoji.cpp | 63 ++++++++++++++----- .../data/stickers/data_custom_emoji.h | 6 ++ .../controls/history_view_suggest_options.cpp | 3 + .../history/view/history_view_reply.cpp | 2 + .../earn/info_channel_earn_list.cpp | 6 ++ .../peer_gifts/info_peer_gifts_common.cpp | 27 +++++++- .../info/peer_gifts/info_peer_gifts_common.h | 3 + .../info/profile/info_profile_actions.cpp | 1 + .../settings/settings_credits_graphics.cpp | 4 ++ Telegram/SourceFiles/ui/effects/credits.style | 2 + .../window/window_session_controller.cpp | 1 + 11 files changed, 100 insertions(+), 18 deletions(-) diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index ff551f225e..6de1cbd29d 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lottie/lottie_frame_generator.h" #include "ffmpeg/ffmpeg_frame_generator.h" #include "chat_helpers/stickers_lottie.h" +#include "info/channel_statistics/earn/earn_icons.h" #include "storage/file_download.h" // kMaxFileInMemory #include "ui/chat/chats_filter_tag.h" #include "ui/effects/premium_stars_colored.h" @@ -1020,30 +1021,61 @@ uint64 CustomEmojiManager::coloredSetId() const { return _coloredSetId; } +TextWithEntities CustomEmojiManager::tonEmoji(QMargins padding) { + return Ui::Text::SingleCustomEmoji(registerInternalEmoji( + u"builtin:ton_emoji"_q, + Ui::Earn::IconCurrencyColored( + st::tonIconEmojiSize, + st::currencyFg->c), + st::tonIconEmojiPadding + padding, + false)); +} + +TextWithEntities CustomEmojiManager::monoTonEmoji(QMargins padding) { + return Ui::Text::SingleCustomEmoji(registerInternalEmoji( + u"builtin:monoton_emoji"_q, + Ui::Earn::IconCurrencyColored( + st::tonIconEmojiSize, + st::currencyFg->c), + st::tonIconEmojiPadding + padding, + true)); +} + TextWithEntities CustomEmojiManager::creditsEmoji(QMargins padding) { - return Ui::Text::SingleCustomEmoji( - registerInternalEmoji( - Ui::GenerateStars(st::normalFont->height, 1), - padding, - false)); + return Ui::Text::SingleCustomEmoji(registerInternalEmoji( + u"builtin:credits_emoji"_q, + Ui::GenerateStars(st::normalFont->height, 1), + padding, + false)); } TextWithEntities CustomEmojiManager::ministarEmoji(QMargins padding) { - return Ui::Text::SingleCustomEmoji( - registerInternalEmoji( - Ui::GenerateStars(st::giftBoxByStarsStyle.font->height, 1), - padding, - false)); + return Ui::Text::SingleCustomEmoji(registerInternalEmoji( + u"builtin:ministar_emoji"_q, + Ui::GenerateStars(st::giftBoxByStarsStyle.font->height, 1), + padding, + false)); } QString CustomEmojiManager::registerInternalEmoji( + const QString &key, QImage emoji, QMargins padding, bool textColor) { + auto i = _imageEmoji.find(key); + if (i == end(_imageEmoji)) { + i = _imageEmoji.emplace( + key, + registerImageEmoji(std::move(emoji), textColor)).first; + } + return i->second + InternalPadding(padding); +} + +QString CustomEmojiManager::registerImageEmoji( + QImage emoji, + bool textColor) { _internalEmoji.push_back({ std::move(emoji), textColor }); - return InternalPrefix() - + QString::number(_internalEmoji.size() - 1) - + InternalPadding(padding); + return InternalPrefix() + QString::number(_internalEmoji.size() - 1); } QString CustomEmojiManager::registerInternalEmoji( @@ -1063,10 +1095,7 @@ QString CustomEmojiManager::registerInternalEmoji( icon.paint(p, 0, 0, icon.width()); p.end(); - const auto result = registerInternalEmoji( - std::move(image), - QMargins{}, - textColor); + const auto result = registerImageEmoji(std::move(image), textColor); _iconEmoji.emplace(&icon, result); return result + InternalPadding(padding); } diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h index b01f7561e4..c7f4f0719b 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h @@ -84,6 +84,7 @@ public: [[nodiscard]] Session &owner() const; [[nodiscard]] QString registerInternalEmoji( + const QString &key, QImage emoji, QMargins padding = {}, bool textColor = true); @@ -99,6 +100,8 @@ public: [[nodiscard]] uint64 coloredSetId() const; + [[nodiscard]] TextWithEntities tonEmoji(QMargins padding = {}); + [[nodiscard]] TextWithEntities monoTonEmoji(QMargins padding = {}); [[nodiscard]] TextWithEntities creditsEmoji(QMargins padding = {}); [[nodiscard]] TextWithEntities ministarEmoji(QMargins padding = {}); @@ -127,6 +130,7 @@ private: DocumentId documentId, SizeTag tag, int sizeOverride = 0); + [[nodiscard]] QString registerImageEmoji(QImage emoji, bool textColor); void request(); void requestFinished(); @@ -193,6 +197,8 @@ private: std::vector _internalEmoji; base::flat_map, QString> _iconEmoji; + base::flat_map _imageEmoji; + #if 0 // inject-to-on_main crl::time _repaintsLastAdded = 0; rpl::lifetime _repaintsLifetime; diff --git a/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp b/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp index debbfc8a2b..174e10aa6a 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_suggest_options.cpp @@ -243,6 +243,7 @@ StarsTonPriceInput AddStarsTonPriceInput( const auto tonField = ownedTonField.data(); const auto tonIcon = makeIcon(tonField, Ui::Text::SingleCustomEmoji( manager->registerInternalEmoji( + u"ton_price_field_emoji"_q, Ui::Earn::IconCurrencyColored( st::tonFieldIconSize, st::currencyFg->c), @@ -654,6 +655,7 @@ void ChooseSuggestPriceBox( const auto button = box->addButton(rpl::single(QString()), state->save); const auto coloredTonIcon = Ui::Text::SingleCustomEmoji( session->data().customEmojiManager().registerInternalEmoji( + u"ton_price_suggest_save"_q, Ui::Earn::IconCurrencyColored( st::tonFieldIconSize, st::currencyFg->c), @@ -904,6 +906,7 @@ TextWithEntities SuggestOptions::composeText() const { const auto amount = _values.price().ton() ? Ui::Text::SingleCustomEmoji( manager->registerInternalEmoji( + u"ton_price_preview_emoji"_q, Ui::Earn::IconCurrencyColored( st::suggestBarTonIconSize, st::currencyFg->c), diff --git a/Telegram/SourceFiles/history/view/history_view_reply.cpp b/Telegram/SourceFiles/history/view/history_view_reply.cpp index 5d18086720..9635477b5c 100644 --- a/Telegram/SourceFiles/history/view/history_view_reply.cpp +++ b/Telegram/SourceFiles/history/view/history_view_reply.cpp @@ -107,6 +107,7 @@ constexpr auto kNonExpandedLinesLimit = 5; not_null session) { return Ui::Text::SingleCustomEmoji( session->data().customEmojiManager().registerInternalEmoji( + u"task_done_reply_preview"_q, MakeTaskDoneImage(), QMargins(0, st::lineWidth, st::lineWidth, 0))); } @@ -114,6 +115,7 @@ constexpr auto kNonExpandedLinesLimit = 5; [[nodiscard]] TextWithEntities TaskIcon(not_null session) { return Ui::Text::SingleCustomEmoji( session->data().customEmojiManager().registerInternalEmoji( + u"task_not_done_reply_preview"_q, MakeTaskImage(), QMargins(0, st::lineWidth, st::lineWidth, 0))); } diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp index 4e6ef02378..7127310941 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_channel_earn_list.cpp @@ -420,6 +420,11 @@ void InnerWidget::fill() { const auto &st = label->st(); auto icon = Ui::Text::SingleCustomEmoji( session->data().customEmojiManager().registerInternalEmoji( + (!isIn + ? u"stats_row_ton_some"_q + : (*isIn) + ? u"stats_row_ton_in"_q + : u"stats_row_ton_out"_q), Ui::Earn::IconCurrencyColored( st.style.font, !isIn @@ -443,6 +448,7 @@ void InnerWidget::fill() { const auto bigCurrencyIcon = Ui::Text::SingleCustomEmoji( session->data().customEmojiManager().registerInternalEmoji( + u"stats_row_ton_big"_q, Ui::Earn::IconCurrencyColored( st::boxTitle.style.font, st::currencyFg->c), diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp index ef72cb7770..db369e328c 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp @@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "history/view/media/history_view_sticker_player.h" #include "lang/lang_keys.h" +#include "info/channel_statistics/earn/earn_icons.h" #include "main/main_session.h" #include "settings/settings_credits_graphics.h" #include "ui/layers/generic_box.h" @@ -614,7 +615,8 @@ void GiftButton::paintEvent(QPaintEvent *e) { v::match(_descriptor, [](const GiftTypePremium &) { }, [&](const GiftTypeStars &data) { - if (unique && data.pinned) { + if (!unique) { + } else if (data.pinned) { auto hq = PainterHighQualityEnabler(p); const auto &icon = st::giftBoxPinIcon; const auto skip = st::giftBoxUserpicSkip; @@ -626,6 +628,25 @@ void GiftButton::paintEvent(QPaintEvent *e) { QSize(icon.width() + 2 * add, icon.height() + 2 * add)); p.drawEllipse(rect); icon.paintInCenter(p, rect); + } else if (unique->nanoTonForResale && unique->onlyAcceptTon) { + if (_tonIcon.isNull()) { + _tonIcon = Ui::Earn::IconCurrencyColored( + st::tonIconEmojiSize, + QColor(255, 255, 255)); + } + const auto size = _tonIcon.size() / _tonIcon.devicePixelRatio(); + const auto skip = st::giftBoxUserpicSkip; + const auto add = (st::giftBoxUserpicSize - size.width()) / 2; + p.setPen(Qt::NoPen); + p.setBrush(unique->backdrop.patternColor); + const auto rect = QRect( + QPoint(extend.left() + skip, extend.top() + skip), + QSize(size.width() + 2 * add, size.height() + 2 * add)); + p.drawEllipse(rect); + p.drawImage( + extend.left() + skip + add, + extend.top() + skip + add, + _tonIcon); } }); @@ -720,6 +741,10 @@ TextWithEntities Delegate::monostar() { return Ui::Text::IconEmoji(&st::starIconEmoji); } +TextWithEntities Delegate::monoton() { + return _session->data().customEmojiManager().monoTonEmoji(); +} + TextWithEntities Delegate::ministar() { const auto owner = &_session->data(); const auto top = st::giftBoxByStarsStarTop; diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h index e6f15b759e..07b5620675 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h @@ -115,6 +115,7 @@ class GiftButtonDelegate { public: [[nodiscard]] virtual TextWithEntities star() = 0; [[nodiscard]] virtual TextWithEntities monostar() = 0; + [[nodiscard]] virtual TextWithEntities monoton() = 0; [[nodiscard]] virtual TextWithEntities ministar() = 0; [[nodiscard]] virtual Ui::Text::MarkedContext textContext() = 0; [[nodiscard]] virtual QSize buttonSize() = 0; @@ -173,6 +174,7 @@ private: Ui::Text::String _byStars; std::shared_ptr _userpic; QImage _uniqueBackgroundCache; + QImage _tonIcon; std::unique_ptr _uniquePatternEmoji; base::flat_map _uniquePatternCache; std::optional _stars; @@ -199,6 +201,7 @@ public: TextWithEntities star() override; TextWithEntities monostar() override; + TextWithEntities monoton() override; TextWithEntities ministar() override; Ui::Text::MarkedContext textContext() override; QSize buttonSize() override; diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 26823bb83b..405dceb0f7 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -908,6 +908,7 @@ rpl::producer AddCurrencyAction( const auto name = Ui::CreateChild(button, st.rightLabel); const auto icon = Ui::Text::SingleCustomEmoji( user->owner().customEmojiManager().registerInternalEmoji( + u"profile_ton_section_icon"_q, Ui::Earn::IconCurrencyColored( st.rightLabel.style.font, st.rightLabel.textFg->c), diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index a3d63a2ac0..aa78c3bde4 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -722,6 +722,7 @@ not_null AddBalanceWidget( if (value.ton()) { text.append(Ui::Text::SingleCustomEmoji( manager->registerInternalEmoji( + u"balance_amount_ton_icon"_q, Ui::Earn::IconCurrencyColored( st::tonFieldIconSize, st::currencyFg->c), @@ -1529,6 +1530,9 @@ void GenericCreditsEntryBox( .append( Ui::Text::SingleCustomEmoji( owner->customEmojiManager().registerInternalEmoji( + (e.in + ? u"stats_transaction_ton_in"_q + : u"stats_transaction_ton_out"_q), Ui::Earn::IconCurrencyColored( st::tonFieldIconSize, (e.in diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style index 8deb501b66..096a869a09 100644 --- a/Telegram/SourceFiles/ui/effects/credits.style +++ b/Telegram/SourceFiles/ui/effects/credits.style @@ -81,6 +81,8 @@ starIconEmojiSmall: IconEmoji { icon: icon{{ "chat/mini_stars", creditsBg1 }}; padding: margins(0px, 4px, 0px, 0px); } +tonIconEmojiSize: 18px; +tonIconEmojiPadding: margins(0px, 2px, 0px, 0px); creditsHistoryEntryTypeAds: icon {{ "folders/folders_channels", premiumButtonFg }}; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 53a155529e..2c4f9e0ae8 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -182,6 +182,7 @@ private: return { .tonEmoji = Ui::Text::SingleCustomEmoji( session->data().customEmojiManager().registerInternalEmoji( + u"collectible_ton_icon"_q, Ui::Earn::IconCurrencyColored( st::collectibleInfo.style.font, st::collectibleInfo.textFg->c),