From 962d4d29ee97c2277b384c8662cbfae88ea9c51a Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 24 Sep 2024 23:00:22 +0400 Subject: [PATCH] Process gift updates in list. --- Telegram/Resources/langs/lang.strings | 2 + .../SourceFiles/boxes/sticker_set_box.cpp | 2 +- Telegram/SourceFiles/data/data_credits.h | 1 + .../SourceFiles/data/data_media_types.cpp | 8 +- Telegram/SourceFiles/data/data_media_types.h | 3 +- Telegram/SourceFiles/data/data_session.cpp | 8 ++ Telegram/SourceFiles/data/data_session.h | 15 +++ Telegram/SourceFiles/history/history.cpp | 9 ++ .../history/view/history_view_message.cpp | 1 + .../view/media/history_view_premium_gift.cpp | 4 +- .../peer_gifts/info_peer_gifts_widget.cpp | 62 +++++++++++- .../settings/settings_credits_graphics.cpp | 96 ++++++++++++++----- 12 files changed, 177 insertions(+), 34 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 736551fc9..1c03165c6 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3014,6 +3014,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_limited_of_one" = "unique"; "lng_gift_limited_of_count" = "1 of {amount}"; "lng_gift_anonymous_hint" = "Only you can see the sender's name."; +"lng_gift_hidden_hint" = "This gift is hidden. Only you can see it."; +"lng_gift_visible_hint" = "This gift is visible to visitors of your page."; "lng_gift_availability" = "Availability"; "lng_gift_from_hidden" = "Hidden User"; "lng_gift_availability_left#one" = "{count} of {amount} left"; diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index 275cf3f73..dd98ff312 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -251,7 +251,7 @@ void StickerPremiumMark::paint( : (singleSize.height() - (bg.height() / factor) - radius); const auto point = position + QPoint(shiftx, shifty); p.drawImage(point, bg); - if (_premium) { + if (_premium && _part != RectPart::Center) { validateStar(); p.drawImage(point, _star); } else { diff --git a/Telegram/SourceFiles/data/data_credits.h b/Telegram/SourceFiles/data/data_credits.h index af0f6e865..3397cf7ea 100644 --- a/Telegram/SourceFiles/data/data_credits.h +++ b/Telegram/SourceFiles/data/data_credits.h @@ -69,6 +69,7 @@ struct CreditsHistoryEntry final { bool converted = false; bool anonymous = false; bool savedToProfile = false; + bool fromGiftsList = false; bool reaction = false; bool refunded = false; bool pending = false; diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index 79266a509..81dc056e9 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -579,6 +579,10 @@ const Invoice *Media::invoice() const { return nullptr; } +const GiftCode *Media::gift() const { + return nullptr; +} + CloudImage *Media::location() const { return nullptr; } @@ -2331,8 +2335,8 @@ not_null MediaGiftBox::from() const { return _from; } -const GiftCode &MediaGiftBox::data() const { - return _data; +const GiftCode *MediaGiftBox::gift() const { + return &_data; } TextWithEntities MediaGiftBox::notificationText() const { diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index c194429c1..e1213e39a 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -172,6 +172,7 @@ public: virtual const Call *call() const; virtual GameData *game() const; virtual const Invoice *invoice() const; + virtual const GiftCode *gift() const; virtual CloudImage *location() const; virtual PollData *poll() const; virtual const WallPaper *paper() const; @@ -621,7 +622,7 @@ public: std::unique_ptr clone(not_null parent) override; [[nodiscard]] not_null from() const; - [[nodiscard]] const GiftCode &data() const; + [[nodiscard]] const GiftCode *gift() const override; TextWithEntities notificationText() const override; QString pinnedTextSubstring() const override; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index ed31b1683..9ce94052f 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1645,6 +1645,14 @@ rpl::producer> Session::newItemAdded() const { return _newItemAdded.events(); } +void Session::notifyGiftUpdate(GiftUpdate &&update) { + _giftUpdates.fire(std::move(update)); +} + +rpl::producer Session::giftUpdates() const { + return _giftUpdates.events(); +} + HistoryItem *Session::changeMessageId(PeerId peerId, MsgId wasId, MsgId nowId) { const auto list = messagesListForInsert(peerId); const auto i = list->find(wasId); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 424a92649..a87e7e604 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -77,6 +77,18 @@ struct RepliesReadTillUpdate { bool out = false; }; +struct GiftUpdate { + enum class Action : uchar { + Save, + Unsave, + Convert, + Delete, + }; + + FullMsgId itemId; + Action action = {}; +}; + class Session final { public: using ViewElement = HistoryView::Element; @@ -281,6 +293,8 @@ public: [[nodiscard]] rpl::producer> viewLayoutChanged() const; void notifyNewItemAdded(not_null item); [[nodiscard]] rpl::producer> newItemAdded() const; + void notifyGiftUpdate(GiftUpdate &&update); + [[nodiscard]] rpl::producer giftUpdates() const; void requestItemRepaint(not_null item); [[nodiscard]] rpl::producer> itemRepaintRequest() const; void requestViewRepaint(not_null view); @@ -924,6 +938,7 @@ private: rpl::event_stream> _itemLayoutChanges; rpl::event_stream> _viewLayoutChanges; rpl::event_stream> _newItemAdded; + rpl::event_stream _giftUpdates; rpl::event_stream> _itemRepaintRequest; rpl::event_stream> _viewRepaintRequest; rpl::event_stream> _itemResizeRequest; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 35643637e..f78b3f906 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -175,6 +175,15 @@ void History::itemVanished(not_null item) { && unreadCount() > 0) { setUnreadCount(unreadCount() - 1); } + if (const auto media = item->media()) { + if (const auto gift = media->gift()) { + using GiftAction = Data::GiftUpdate::Action; + owner().notifyGiftUpdate({ + .itemId = item->fullId(), + .action = GiftAction::Delete, + }); + } + } } void History::takeLocalDraft(not_null from) { diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index a447d5ff1..25a579507 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -2374,6 +2374,7 @@ bool Message::hasFromPhoto() const { } else if (item->isPost()) { return true; } else if (item->isEmpty() + || item->isFakeAboutView() || (context() == Context::Replies && item->isDiscussionPost())) { return false; } else if (delegate()->elementIsChatWide()) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp index 354106238..a1afbe051 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp @@ -37,7 +37,7 @@ PremiumGift::PremiumGift( not_null gift) : _parent(parent) , _gift(gift) -, _data(gift->data()) { +, _data(*gift->gift()) { } PremiumGift::~PremiumGift() = default; @@ -155,7 +155,7 @@ ClickHandlerPtr PremiumGift::createViewLink() { const auto itemId = _parent->data()->fullId(); const auto peer = _parent->history()->peer; const auto date = _parent->data()->date(); - const auto data = _gift->data(); + const auto data = *_gift->gift(); return std::make_shared([=](ClickContext context) { const auto my = context.other.value(); if (const auto controller = my.sessionWindow.get()) { diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp index a455dd3aa..91956613c 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -76,7 +76,9 @@ private: int visibleBottom) override; void paintEvent(QPaintEvent *e) override; + void subscribeToUpdates(); void loadMore(); + void refreshButtons(); void validateButtons(); void showGift(int index); @@ -119,6 +121,52 @@ InnerWidget::InnerWidget( , _totalCount(_user->peerGiftsCount()) , _api(&_user->session().mtp()) { _singleMin = _delegate.buttonSize(); + + if (user->isSelf()) { + subscribeToUpdates(); + } +} + +void InnerWidget::subscribeToUpdates() { + _user->owner().giftUpdates( + ) | rpl::start_with_next([=](const Data::GiftUpdate &update) { + const auto itemId = [](const Entry &entry) { + return FullMsgId(entry.gift.fromId, entry.gift.messageId); + }; + const auto i = ranges::find(_entries, update.itemId, itemId); + if (i == end(_entries)) { + return; + } + const auto index = int(i - begin(_entries)); + using Action = Data::GiftUpdate::Action; + if (update.action == Action::Convert + || update.action == Action::Delete) { + _entries.erase(i); + if (_totalCount > 0) { + --_totalCount; + } + for (auto &view : _views) { + if (view.entry >= index) { + --view.entry; + } + } + } else if (update.action == Action::Save + || update.action == Action::Unsave) { + i->gift.hidden = (update.action == Action::Unsave); + v::match(i->descriptor, [](GiftTypePremium &) { + }, [&](GiftTypeStars &data) { + data.hidden = i->gift.hidden; + }); + for (auto &view : _views) { + if (view.entry == index) { + view.entry = -1; + } + } + } else { + return; + } + refreshButtons(); + }, lifetime()); } void InnerWidget::visibleTopBottomUpdated( @@ -170,17 +218,21 @@ void InnerWidget::loadMore() { }); } } - _viewsForWidth = 0; - _viewsFromRow = 0; - _viewsTillRow = 0; - resizeToWidth(width()); - validateButtons(); + refreshButtons(); }).fail([=] { _loadMoreRequestId = 0; _allLoaded = true; }).send(); } +void InnerWidget::refreshButtons() { + _viewsForWidth = 0; + _viewsFromRow = 0; + _viewsTillRow = 0; + resizeToWidth(width()); + validateButtons(); +} + void InnerWidget::validateButtons() { if (!_perRow) { return; diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index a8be5e032..37a29a2bc 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -38,6 +38,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/channel_statistics/boosts/giveaway/boost_badge.h" // InfiniteRadialAnimationWidget. #include "info/settings/info_settings_widget.h" // SectionCustomTopBarData. #include "info/statistics/info_statistics_list_controllers.h" +#include "info/info_controller.h" +#include "info/info_memento.h" #include "iv/iv_instance.h" #include "lang/lang_keys.h" #include "lottie/lottie_single_player.h" @@ -158,21 +160,19 @@ private: void ToggleStarGiftSaved( not_null window, - not_null item, + not_null sender, + MsgId itemId, bool save, Fn done) { - Expects(item->history()->peer->isUser()); - using Flag = MTPpayments_SaveStarGift::Flag; const auto api = &window->session().api(); const auto weak = base::make_weak(window); api->request(MTPpayments_SaveStarGift( MTP_flags(save ? Flag(0) : Flag::f_unsave), - item->history()->peer->asUser()->inputUser, - MTP_int(item->id.bare) + sender->inputUser, + MTP_int(itemId.bare) )).done([=] { if (const auto strong = weak.get()) { - strong->showPeerInfo(strong->session().user()); strong->showToast((save ? tr::lng_gift_display_done : tr::lng_gift_display_done_hide)(tr::now)); @@ -206,16 +206,15 @@ void ConfirmConvertStarGift( void ConvertStarGift( not_null window, - not_null item, + not_null sender, + MsgId itemId, int stars, Fn done) { - Expects(item->history()->peer->isUser()); - const auto api = &window->session().api(); const auto weak = base::make_weak(window); api->request(MTPpayments_ConvertStarGift( - item->history()->peer->asUser()->inputUser, - MTP_int(item->id.bare) + sender->inputUser, + MTP_int(itemId) )).done([=] { if (const auto strong = weak.get()) { strong->showSettings(Settings::CreditsId()); @@ -734,6 +733,8 @@ void ReceiptCreditsBox( const auto myStarGift = isStarGift && 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 @@ -1081,6 +1082,15 @@ void ReceiptCreditsBox( tr::lng_credits_box_out_about_link(tr::now)), Ui::Text::WithEntities), st::creditsBoxAboutDivider))); + } else if (myStarGift && e.fromGiftsList) { + box->addRow(object_ptr>( + box, + object_ptr( + box, + (e.savedToProfile + ? tr::lng_gift_visible_hint() + : tr::lng_gift_hidden_hint()), + st::creditsBoxAboutDivider))); } else if (myStarGift && e.anonymous) { box->addRow(object_ptr>( box, @@ -1157,11 +1167,29 @@ void ReceiptCreditsBox( if (canConvert) { const auto save = !e.savedToProfile; const auto window = weakWindow.get(); - const auto item = session->data().message( - starGiftSender->id, - MsgId(e.bareMsgId)); - if (window && item) { - ToggleStarGiftSaved(window, item, save, [=](bool ok) { + const auto showSection = !e.fromGiftsList; + const auto itemId = MsgId(e.bareMsgId); + if (window) { + const auto done = [=](bool ok) { + if (const auto window = weakWindow.get()) { + if (ok) { + using GiftAction = Data::GiftUpdate::Action; + window->session().data().notifyGiftUpdate({ + .itemId = FullMsgId( + starGiftSender->id, + itemId), + .action = (save + ? GiftAction::Save + : GiftAction::Unsave), + }); + if (showSection) { + window->showSection( + std::make_shared( + window->session().user(), + Info::Section::Type::PeerGifts)); + } + } + } if (const auto strong = weak.data()) { if (ok) { strong->closeBox(); @@ -1169,7 +1197,13 @@ void ReceiptCreditsBox( state->confirmButtonBusy = false; } } - }); + }; + ToggleStarGiftSaved( + window, + starGiftSender, + itemId, + save, + done); } } else if (toRenew && s.expired) { Api::CheckChatInvite(controller, s.inviteHash, nullptr, [=] { @@ -1265,11 +1299,20 @@ void ReceiptCreditsBox( } state->convertButtonBusy = true; const auto window = weakWindow.get(); - const auto item = session->data().message( - starGiftSender->id, - MsgId(e.bareMsgId)); - if (window && item && stars) { - ConvertStarGift(window, item, stars, [=](bool ok) { + const auto itemId = MsgId(e.bareMsgId); + if (window && stars) { + const auto done = [=](bool ok) { + if (const auto window = weakWindow.get()) { + if (ok) { + using GiftAction = Data::GiftUpdate::Action; + window->session().data().notifyGiftUpdate({ + .itemId = FullMsgId( + starGiftSender->id, + itemId), + .action = GiftAction::Convert, + }); + } + } if (const auto strong = weak.data()) { if (ok) { strong->closeBox(); @@ -1277,7 +1320,13 @@ void ReceiptCreditsBox( state->convertButtonBusy = false; } } - }); + }; + ConvertStarGift( + window, + starGiftSender, + itemId, + stars, + done); } }); }); @@ -1366,6 +1415,7 @@ void UserStarGiftBox( .converted = false, .anonymous = data.anonymous, .savedToProfile = !data.hidden, + .fromGiftsList = true, .in = data.mine, .gift = true, },