Partially implement viewing channel gifts.

This commit is contained in:
John Preston 2025-01-10 18:06:11 +04:00
parent 2fd174ab9c
commit 81001e04e9
15 changed files with 81 additions and 56 deletions

View file

@ -834,7 +834,7 @@ std::optional<Data::StarGift> FromTL(
}
std::optional<Data::UserStarGift> FromTL(
not_null<UserData*> to,
not_null<PeerData*> to,
const MTPuserStarGift &gift) {
const auto session = &to->session();
const auto &data = gift.data();

View file

@ -260,7 +260,7 @@ enum class RequirePremiumState {
not_null<Main::Session*> session,
const MTPstarGift &gift);
[[nodiscard]] std::optional<Data::UserStarGift> FromTL(
not_null<UserData*> to,
not_null<PeerData*> to,
const MTPuserStarGift &gift);
[[nodiscard]] Data::UniqueGiftModel FromTL(

View file

@ -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;

View file

@ -375,6 +375,7 @@ public:
[[nodiscard]] bool canEditAdmin(not_null<UserData*> user) const;
[[nodiscard]] bool canRestrictParticipant(
not_null<PeerData*> 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<Data::UnavailableReason> &&reasons) override;
Flags _flags = ChannelDataFlags(Flag::Forbidden);
int _peerGiftsCount = 0;
PtsWaiter _ptsWaiter;

View file

@ -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

View file

@ -486,6 +486,8 @@ public:
[[nodiscard]] bool hasUnreadStories() const;
void setStoriesState(StoriesState state);
[[nodiscard]] int peerGiftsCount() const;
const PeerId id;
MTPinputPeer input = MTP_inputPeerEmpty();

View file

@ -177,7 +177,7 @@ std::shared_ptr<ContentMemento> Memento::DefaultContent(
case Section::Type::RequestsList:
return std::make_shared<RequestsList::Memento>(peer);
case Section::Type::PeerGifts:
return std::make_shared<PeerGifts::Memento>(peer->asUser());
return std::make_shared<PeerGifts::Memento>(peer);
case Section::Type::SavedSublists:
return std::make_shared<Saved::SublistsMemento>(&peer->session());
case Section::Type::Members:

View file

@ -205,11 +205,11 @@ inline auto AddSavedSublistButton(
inline auto AddPeerGiftsButton(
Ui::VerticalLayout *parent,
not_null<Window::SessionNavigation*> navigation,
not_null<UserData*> user,
not_null<PeerData*> 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<Info::Memento>(
user,
peer,
Section::Type::PeerGifts));
});
return result;

View file

@ -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<UserData*> to,
not_null<PeerData*> to,
const Data::UserStarGift &gift) {
return GiftTypeStars{
.info = gift.info,
@ -52,10 +53,10 @@ public:
InnerWidget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user);
not_null<PeerData*> peer);
[[nodiscard]] not_null<UserData*> user() const {
return _user;
[[nodiscard]] not_null<PeerData*> peer() const {
return _peer;
}
void saveState(not_null<Memento*> memento);
@ -88,7 +89,7 @@ private:
Delegate _delegate;
not_null<Controller*> _controller;
std::unique_ptr<Ui::FlatLabel> _about;
const not_null<UserData*> _user;
const not_null<PeerData*> _peer;
std::vector<Entry> _entries;
int _totalCount = 0;
@ -113,32 +114,33 @@ private:
InnerWidget::InnerWidget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user)
not_null<PeerData*> peer)
: BoxContentDivider(parent)
, _window(controller->parentController())
, _delegate(_window, GiftButtonMode::Minimal)
, _controller(controller)
, _about(std::make_unique<Ui::FlatLabel>(
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::Memento(not_null<UserData*> user)
: ContentMemento(user, nullptr, PeerId()) {
Memento::Memento(not_null<PeerData*> peer)
: ContentMemento(peer, nullptr, PeerId()) {
}
Section Memento::section() const {
return Section(Section::Type::PeerGifts);
}
not_null<UserData*> Memento::user() const {
return peer()->asUser();
}
object_ptr<ContentWidget> Memento::createWidget(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) {
auto result = object_ptr<Widget>(parent, controller, user());
auto result = object_ptr<Widget>(parent, controller, peer());
result->setInternalState(geometry, this);
return result;
}
@ -407,20 +405,20 @@ Memento::~Memento() = default;
Widget::Widget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user)
not_null<PeerData*> peer)
: ContentWidget(parent, controller) {
_inner = setInnerWidget(object_ptr<InnerWidget>(
this,
controller,
user));
peer));
}
rpl::producer<QString> Widget::title() {
return tr::lng_peer_gifts_title();
}
not_null<UserData*> Widget::user() const {
return _inner->user();
not_null<PeerData*> Widget::peer() const {
return _inner->peer();
}
bool Widget::showInternal(not_null<ContentMemento*> memento) {
@ -428,7 +426,7 @@ bool Widget::showInternal(not_null<ContentMemento*> memento) {
return false;
}
if (auto similarMemento = dynamic_cast<Memento*>(memento.get())) {
if (similarMemento->user() == user()) {
if (similarMemento->peer() == peer()) {
restoreState(similarMemento);
return true;
}
@ -445,7 +443,7 @@ void Widget::setInternalState(
}
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {
auto result = std::make_shared<Memento>(user());
auto result = std::make_shared<Memento>(peer());
saveState(result.get());
return result;
}

View file

@ -24,7 +24,7 @@ class InnerWidget;
class Memento final : public ContentMemento {
public:
explicit Memento(not_null<UserData*> user);
explicit Memento(not_null<PeerData*> peer);
object_ptr<ContentWidget> createWidget(
QWidget *parent,
@ -33,8 +33,6 @@ public:
Section section() const override;
[[nodiscard]] not_null<UserData*> user() const;
void setListState(std::unique_ptr<ListState> state);
std::unique_ptr<ListState> listState();
@ -50,9 +48,9 @@ public:
Widget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user);
not_null<PeerData*> peer);
[[nodiscard]] not_null<UserData*> user() const;
[[nodiscard]] not_null<PeerData*> peer() const;
bool showInternal(
not_null<ContentMemento*> memento) override;

View file

@ -221,12 +221,12 @@ object_ptr<Ui::RpWidget> InnerWidget::setupSharedMedia(
st::infoSharedMediaButtonIconPosition);
};
auto addPeerGiftsButton = [&](
not_null<UserData*> user,
not_null<PeerData*> peer,
const style::icon &icon) {
auto result = Media::AddPeerGiftsButton(
content,
_controller,
user,
peer,
tracker);
object_ptr<Profile::FloatingIcon>(
result,
@ -236,9 +236,7 @@ object_ptr<Ui::RpWidget> 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);

View file

@ -595,12 +595,12 @@ rpl::producer<int> SavedSublistCountValue(
return sublist->fullCountValue();
}
rpl::producer<int> PeerGiftsCountValue(not_null<UserData*> user) {
return user->session().changes().peerFlagsValue(
user,
rpl::producer<int> PeerGiftsCountValue(not_null<PeerData*> peer) {
return peer->session().changes().peerFlagsValue(
peer,
UpdateFlag::PeerGifts
) | rpl::map([=] {
return user->peerGiftsCount();
return peer->peerGiftsCount();
});
}

View file

@ -122,7 +122,7 @@ struct LinkWithUrl {
[[nodiscard]] rpl::producer<int> SavedSublistCountValue(
not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<int> PeerGiftsCountValue(
not_null<UserData*> user);
not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<bool> CanAddMemberValue(
not_null<PeerData*> peer);
[[nodiscard]] rpl::producer<int> FullReactionsCountValue(

View file

@ -1748,7 +1748,7 @@ void GlobalStarGiftBox(
void UserStarGiftBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
not_null<UserData*> owner,
not_null<PeerData*> owner,
const Data::UserStarGift &data) {
Settings::ReceiptCreditsBox(
box,

View file

@ -138,7 +138,7 @@ void GlobalStarGiftBox(
void UserStarGiftBox(
not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> controller,
not_null<UserData*> owner,
not_null<PeerData*> owner,
const Data::UserStarGift &data);
void StarGiftViewBox(
not_null<Ui::GenericBox*> box,