Started gifts list in profile.

This commit is contained in:
John Preston 2024-09-20 15:07:01 +04:00
parent 215a262076
commit 4803bd4b3f
15 changed files with 359 additions and 26 deletions

View file

@ -949,6 +949,8 @@ PRIVATE
info/media/info_media_widget.h
info/members/info_members_widget.cpp
info/members/info_members_widget.h
info/peer_gifts/info_peer_gifts_widget.cpp
info/peer_gifts/info_peer_gifts_widget.h
info/polls/info_polls_results_inner_widget.cpp
info/polls/info_polls_results_inner_widget.h
info/polls/info_polls_results_widget.cpp

View file

@ -1323,6 +1323,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_profile_similar_channels#other" = "{count} similar channels";
"lng_profile_saved_messages#one" = "{count} saved message";
"lng_profile_saved_messages#other" = "{count} saved messages";
"lng_profile_peer_gifts#one" = "{count} gift";
"lng_profile_peer_gifts#other" = "{count} gifts";
"lng_profile_participants_section" = "Members";
"lng_profile_subscribers_section" = "Subscribers";
"lng_profile_add_contact" = "Add Contact";
@ -1924,6 +1926,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_similar_channels_premium_all_link" = "Telegram Premium";
"lng_similar_channels_show_more" = "Show more channels";
"lng_peer_gifts_title" = "Gifts";
"lng_premium_gift_duration_months#one" = "for {count} month";
"lng_premium_gift_duration_months#other" = "for {count} months";
"lng_premium_gift_duration_years#one" = "for {count} year";

View file

@ -84,34 +84,35 @@ struct PeerUpdate {
BotCanBeInvited = (1ULL << 22),
BotStartToken = (1ULL << 23),
CommonChats = (1ULL << 24),
HasCalls = (1ULL << 25),
SupportInfo = (1ULL << 26),
IsBot = (1ULL << 27),
EmojiStatus = (1ULL << 28),
BusinessDetails = (1ULL << 29),
Birthday = (1ULL << 30),
PersonalChannel = (1ULL << 31),
PeerGifts = (1ULL << 25),
HasCalls = (1ULL << 26),
SupportInfo = (1ULL << 27),
IsBot = (1ULL << 28),
EmojiStatus = (1ULL << 29),
BusinessDetails = (1ULL << 30),
Birthday = (1ULL << 31),
PersonalChannel = (1ULL << 32),
// For chats and channels
InviteLinks = (1ULL << 32),
Members = (1ULL << 33),
Admins = (1ULL << 34),
BannedUsers = (1ULL << 35),
Rights = (1ULL << 36),
PendingRequests = (1ULL << 37),
Reactions = (1ULL << 38),
InviteLinks = (1ULL << 33),
Members = (1ULL << 34),
Admins = (1ULL << 35),
BannedUsers = (1ULL << 36),
Rights = (1ULL << 37),
PendingRequests = (1ULL << 38),
Reactions = (1ULL << 39),
// For channels
ChannelAmIn = (1ULL << 39),
StickersSet = (1ULL << 40),
EmojiSet = (1ULL << 41),
ChannelLinkedChat = (1ULL << 42),
ChannelLocation = (1ULL << 43),
Slowmode = (1ULL << 44),
GroupCall = (1ULL << 45),
ChannelAmIn = (1ULL << 40),
StickersSet = (1ULL << 41),
EmojiSet = (1ULL << 42),
ChannelLinkedChat = (1ULL << 43),
ChannelLocation = (1ULL << 44),
Slowmode = (1ULL << 45),
GroupCall = (1ULL << 46),
// For iteration
LastUsedBit = (1ULL << 45),
LastUsedBit = (1ULL << 46),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }

View file

@ -130,6 +130,17 @@ void UserData::setCommonChatsCount(int count) {
}
}
int UserData::peerGiftsCount() const {
return _peerGiftsCount;
}
void UserData::setPeerGiftsCount(int count) {
if (_peerGiftsCount != count) {
_peerGiftsCount = count;
session().changes().peerUpdated(this, UpdateFlag::PeerGifts);
}
}
bool UserData::hasPrivateForwardName() const {
return !_privateForwardName.isEmpty();
}
@ -610,6 +621,7 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
: UserData::CallsStatus::Disabled);
user->setAbout(qs(update.vabout().value_or_empty()));
user->setCommonChatsCount(update.vcommon_chats_count().v);
user->setPeerGiftsCount(update.vstargifts_count().value_or_empty());
user->checkFolder(update.vfolder_id().value_or_empty());
user->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
user->setTranslationDisabled(update.is_translations_disabled());

View file

