From 8b11d2d5e784efae585861a2f75c1cc07db62a3d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 26 Sep 2024 16:38:10 +0400 Subject: [PATCH] Show nice star gift transactions in history. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/api/api_credits.cpp | 13 +++++- .../info_statistics_list_controllers.cpp | 13 ++++-- .../settings/settings_credits_graphics.cpp | 41 ++++++++++++------- .../ui/effects/credits_graphics.cpp | 32 +++++++++++++++ .../SourceFiles/ui/effects/credits_graphics.h | 5 +++ 6 files changed, 85 insertions(+), 20 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index eb63fb9b6..92d6976a9 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2430,6 +2430,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_credits_box_history_entry_gift_name" = "Received Gift"; "lng_credits_box_history_entry_giveaway_name" = "Received Prize"; "lng_credits_box_history_entry_gift_sent" = "Sent Gift"; +"lng_credits_box_history_entry_gift_converted" = "Converted Gift"; "lng_credits_box_history_entry_gift_out_about" = "With Stars, **{user}** will be able to unlock content and services on Telegram.\n{link}"; "lng_credits_box_history_entry_gift_in_about" = "Use Stars to unlock content and services on Telegram. {link}"; "lng_credits_box_history_entry_gift_about_link" = "See Examples {emoji}"; diff --git a/Telegram/SourceFiles/api/api_credits.cpp b/Telegram/SourceFiles/api/api_credits.cpp index 96ec1b15c..1fab209ce 100644 --- a/Telegram/SourceFiles/api/api_credits.cpp +++ b/Telegram/SourceFiles/api/api_credits.cpp @@ -69,6 +69,8 @@ constexpr auto kTransactionsLimit = 100; }, [](const auto &) { return PeerId(0); }).value; + const auto stargift = tl.data().vstargift(); + const auto incoming = (int64(tl.data().vstars().v) >= 0); return Data::CreditsHistoryEntry{ .id = qs(tl.data().vid()), .title = qs(tl.data().vtitle().value_or_empty()), @@ -81,6 +83,9 @@ constexpr auto kTransactionsLimit = 100; .barePeerId = barePeerId, .bareGiveawayMsgId = uint64( tl.data().vgiveaway_post_id().value_or_empty()), + .bareGiftStickerId = (stargift + ? owner->processDocument(stargift->data().vsticker())->id + : 0), .peerType = tl.data().vpeer().match([](const HistoryPeerTL &) { return Data::CreditsHistoryEntry::PeerType::Peer; }, [](const MTPDstarsTransactionPeerPlayMarket &) { @@ -104,12 +109,16 @@ constexpr auto kTransactionsLimit = 100; ? base::unixtime::parse(tl.data().vtransaction_date()->v) : QDateTime(), .successLink = qs(tl.data().vtransaction_url().value_or_empty()), + .convertStars = int(stargift + ? stargift->data().vconvert_stars().v + : 0), + .converted = stargift && incoming, .reaction = tl.data().is_reaction(), .refunded = tl.data().is_refund(), .pending = tl.data().is_pending(), .failed = tl.data().is_failed(), - .in = (int64(tl.data().vstars().v) >= 0), - .gift = tl.data().is_gift(), + .in = incoming, + .gift = tl.data().is_gift() || stargift.has_value(), }; } diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp index 495cb458d..817faf0bb 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp @@ -843,14 +843,16 @@ void CreditsRow::init() { const auto name = !isSpecial ? PeerListRow::generateName() : Ui::GenerateEntryName(_entry).text; - _name = (_entry.reaction || _entry.bareGiveawayMsgId) + _name = (_entry.reaction + || _entry.bareGiveawayMsgId + || _entry.convertStars) ? Ui::GenerateEntryName(_entry).text : _entry.title.isEmpty() ? name : _entry.title; const auto joiner = QString(QChar(' ')) + QChar(8212) + QChar(' '); PeerListRow::setCustomStatus( - langDateTimeFull(_entry.date) + langDateTime(_entry.date) + (_entry.refunded ? (joiner + tr::lng_channel_earn_history_return(tr::now)) : _entry.pending @@ -889,7 +891,12 @@ void CreditsRow::init() { _context); } if (!_paintUserpicCallback) { - _paintUserpicCallback = !isSpecial + _paintUserpicCallback = _entry.convertStars + ? Ui::GenerateGiftStickerUserpicCallback( + _context.session, + _entry.bareGiftStickerId, + _context.customEmojiRepaint) + : !isSpecial ? PeerListRow::generatePaintUserpicCallback(false) : Ui::GenerateCreditsPaintUserpicCallback(_entry); } diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index 37a29a2bc..5e22af9d2 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -730,15 +730,16 @@ void ReceiptCreditsBox( const auto item = controller->session().data().message( PeerId(e.barePeerId), MsgId(e.bareMsgId)); const auto isStarGift = (e.convertStars > 0); - const auto myStarGift = isStarGift && e.in; + const auto creditsHistoryStarGift = isStarGift && !e.id.isEmpty(); + const auto sentStarGift = creditsHistoryStarGift && !e.in; + const auto convertedStarGift = creditsHistoryStarGift && e.converted; + const auto gotStarGift = isStarGift && !creditsHistoryStarGift && e.in; const auto starGiftSender = (isStarGift && item) ? item->history()->peer->asUser() : (isStarGift && e.in) ? controller->session().data().peer(PeerId(e.barePeerId))->asUser() : nullptr; - const auto canConvert = myStarGift - && !e.converted - && starGiftSender; + const auto canConvert = gotStarGift && !e.converted && starGiftSender; box->setStyle(canConvert ? st::starGiftBox : st::giveawayGiftCodeBox); box->setNoContentMargin(true); @@ -815,11 +816,17 @@ void ReceiptCreditsBox( ) | rpl::start_with_next([=] { auto p = Painter(icon); const auto &lottie = state->lottie; + const auto factor = style::DevicePixelRatio(); + const auto request = Lottie::FrameRequest{ + .box = icon->size() * factor, + }; const auto frame = (lottie && lottie->ready()) - ? lottie->frameInfo({ .box = icon->size() }) + ? lottie->frameInfo(request) : Lottie::Animation::FrameInfo(); if (!frame.image.isNull()) { - p.drawImage(0, 0, frame.image); + p.drawImage( + QRect(QPoint(), frame.image.size() / factor), + frame.image); if (lottie->frameIndex() < lottie->framesCount() - 1) { lottie->markFrameShown(); } @@ -862,7 +869,11 @@ void ReceiptCreditsBox( ? tr::lng_credits_box_history_entry_subscription(tr::now) : !e.title.isEmpty() ? e.title - : (isStarGift && !myStarGift) + : sentStarGift + ? tr::lng_credits_box_history_entry_gift_sent(tr::now) + : convertedStarGift + ? tr::lng_credits_box_history_entry_gift_converted(tr::now) + : (isStarGift && !gotStarGift) ? tr::lng_gift_link_label_gift(tr::now) : e.gift ? tr::lng_credits_box_history_entry_gift_name(tr::now) @@ -912,9 +923,9 @@ void ReceiptCreditsBox( context); } else { auto t = TextWithEntities() - .append((e.in && !isStarGift) + .append((e.in && (creditsHistoryStarGift || !isStarGift)) ? u"+"_q - : e.gift + : (e.gift && !creditsHistoryStarGift) ? QString() : QString(kMinus)) .append(Lang::FormatCountDecimal(std::abs(int64(e.credits)))) @@ -942,9 +953,9 @@ void ReceiptCreditsBox( ? st::windowSubTextFg : e.pending ? st::creditsStroke - : (e.in || isStarGift) + : (e.in || (isStarGift && !creditsHistoryStarGift)) ? st::boxTextFgGood - : e.gift + : (e.gift && !creditsHistoryStarGift) ? st::windowBoldFg : st::menuIconAttentionColor); const auto x = (amount->width() - fullWidth) / 2; @@ -997,7 +1008,7 @@ void ReceiptCreditsBox( rpl::single(e.description), st::creditsBoxAbout))); } - if (myStarGift) { + if (gotStarGift) { Ui::AddSkip(content); const auto about = box->addRow( object_ptr>( @@ -1061,7 +1072,7 @@ void ReceiptCreditsBox( Ui::AddSkip(content); Ui::AddSkip(content); - if (isStarGift) { + if (isStarGift && e.id.isEmpty()) { AddStarGiftTable(controller, content, e); } else { AddCreditsHistoryEntryTable(controller, content, e); @@ -1082,7 +1093,7 @@ void ReceiptCreditsBox( tr::lng_credits_box_out_about_link(tr::now)), Ui::Text::WithEntities), st::creditsBoxAboutDivider))); - } else if (myStarGift && e.fromGiftsList) { + } else if (gotStarGift && e.fromGiftsList) { box->addRow(object_ptr>( box, object_ptr( @@ -1091,7 +1102,7 @@ void ReceiptCreditsBox( ? tr::lng_gift_visible_hint() : tr::lng_gift_hidden_hint()), st::creditsBoxAboutDivider))); - } else if (myStarGift && e.anonymous) { + } else if (gotStarGift && e.anonymous) { box->addRow(object_ptr>( box, object_ptr( diff --git a/Telegram/SourceFiles/ui/effects/credits_graphics.cpp b/Telegram/SourceFiles/ui/effects/credits_graphics.cpp index e82ec08c1..c855fac0d 100644 --- a/Telegram/SourceFiles/ui/effects/credits_graphics.cpp +++ b/Telegram/SourceFiles/ui/effects/credits_graphics.cpp @@ -16,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo.h" #include "data/data_photo_media.h" #include "data/data_session.h" +#include "history/view/media/history_view_sticker_player.h" +#include "info/userpic/info_userpic_emoji_builder_preview.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "ui/effects/premium_graphics.h" @@ -436,6 +438,32 @@ PaintRoundImageCallback GeneratePaidMediaPaintCallback( totalCount); } +PaintRoundImageCallback GenerateGiftStickerUserpicCallback( + not_null session, + uint64 stickerId, + Fn update) { + struct State { + std::optional painter; + int size = 0; + }; + const auto state = std::make_shared(); + //const auto document = session->data().document(stickerId); + return [=](Painter &p, int x, int y, int outerWidth, int size) { + if (state->size != size || !state->painter) { + state->size = size; + state->painter.emplace(size * M_SQRT2); + state->painter->setDocument( + session->data().document(stickerId), + update); + } + const auto skip = int(base::SafeRound((size * (M_SQRT2 - 1.)) / 2.)); + auto hq = PainterHighQualityEnabler(p); + p.translate(x - skip, y - skip); + state->painter->paintForeground(p); + p.translate(skip - x, skip - y); + }; +} + Fn)> PaintPreviewCallback( not_null session, const Data::CreditsHistoryEntry &entry) { @@ -463,6 +491,10 @@ TextWithEntities GenerateEntryName(const Data::CreditsHistoryEntry &entry) { ? tr::lng_credits_box_history_entry_reaction_name : entry.bareGiveawayMsgId ? tr::lng_credits_box_history_entry_giveaway_name + : entry.converted + ? tr::lng_credits_box_history_entry_gift_converted + : entry.convertStars + ? tr::lng_credits_box_history_entry_gift_sent : entry.gift ? tr::lng_credits_box_history_entry_gift_name : (entry.peerType == Data::CreditsHistoryEntry::PeerType::Fragment) diff --git a/Telegram/SourceFiles/ui/effects/credits_graphics.h b/Telegram/SourceFiles/ui/effects/credits_graphics.h index 038db1c8c..d2a6ef7b8 100644 --- a/Telegram/SourceFiles/ui/effects/credits_graphics.h +++ b/Telegram/SourceFiles/ui/effects/credits_graphics.h @@ -64,6 +64,11 @@ PaintRoundImageCallback GeneratePaidMediaPaintCallback( int totalCount, Fn update); +PaintRoundImageCallback GenerateGiftStickerUserpicCallback( + not_null session, + uint64 stickerId, + Fn update); + Fn)> PaintPreviewCallback( not_null session, const Data::CreditsHistoryEntry &entry);