diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp index b689b2d22..cbd8e670f 100644 --- a/Telegram/SourceFiles/api/api_premium.cpp +++ b/Telegram/SourceFiles/api/api_premium.cpp @@ -834,7 +834,7 @@ std::optional FromTL( } std::optional FromTL( - not_null to, + not_null to, const MTPuserStarGift &gift) { const auto session = &to->session(); const auto &data = gift.data(); diff --git a/Telegram/SourceFiles/api/api_premium.h b/Telegram/SourceFiles/api/api_premium.h index 4617da755..912856aff 100644 --- a/Telegram/SourceFiles/api/api_premium.h +++ b/Telegram/SourceFiles/api/api_premium.h @@ -260,7 +260,7 @@ enum class RequirePremiumState { not_null session, const MTPstarGift &gift); [[nodiscard]] std::optional FromTL( - not_null to, + not_null to, const MTPuserStarGift &gift); [[nodiscard]] Data::UniqueGiftModel FromTL( diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 436272664..b757c5104 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -714,6 +714,10 @@ bool ChannelData::canRestrictParticipant( return adminRights() & AdminRight::BanUsers; } +bool ChannelData::canManageGifts() const { + return amCreator(); // todo channel gifts +} + void ChannelData::setBotVerifyDetails(Ui::BotVerifyDetails details) { if (!details) { if (_botVerifyDetails) { @@ -859,6 +863,17 @@ void ChannelData::growSlowmodeLastMessage(TimeId when) { session().changes().peerUpdated(this, UpdateFlag::Slowmode); } +int ChannelData::peerGiftsCount() const { + return _peerGiftsCount; +} + +void ChannelData::setPeerGiftsCount(int count) { + if (_peerGiftsCount != count) { + _peerGiftsCount = count; + session().changes().peerUpdated(this, UpdateFlag::PeerGifts); + } +} + int ChannelData::boostsApplied() const { if (const auto info = mgInfo.get()) { return info->boostsApplied; diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 4c40c61db..af2c2602c 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -375,6 +375,7 @@ public: [[nodiscard]] bool canEditAdmin(not_null user) const; [[nodiscard]] bool canRestrictParticipant( not_null participant) const; + [[nodiscard]] bool canManageGifts() const; void setBotVerifyDetails(Ui::BotVerifyDetails details); void setBotVerifyDetailsIcon(DocumentId iconId); @@ -452,6 +453,9 @@ public: [[nodiscard]] TimeId slowmodeLastMessage() const; void growSlowmodeLastMessage(TimeId when); + [[nodiscard]] int peerGiftsCount() const; + void setPeerGiftsCount(int count); + [[nodiscard]] int boostsApplied() const; [[nodiscard]] int boostsUnrestrict() const; [[nodiscard]] bool unrestrictedByBoosts() const; @@ -522,6 +526,7 @@ private: std::vector &&reasons) override; Flags _flags = ChannelDataFlags(Flag::Forbidden); + int _peerGiftsCount = 0; PtsWaiter _ptsWaiter; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 9da5b0f5f..5cff6c49a 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1532,6 +1532,15 @@ void PeerData::setStoriesState(StoriesState state) { } } +int PeerData::peerGiftsCount() const { + if (const auto user = asUser()) { + return user->peerGiftsCount(); + } else if (const auto channel = asChannel()) { + return channel->peerGiftsCount(); + } + return 0; +} + void PeerData::setIsBlocked(bool is) { const auto status = is ? BlockStatus::Blocked diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 9f7837412..ca416bb5c 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -486,6 +486,8 @@ public: [[nodiscard]] bool hasUnreadStories() const; void setStoriesState(StoriesState state); + [[nodiscard]] int peerGiftsCount() const; + const PeerId id; MTPinputPeer input = MTP_inputPeerEmpty(); diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 3e33e66fe..40f7733dd 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -177,7 +177,7 @@ std::shared_ptr Memento::DefaultContent( case Section::Type::RequestsList: return std::make_shared(peer); case Section::Type::PeerGifts: - return std::make_shared(peer->asUser()); + return std::make_shared(peer); case Section::Type::SavedSublists: return std::make_shared(&peer->session()); case Section::Type::Members: diff --git a/Telegram/SourceFiles/info/media/info_media_buttons.h b/Telegram/SourceFiles/info/media/info_media_buttons.h index b416221bf..4efdb15f9 100644 --- a/Telegram/SourceFiles/info/media/info_media_buttons.h +++ b/Telegram/SourceFiles/info/media/info_media_buttons.h @@ -205,11 +205,11 @@ inline auto AddSavedSublistButton( inline auto AddPeerGiftsButton( Ui::VerticalLayout *parent, not_null navigation, - not_null user, + not_null peer, Ui::MultiSlideTracker &tracker) { auto result = AddCountedButton( parent, - Profile::PeerGiftsCountValue(user), + Profile::PeerGiftsCountValue(peer), [](int count) { return tr::lng_profile_peer_gifts(tr::now, lt_count, count); }, @@ -217,7 +217,7 @@ inline auto AddPeerGiftsButton( result->addClickHandler([=] { navigation->showSection( std::make_shared( - user, + peer, Section::Type::PeerGifts)); }); return result; 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 746984b27..602e4d4cd 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/peer_gifts/info_peer_gifts_widget.h" #include "api/api_premium.h" +#include "data/data_channel.h" #include "data/data_session.h" #include "data/data_user.h" #include "info/peer_gifts/info_peer_gifts_common.h" @@ -32,7 +33,7 @@ constexpr auto kPreloadPages = 2; constexpr auto kPerPage = 50; [[nodiscard]] GiftDescriptor DescriptorForGift( - not_null to, + not_null to, const Data::UserStarGift &gift) { return GiftTypeStars{ .info = gift.info, @@ -52,10 +53,10 @@ public: InnerWidget( QWidget *parent, not_null controller, - not_null user); + not_null peer); - [[nodiscard]] not_null user() const { - return _user; + [[nodiscard]] not_null peer() const { + return _peer; } void saveState(not_null memento); @@ -88,7 +89,7 @@ private: Delegate _delegate; not_null _controller; std::unique_ptr _about; - const not_null _user; + const not_null _peer; std::vector _entries; int _totalCount = 0; @@ -113,32 +114,33 @@ private: InnerWidget::InnerWidget( QWidget *parent, not_null controller, - not_null user) + not_null peer) : BoxContentDivider(parent) , _window(controller->parentController()) , _delegate(_window, GiftButtonMode::Minimal) , _controller(controller) , _about(std::make_unique( this, - (user->isSelf() + (peer->isSelf() ? tr::lng_peer_gifts_about_mine(Ui::Text::RichLangValue) : tr::lng_peer_gifts_about( lt_user, - rpl::single(Ui::Text::Bold(user->shortName())), + rpl::single(Ui::Text::Bold(peer->shortName())), Ui::Text::RichLangValue)), st::giftListAbout)) -, _user(user) -, _totalCount(_user->peerGiftsCount()) -, _api(&_user->session().mtp()) { +, _peer(peer) +, _totalCount(_peer->peerGiftsCount()) +, _api(&_peer->session().mtp()) { _singleMin = _delegate.buttonSize(); - if (user->isSelf()) { + const auto channel = peer->asBroadcast(); + if (peer->isSelf() || (channel && channel->canManageGifts())) { subscribeToUpdates(); } } void InnerWidget::subscribeToUpdates() { - _user->owner().giftUpdates( + _peer->owner().giftUpdates( ) | rpl::start_with_next([=](const Data::GiftUpdate &update) { const auto itemId = [](const Entry &entry) { return FullMsgId(entry.gift.fromId, entry.gift.messageId); @@ -202,11 +204,11 @@ void InnerWidget::paintEvent(QPaintEvent *e) { } void InnerWidget::loadMore() { - if (_allLoaded || _loadMoreRequestId) { - return; + if (_allLoaded || _loadMoreRequestId || !_peer->isUser()) { + return; // todo channel gifts } _loadMoreRequestId = _api.request(MTPpayments_GetUserStarGifts( - _user->inputUser, + _peer->asUser()->inputUser, MTP_string(_offset), MTP_int(kPerPage) )).done([=](const MTPpayments_UserStarGifts &result) { @@ -219,13 +221,13 @@ void InnerWidget::loadMore() { } _totalCount = data.vcount().v; - const auto owner = &_user->owner(); + const auto owner = &_peer->owner(); owner->processUsers(data.vusers()); _entries.reserve(_entries.size() + data.vgifts().v.size()); for (const auto &gift : data.vgifts().v) { - if (auto parsed = Api::FromTL(_user, gift)) { - auto descriptor = DescriptorForGift(_user, *parsed); + if (auto parsed = Api::FromTL(_peer, gift)) { + auto descriptor = DescriptorForGift(_peer, *parsed); _entries.push_back({ .gift = std::move(*parsed), .descriptor = std::move(descriptor), @@ -327,7 +329,7 @@ void InnerWidget::showGift(int index) { _window->show(Box( ::Settings::UserStarGiftBox, _window, - _user, + _peer, _entries[index].gift)); } @@ -373,23 +375,19 @@ void InnerWidget::restoreState(not_null memento) { } } -Memento::Memento(not_null user) -: ContentMemento(user, nullptr, PeerId()) { +Memento::Memento(not_null peer) +: ContentMemento(peer, nullptr, PeerId()) { } Section Memento::section() const { return Section(Section::Type::PeerGifts); } -not_null Memento::user() const { - return peer()->asUser(); -} - object_ptr Memento::createWidget( QWidget *parent, not_null controller, const QRect &geometry) { - auto result = object_ptr(parent, controller, user()); + auto result = object_ptr(parent, controller, peer()); result->setInternalState(geometry, this); return result; } @@ -407,20 +405,20 @@ Memento::~Memento() = default; Widget::Widget( QWidget *parent, not_null controller, - not_null user) + not_null peer) : ContentWidget(parent, controller) { _inner = setInnerWidget(object_ptr( this, controller, - user)); + peer)); } rpl::producer Widget::title() { return tr::lng_peer_gifts_title(); } -not_null Widget::user() const { - return _inner->user(); +not_null Widget::peer() const { + return _inner->peer(); } bool Widget::showInternal(not_null memento) { @@ -428,7 +426,7 @@ bool Widget::showInternal(not_null memento) { return false; } if (auto similarMemento = dynamic_cast(memento.get())) { - if (similarMemento->user() == user()) { + if (similarMemento->peer() == peer()) { restoreState(similarMemento); return true; } @@ -445,7 +443,7 @@ void Widget::setInternalState( } std::shared_ptr Widget::doCreateMemento() { - auto result = std::make_shared(user()); + auto result = std::make_shared(peer()); saveState(result.get()); return result; } diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.h b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.h index 45e83f859..f7cd71001 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.h +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.h @@ -24,7 +24,7 @@ class InnerWidget; class Memento final : public ContentMemento { public: - explicit Memento(not_null user); + explicit Memento(not_null peer); object_ptr createWidget( QWidget *parent, @@ -33,8 +33,6 @@ public: Section section() const override; - [[nodiscard]] not_null user() const; - void setListState(std::unique_ptr state); std::unique_ptr listState(); @@ -50,9 +48,9 @@ public: Widget( QWidget *parent, not_null controller, - not_null user); + not_null peer); - [[nodiscard]] not_null user() const; + [[nodiscard]] not_null peer() const; bool showInternal( not_null memento) override; diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index 03a6cbefa..4ab34cb2b 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -221,12 +221,12 @@ object_ptr InnerWidget::setupSharedMedia( st::infoSharedMediaButtonIconPosition); }; auto addPeerGiftsButton = [&]( - not_null user, + not_null peer, const style::icon &icon) { auto result = Media::AddPeerGiftsButton( content, _controller, - user, + peer, tracker); object_ptr( result, @@ -236,9 +236,7 @@ object_ptr InnerWidget::setupSharedMedia( if (!_topic) { addStoriesButton(_peer, st::infoIconMediaStories); - if (const auto user = _peer->asUser()) { - addPeerGiftsButton(user, st::infoIconMediaGifts); - } + addPeerGiftsButton(_peer, st::infoIconMediaGifts); addSavedSublistButton(_peer, st::infoIconMediaSaved); } addMediaButton(MediaType::Photo, st::infoIconMediaPhoto); diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 79e54aceb..8caddbf0c 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -595,12 +595,12 @@ rpl::producer SavedSublistCountValue( return sublist->fullCountValue(); } -rpl::producer PeerGiftsCountValue(not_null user) { - return user->session().changes().peerFlagsValue( - user, +rpl::producer PeerGiftsCountValue(not_null peer) { + return peer->session().changes().peerFlagsValue( + peer, UpdateFlag::PeerGifts ) | rpl::map([=] { - return user->peerGiftsCount(); + return peer->peerGiftsCount(); }); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.h b/Telegram/SourceFiles/info/profile/info_profile_values.h index 64c6a901e..dab3cf506 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.h +++ b/Telegram/SourceFiles/info/profile/info_profile_values.h @@ -122,7 +122,7 @@ struct LinkWithUrl { [[nodiscard]] rpl::producer SavedSublistCountValue( not_null peer); [[nodiscard]] rpl::producer PeerGiftsCountValue( - not_null user); + not_null peer); [[nodiscard]] rpl::producer CanAddMemberValue( not_null peer); [[nodiscard]] rpl::producer FullReactionsCountValue( diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index 38a65b229..79164c580 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -1748,7 +1748,7 @@ void GlobalStarGiftBox( void UserStarGiftBox( not_null box, not_null controller, - not_null owner, + not_null owner, const Data::UserStarGift &data) { Settings::ReceiptCreditsBox( box, diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.h b/Telegram/SourceFiles/settings/settings_credits_graphics.h index 849d439a9..155b9be63 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.h +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.h @@ -138,7 +138,7 @@ void GlobalStarGiftBox( void UserStarGiftBox( not_null box, not_null controller, - not_null owner, + not_null owner, const Data::UserStarGift &data); void StarGiftViewBox( not_null box,