@ -185,9 +185,12 @@ public:
void setBirthday(Data::Birthday value);
void setBirthday(const tl::conditional<MTPBirthday> &value);
int commonChatsCount() const;
[[nodiscard]] int commonChatsCount() const;
void setCommonChatsCount(int count);
[[nodiscard]] int peerGiftsCount() const;
void setPeerGiftsCount(int count);
[[nodiscard]] bool hasPrivateForwardName() const;
[[nodiscard]] QString privateForwardName() const;
void setPrivateForwardName(const QString &name);
@ -222,6 +225,7 @@ private:
Data::LastseenStatus _lastseen;
Data::Birthday _birthday;
int _commonChatsCount = 0;
int _peerGiftsCount = 0;
ContactStatus _contactStatus = ContactStatus::Unknown;
CallsStatus _callsStatus = CallsStatus::Unknown;

View file

@ -473,6 +473,7 @@ infoIconMediaStories: icon {{ "info/info_media_stories", infoIconFg }};
infoIconMediaSaved: icon {{ "info/info_media_saved", infoIconFg }};
infoIconMediaStoriesArchive: icon {{ "info/info_stories_archive", infoIconFg }};
infoIconMediaStoriesRecent: icon {{ "info/info_stories_recent", infoIconFg }};
infoIconMediaGifts: icon {{ "menu/gift_premium", infoIconFg, point(4px, 4px) }};
infoIconShare: icon {{ "info/info_share", infoIconFg }};
infoIconEdit: icon {{ "info/info_edit", infoIconFg }};

View file

@ -127,6 +127,7 @@ public:
CommonGroups,
SimilarChannels,
SavedSublists,
PeerGifts,
Members,
Settings,
Downloads,

View file

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/saved/info_saved_sublists_widget.h"
#include "info/settings/info_settings_widget.h"
#include "info/similar_channels/info_similar_channels_widget.h"
#include "info/peer_gifts/info_peer_gifts_widget.h"
#include "info/polls/info_polls_results_widget.h"
#include "info/info_section_widget.h"
#include "info/info_layer_widget.h"
@ -148,6 +149,8 @@ std::shared_ptr<ContentMemento> Memento::DefaultContent(
case Section::Type::SimilarChannels:
return std::make_shared<SimilarChannels::Memento>(
peer->asChannel());
case Section::Type::PeerGifts:
return std::make_shared<PeerGifts::Memento>(peer->asUser());
case Section::Type::SavedSublists:
return std::make_shared<Saved::SublistsMemento>(&peer->session());
case Section::Type::Members:

View file

@ -203,4 +203,25 @@ inline auto AddSavedSublistButton(
return result;
}
inline auto AddPeerGiftsButton(
Ui::VerticalLayout *parent,
not_null<Window::SessionNavigation*> navigation,
not_null<UserData*> user,
Ui::MultiSlideTracker &tracker) {
auto result = AddCountedButton(
parent,
Profile::PeerGiftsCountValue(user),
[](int count) {
return tr::lng_profile_peer_gifts(tr::now, lt_count, count);
},
tracker)->entity();
result->addClickHandler([=] {
navigation->showSection(
std::make_shared<Info::Memento>(
user,
Section::Type::PeerGifts));
});
return result;
}
} // namespace Info::Media

View file

@ -0,0 +1,177 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "info/peer_gifts/info_peer_gifts_widget.h"
#include "data/data_user.h"
#include "info/info_controller.h"
#include "ui/ui_utility.h"
#include "lang/lang_keys.h"
#include "window/window_session_controller.h"
#include "styles/style_info.h"
namespace Info::PeerGifts {
namespace {
} // namespace
class InnerWidget final : public Ui::RpWidget {
public:
InnerWidget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user);
[[nodiscard]] not_null<UserData*> user() const {
return _user;
}
rpl::producer<Ui::ScrollToRequest> scrollToRequests() const;
int desiredHeight() const;
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
protected:
void visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) override;
private:
const std::shared_ptr<Main::SessionShow> _show;
not_null<Controller*> _controller;
const not_null<UserData*> _user;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
};
InnerWidget::InnerWidget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user)
: RpWidget(parent)
, _show(controller->uiShow())
, _controller(controller)
, _user(user) {
}
void InnerWidget::visibleTopBottomUpdated(
int visibleTop,
int visibleBottom) {
}
void InnerWidget::saveState(not_null<Memento*> memento) {
auto state = std::make_unique<ListState>();
memento->setListState(std::move(state));
}
void InnerWidget::restoreState(not_null<Memento*> memento) {
if (const auto state = memento->listState()) {
}
}
rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
return _scrollToRequests.events();
}
int InnerWidget::desiredHeight() const {
auto desired = 0;
return qMax(height(), desired);
}
Memento::Memento(not_null<UserData*> user)
: ContentMemento(user, 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());
result->setInternalState(geometry, this);
return result;
}
void Memento::setListState(std::unique_ptr<ListState> state) {
_listState = std::move(state);
}
std::unique_ptr<ListState> Memento::listState() {
return std::move(_listState);
}
Memento::~Memento() = default;
Widget::Widget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user)
: ContentWidget(parent, controller) {
_inner = setInnerWidget(object_ptr<InnerWidget>(
this,
controller,
user));
}
rpl::producer<QString> Widget::title() {
return tr::lng_peer_gifts_title();
}
not_null<UserData*> Widget::user() const {
return _inner->user();
}
bool Widget::showInternal(not_null<ContentMemento*> memento) {
if (!controller()->validateMementoPeer(memento)) {
return false;
}
if (auto similarMemento = dynamic_cast<Memento*>(memento.get())) {
if (similarMemento->user() == user()) {
restoreState(similarMemento);
return true;
}
}
return false;
}
void Widget::setInternalState(
const QRect &geometry,
not_null<Memento*> memento) {
setGeometry(geometry);
Ui::SendPendingMoveResizeEvents(this);
restoreState(memento);
}
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {
auto result = std::make_shared<Memento>(user());
saveState(result.get());
return result;
}
void Widget::saveState(not_null<Memento*> memento) {
memento->setScrollTop(scrollTopSave());
_inner->saveState(memento);
}
void Widget::restoreState(not_null<Memento*> memento) {
_inner->restoreState(memento);
scrollTopRestore(memento->scrollTop());
}
} // namespace Info::PeerGifts

View file

@ -0,0 +1,84 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "info/info_content_widget.h"
class UserData;
struct PeerListState;
namespace Info::PeerGifts {
struct ListEntry {
TextWithEntities message;
int64 convertStars = 0;
PeerId fromId = 0;
MsgId messageId = 0;
bool anonymous = false;
bool hidden = false;
};
struct ListState {
std::vector<ListEntry> list;
QString offset;
};
class InnerWidget;
class Memento final : public ContentMemento {
public:
explicit Memento(not_null<UserData*> user);
object_ptr<ContentWidget> createWidget(
QWidget *parent,
not_null<Controller*> controller,
const QRect &geometry) override;
Section section() const override;
[[nodiscard]] not_null<UserData*> user() const;
void setListState(std::unique_ptr<ListState> state);
std::unique_ptr<ListState> listState();
~Memento();
private:
std::unique_ptr<ListState> _listState;
};
class Widget final : public ContentWidget {
public:
Widget(
QWidget *parent,
not_null<Controller*> controller,
not_null<UserData*> user);
[[nodiscard]] not_null<UserData*> user() const;
bool showInternal(
not_null<ContentMemento*> memento) override;
void setInternalState(
const QRect &geometry,
not_null<Memento*> memento);
rpl::producer<QString> title() override;
private:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
std::shared_ptr<ContentMemento> doCreateMemento() override;
InnerWidget *_inner = nullptr;
};
} // namespace Info::PeerGifts

View file

@ -231,6 +231,19 @@ object_ptr<Ui::RpWidget> InnerWidget::setupSharedMedia(
icon,
st::infoSharedMediaButtonIconPosition);
};
auto addPeerGiftsButton = [&](
not_null<UserData*> user,
const style::icon &icon) {
auto result = Media::AddPeerGiftsButton(
content,
_controller,
user,
tracker);
object_ptr<Profile::FloatingIcon>(
result,
icon,
st::infoSharedMediaButtonIconPosition);
};
if (!_topic) {
addStoriesButton(_peer, st::infoIconMediaStories);
@ -245,6 +258,7 @@ object_ptr<Ui::RpWidget> InnerWidget::setupSharedMedia(
addMediaButton(MediaType::GIF, st::infoIconMediaGif);
if (const auto user = _peer->asUser()) {
addCommonGroupsButton(user, st::infoIconMediaGroup);
addPeerGiftsButton(user, st::infoIconMediaGifts);
} else if (const auto channel = _peer->asChannel()) {
addSimilarChannelsButton(channel, st::infoIconMediaChannel);
}

View file

@ -581,6 +581,15 @@ rpl::producer<int> SavedSublistCountValue(
return sublist->fullCountValue();
}
rpl::producer<int> PeerGiftsCountValue(not_null<UserData*> user) {
return user->session().changes().peerFlagsValue(
user,
UpdateFlag::PeerGifts
) | rpl::map([=] {
return user->peerGiftsCount();
});
}
rpl::producer<bool> CanAddMemberValue(not_null<PeerData*> peer) {
if (const auto chat = peer->asChat()) {
return peer->session().changes().peerFlagsValue(

View file

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

View file

@ -990,9 +990,7 @@ void ReceiptCreditsBox(
rpl::single(e.description),
st::creditsBoxAbout)));
}
if (isStarGift && !canConvert) {
// Nothing
} else if (isStarGift) {
if (isStarGift) {
Ui::AddSkip(content);
const auto about = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(