mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Support similar bots section.
This commit is contained in:
parent
232077b919
commit
6ff5e221ea
17 changed files with 226 additions and 157 deletions
|
@ -1014,8 +1014,8 @@ PRIVATE
|
|||
info/saved/info_saved_sublists_widget.h
|
||||
info/settings/info_settings_widget.cpp
|
||||
info/settings/info_settings_widget.h
|
||||
info/similar_channels/info_similar_channels_widget.cpp
|
||||
info/similar_channels/info_similar_channels_widget.h
|
||||
info/similar_peers/info_similar_peers_widget.cpp
|
||||
info/similar_peers/info_similar_peers_widget.h
|
||||
info/statistics/info_statistics_common.h
|
||||
info/statistics/info_statistics_inner_widget.cpp
|
||||
info/statistics/info_statistics_inner_widget.h
|
||||
|
|
|
@ -1346,6 +1346,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_profile_common_groups#other" = "{count} groups in common";
|
||||
"lng_profile_similar_channels#one" = "{count} similar channel";
|
||||
"lng_profile_similar_channels#other" = "{count} similar channels";
|
||||
"lng_profile_similar_bots#one" = "{count} similar bot";
|
||||
"lng_profile_similar_bots#other" = "{count} similar bots";
|
||||
"lng_profile_saved_messages#one" = "{count} saved message";
|
||||
"lng_profile_saved_messages#other" = "{count} saved messages";
|
||||
"lng_profile_peer_gifts#one" = "{count} gift";
|
||||
|
@ -2108,6 +2110,11 @@ 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_similar_bots_title" = "Similar bots";
|
||||
"lng_similar_bots_premium_all#one" = "Subscribe to {link} to unlock up to **{count}** similar bot.";
|
||||
"lng_similar_bots_premium_all#other" = "Subscribe to {link} to unlock up to **{count}** similar bots.";
|
||||
"lng_similar_bots_show_more" = "Show more bots";
|
||||
|
||||
"lng_peer_gifts_title" = "Gifts";
|
||||
"lng_peer_gifts_about" = "These gifts were sent to {user} by other users.";
|
||||
"lng_peer_gifts_about_mine" = "These gifts were sent to you by other users. Click on a gift to convert it to Stars or change its privacy settings.";
|
||||
|
|
|
@ -211,11 +211,10 @@ void ApplyBotsList(
|
|||
Data::PeerUpdate::Flag::FullInfo);
|
||||
}
|
||||
|
||||
[[nodiscard]] ChatParticipants::Channels ParseSimilar(
|
||||
[[nodiscard]] ChatParticipants::Peers ParseSimilarChannels(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPmessages_Chats &chats) {
|
||||
auto result = ChatParticipants::Channels();
|
||||
std::vector<not_null<ChannelData*>>();
|
||||
auto result = ChatParticipants::Peers();
|
||||
chats.match([&](const auto &data) {
|
||||
const auto &list = data.vchats().v;
|
||||
result.list.reserve(list.size());
|
||||
|
@ -234,10 +233,29 @@ void ApplyBotsList(
|
|||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] ChatParticipants::Channels ParseSimilar(
|
||||
[[nodiscard]] ChatParticipants::Peers ParseSimilarChannels(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPmessages_Chats &chats) {
|
||||
return ParseSimilar(&channel->session(), chats);
|
||||
return ParseSimilarChannels(&channel->session(), chats);
|
||||
}
|
||||
|
||||
[[nodiscard]] ChatParticipants::Peers ParseSimilarBots(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPusers_Users &users) {
|
||||
auto result = ChatParticipants::Peers();
|
||||
users.match([&](const auto &data) {
|
||||
const auto &list = data.vusers().v;
|
||||
result.list.reserve(list.size());
|
||||
for (const auto &user : list) {
|
||||
result.list.push_back(session->data().processUser(user));
|
||||
}
|
||||
if constexpr (MTPDusers_usersSlice::Is<decltype(data)>()) {
|
||||
if (session->premiumPossible()) {
|
||||
result.more = data.vcount().v - data.vusers().v.size();
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -782,52 +800,65 @@ void ChatParticipants::unblock(
|
|||
_kickRequests.emplace(kick, requestId);
|
||||
}
|
||||
|
||||
void ChatParticipants::loadSimilarChannels(not_null<ChannelData*> channel) {
|
||||
if (!channel->isBroadcast()) {
|
||||
return;
|
||||
} else if (const auto i = _similar.find(channel); i != end(_similar)) {
|
||||
void ChatParticipants::loadSimilarPeers(not_null<PeerData*> peer) {
|
||||
if (const auto i = _similar.find(peer); i != end(_similar)) {
|
||||
if (i->second.requestId
|
||||
|| !i->second.channels.more
|
||||
|| !channel->session().premium()) {
|
||||
|| !i->second.peers.more
|
||||
|| !peer->session().premium()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
using Flag = MTPchannels_GetChannelRecommendations::Flag;
|
||||
_similar[channel].requestId = _api.request(
|
||||
MTPchannels_GetChannelRecommendations(
|
||||
MTP_flags(Flag::f_channel),
|
||||
channel->inputChannel)
|
||||
).done([=](const MTPmessages_Chats &result) {
|
||||
auto &similar = _similar[channel];
|
||||
similar.requestId = 0;
|
||||
auto parsed = ParseSimilar(channel, result);
|
||||
if (similar.channels == parsed) {
|
||||
return;
|
||||
}
|
||||
similar.channels = std::move(parsed);
|
||||
if (const auto history = channel->owner().historyLoaded(channel)) {
|
||||
if (const auto item = history->joinedMessageInstance()) {
|
||||
history->owner().requestItemResize(item);
|
||||
if (const auto channel = peer->asBroadcast()) {
|
||||
using Flag = MTPchannels_GetChannelRecommendations::Flag;
|
||||
_similar[peer].requestId = _api.request(
|
||||
MTPchannels_GetChannelRecommendations(
|
||||
MTP_flags(Flag::f_channel),
|
||||
channel->inputChannel)
|
||||
).done([=](const MTPmessages_Chats &result) {
|
||||
auto &similar = _similar[channel];
|
||||
similar.requestId = 0;
|
||||
auto parsed = ParseSimilarChannels(channel, result);
|
||||
if (similar.peers == parsed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_similarLoaded.fire_copy(channel);
|
||||
}).send();
|
||||
similar.peers = std::move(parsed);
|
||||
if (const auto history = channel->owner().historyLoaded(channel)) {
|
||||
if (const auto item = history->joinedMessageInstance()) {
|
||||
history->owner().requestItemResize(item);
|
||||
}
|
||||
}
|
||||
_similarLoaded.fire_copy(channel);
|
||||
}).send();
|
||||
} else if (const auto bot = peer->asBot()) {
|
||||
_similar[peer].requestId = _api.request(
|
||||
MTPbots_GetBotRecommendations(bot->inputUser)
|
||||
).done([=](const MTPusers_Users &result) {
|
||||
auto &similar = _similar[peer];
|
||||
similar.requestId = 0;
|
||||
auto parsed = ParseSimilarBots(&peer->session(), result);
|
||||
if (similar.peers == parsed) {
|
||||
return;
|
||||
}
|
||||
similar.peers = std::move(parsed);
|
||||
_similarLoaded.fire_copy(peer);
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
|
||||
auto ChatParticipants::similar(not_null<ChannelData*> channel)
|
||||
-> const Channels & {
|
||||
const auto i = channel->isBroadcast()
|
||||
? _similar.find(channel)
|
||||
auto ChatParticipants::similar(not_null<PeerData*> peer)
|
||||
-> const Peers & {
|
||||
const auto i = (peer->isBroadcast() || peer->isBot())
|
||||
? _similar.find(peer)
|
||||
: end(_similar);
|
||||
if (i != end(_similar)) {
|
||||
return i->second.channels;
|
||||
return i->second.peers;
|
||||
}
|
||||
static const auto empty = Channels();
|
||||
static const auto empty = Peers();
|
||||
return empty;
|
||||
}
|
||||
|
||||
auto ChatParticipants::similarLoaded() const
|
||||
-> rpl::producer<not_null<ChannelData*>> {
|
||||
-> rpl::producer<not_null<PeerData*>> {
|
||||
return _similarLoaded.events();
|
||||
}
|
||||
|
||||
|
@ -841,15 +872,15 @@ void ChatParticipants::loadRecommendations() {
|
|||
MTP_inputChannelEmpty())
|
||||
).done([=](const MTPmessages_Chats &result) {
|
||||
_recommendations.requestId = 0;
|
||||
auto parsed = ParseSimilar(_session, result);
|
||||
_recommendations.channels = std::move(parsed);
|
||||
_recommendations.channels.more = 0;
|
||||
auto parsed = ParseSimilarChannels(_session, result);
|
||||
_recommendations.peers = std::move(parsed);
|
||||
_recommendations.peers.more = 0;
|
||||
_recommendationsLoaded = true;
|
||||
}).send();
|
||||
}
|
||||
|
||||
const ChatParticipants::Channels &ChatParticipants::recommendations() const {
|
||||
return _recommendations.channels;
|
||||
const ChatParticipants::Peers &ChatParticipants::recommendations() const {
|
||||
return _recommendations.peers;
|
||||
}
|
||||
|
||||
rpl::producer<> ChatParticipants::recommendationsLoaded() const {
|
||||
|
|
|
@ -138,27 +138,27 @@ public:
|
|||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> participant);
|
||||
|
||||
void loadSimilarChannels(not_null<ChannelData*> channel);
|
||||
void loadSimilarPeers(not_null<PeerData*> peer);
|
||||
|
||||
struct Channels {
|
||||
std::vector<not_null<ChannelData*>> list;
|
||||
struct Peers {
|
||||
std::vector<not_null<PeerData*>> list;
|
||||
int more = 0;
|
||||
|
||||
friend inline bool operator==(
|
||||
const Channels &,
|
||||
const Channels &) = default;
|
||||
const Peers &,
|
||||
const Peers &) = default;
|
||||
};
|
||||
[[nodiscard]] const Channels &similar(not_null<ChannelData*> channel);
|
||||
[[nodiscard]] const Peers &similar(not_null<PeerData*> peer);
|
||||
[[nodiscard]] auto similarLoaded() const
|
||||
-> rpl::producer<not_null<ChannelData*>>;
|
||||
-> rpl::producer<not_null<PeerData*>>;
|
||||
|
||||
void loadRecommendations();
|
||||
[[nodiscard]] const Channels &recommendations() const;
|
||||
[[nodiscard]] const Peers &recommendations() const;
|
||||
[[nodiscard]] rpl::producer<> recommendationsLoaded() const;
|
||||
|
||||
private:
|
||||
struct SimilarChannels {
|
||||
Channels channels;
|
||||
struct SimilarPeers {
|
||||
Peers peers;
|
||||
mtpRequestId requestId = 0;
|
||||
};
|
||||
|
||||
|
@ -186,10 +186,10 @@ private:
|
|||
not_null<PeerData*>>;
|
||||
base::flat_map<KickRequest, mtpRequestId> _kickRequests;
|
||||
|
||||
base::flat_map<not_null<ChannelData*>, SimilarChannels> _similar;
|
||||
rpl::event_stream<not_null<ChannelData*>> _similarLoaded;
|
||||
base::flat_map<not_null<PeerData*>, SimilarPeers> _similar;
|
||||
rpl::event_stream<not_null<PeerData*>> _similarLoaded;
|
||||
|
||||
SimilarChannels _recommendations;
|
||||
SimilarPeers _recommendations;
|
||||
rpl::variable<bool> _recommendationsLoaded = false;
|
||||
|
||||
};
|
||||
|
|
|
@ -1772,7 +1772,7 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
|
|||
_channelAmInRequests.emplace(channel, requestId);
|
||||
|
||||
using Flag = ChannelDataFlag;
|
||||
chatParticipants().loadSimilarChannels(channel);
|
||||
chatParticipants().loadSimilarPeers(channel);
|
||||
channel->setFlags(channel->flags() | Flag::SimilarExpanded);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -911,6 +911,16 @@ void PeerData::fullUpdated() {
|
|||
setLoadedStatus(LoadedStatus::Full);
|
||||
}
|
||||
|
||||
UserData *PeerData::asBot() {
|
||||
return isBot() ? static_cast<UserData*>(this) : nullptr;
|
||||
}
|
||||
|
||||
const UserData *PeerData::asBot() const {
|
||||
return isBot()
|
||||
? static_cast<const UserData*>(this)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
UserData *PeerData::asUser() {
|
||||
return isUser() ? static_cast<UserData*>(this) : nullptr;
|
||||
}
|
||||
|
@ -1131,6 +1141,13 @@ EmojiStatusId PeerData::emojiStatusId() const {
|
|||
return _emojiStatusId;
|
||||
}
|
||||
|
||||
bool PeerData::isBot() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->isBot();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PeerData::isSelf() const {
|
||||
if (const auto user = asUser()) {
|
||||
return (user->flags() & UserDataFlag::Self);
|
||||
|
|
|
@ -218,6 +218,7 @@ public:
|
|||
[[nodiscard]] bool isChannel() const {
|
||||
return peerIsChannel(id);
|
||||
}
|
||||
[[nodiscard]] bool isBot() const;
|
||||
[[nodiscard]] bool isSelf() const;
|
||||
[[nodiscard]] bool isVerified() const;
|
||||
[[nodiscard]] bool isPremium() const;
|
||||
|
@ -267,6 +268,8 @@ public:
|
|||
[[nodiscard]] int slowmodeSecondsLeft() const;
|
||||
[[nodiscard]] bool canManageGroupCall() const;
|
||||
|
||||
[[nodiscard]] UserData *asBot();
|
||||
[[nodiscard]] const UserData *asBot() const;
|
||||
[[nodiscard]] UserData *asUser();
|
||||
[[nodiscard]] const UserData *asUser() const;
|
||||
[[nodiscard]] ChatData *asChat();
|
||||
|
|
|
@ -18,7 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "info/similar_channels/info_similar_channels_widget.h"
|
||||
#include "info/similar_peers/info_similar_peers_widget.h"
|
||||
#include "info/info_controller.h"
|
||||
#include "info/info_memento.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
@ -37,7 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace HistoryView {
|
||||
namespace {
|
||||
|
||||
using Channels = Api::ChatParticipants::Channels;
|
||||
using Channels = Api::ChatParticipants::Peers;
|
||||
|
||||
//void SimilarChannelsController::prepare() {
|
||||
// for (const auto &channel : _channels.list) {
|
||||
|
@ -86,7 +86,7 @@ using Channels = Api::ChatParticipants::Channels;
|
|||
strong->showSection(
|
||||
std::make_shared<Info::Memento>(
|
||||
channel,
|
||||
Info::Section::Type::SimilarChannels));
|
||||
Info::Section::Type::SimilarPeers));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -519,7 +519,7 @@ QSize SimilarChannels::countOptimalSize() {
|
|||
_channels.clear();
|
||||
_moreThumbnails = {};
|
||||
const auto api = &channel->session().api();
|
||||
api->chatParticipants().loadSimilarChannels(channel);
|
||||
api->chatParticipants().loadSimilarPeers(channel);
|
||||
const auto premium = channel->session().premium();
|
||||
const auto &similar = api->chatParticipants().similar(channel);
|
||||
_empty = similar.list.empty() ? 1 : 0;
|
||||
|
@ -543,9 +543,14 @@ QSize SimilarChannels::countOptimalSize() {
|
|||
? limit
|
||||
: int(similar.list.size());
|
||||
const auto more = similar.more + int(similar.list.size() - take);
|
||||
auto &&channels = ranges::views::all(similar.list)
|
||||
auto &&peers = ranges::views::all(similar.list)
|
||||
| ranges::views::take(limit);
|
||||
for (const auto &channel : channels) {
|
||||
for (const auto &peer : peers) {
|
||||
const auto channel = peer->asBroadcast();
|
||||
if (!channel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto moreCounter = (_channels.size() + 1 == take) ? more : 0;
|
||||
_channels.push_back({
|
||||
.geometry = QRect(QPoint(x, y), outer.size()),
|
||||
|
@ -566,8 +571,8 @@ QSize SimilarChannels::countOptimalSize() {
|
|||
: channel->openLink();
|
||||
|
||||
const auto counter = moreCounter
|
||||
? moreCounter :
|
||||
channel->membersCount();
|
||||
? moreCounter
|
||||
: channel->membersCount();
|
||||
if (moreCounter || counter > 1) {
|
||||
last.counter = (moreCounter ? u"+"_q : QString())
|
||||
+ Lang::FormatCountToShort(counter).string;
|
||||
|
|
|
@ -477,6 +477,7 @@ infoIconMediaAudio: icon {{ "info/info_media_audio", infoIconFg }};
|
|||
infoIconMediaLink: icon {{ "info/info_media_link", infoIconFg }};
|
||||
infoIconMediaGroup: icon {{ "info/info_common_groups", infoIconFg }};
|
||||
infoIconMediaChannel: icon {{ "menu/channel", infoIconFg, point(4px, 4px) }};
|
||||
infoIconMediaBot: icon {{ "menu/bot", infoIconFg, point(4px, 4px) }};
|
||||
infoIconMediaVoice: icon {{ "info/info_media_voice", infoIconFg }};
|
||||
infoIconMediaStories: icon {{ "info/info_media_stories", infoIconFg }};
|
||||
infoIconMediaSaved: icon {{ "info/info_media_saved", infoIconFg }};
|
||||
|
|
|
@ -158,7 +158,7 @@ public:
|
|||
Media,
|
||||
GlobalMedia,
|
||||
CommonGroups,
|
||||
SimilarChannels,
|
||||
SimilarPeers,
|
||||
RequestsList,
|
||||
ReactionsList,
|
||||
SavedSublists,
|
||||
|
|
|
@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "info/common_groups/info_common_groups_widget.h"
|
||||
#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/similar_peers/info_similar_peers_widget.h"
|
||||
#include "info/reactions_list/info_reactions_list_widget.h"
|
||||
#include "info/requests_list/info_requests_list_widget.h"
|
||||
#include "info/peer_gifts/info_peer_gifts_widget.h"
|
||||
|
@ -172,9 +172,8 @@ std::shared_ptr<ContentMemento> Memento::DefaultContent(
|
|||
section.mediaType());
|
||||
case Section::Type::CommonGroups:
|
||||
return std::make_shared<CommonGroups::Memento>(peer->asUser());
|
||||
case Section::Type::SimilarChannels:
|
||||
return std::make_shared<SimilarChannels::Memento>(
|
||||
peer->asChannel());
|
||||
case Section::Type::SimilarPeers:
|
||||
return std::make_shared<SimilarPeers::Memento>(peer);
|
||||
case Section::Type::RequestsList:
|
||||
return std::make_shared<RequestsList::Memento>(peer);
|
||||
case Section::Type::PeerGifts:
|
||||
|
|
|
@ -131,26 +131,25 @@ inline auto AddCommonGroupsButton(
|
|||
return result;
|
||||
}
|
||||
|
||||
inline auto AddSimilarChannelsButton(
|
||||
inline auto AddSimilarPeersButton(
|
||||
Ui::VerticalLayout *parent,
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
not_null<ChannelData*> channel,
|
||||
not_null<PeerData*> peer,
|
||||
Ui::MultiSlideTracker &tracker) {
|
||||
auto result = AddCountedButton(
|
||||
parent,
|
||||
Profile::SimilarChannelsCountValue(channel),
|
||||
[](int count) {
|
||||
return tr::lng_profile_similar_channels(
|
||||
tr::now,
|
||||
lt_count,
|
||||
count);
|
||||
Profile::SimilarPeersCountValue(peer),
|
||||
[=](int count) {
|
||||
return peer->isBroadcast()
|
||||
? tr::lng_profile_similar_channels(tr::now, lt_count, count)
|
||||
: tr::lng_profile_similar_bots(tr::now, lt_count, count);
|
||||
},
|
||||
tracker)->entity();
|
||||
result->addClickHandler([=] {
|
||||
navigation->showSection(
|
||||
std::make_shared<Info::Memento>(
|
||||
channel,
|
||||
Section::Type::SimilarChannels));
|
||||
peer,
|
||||
Section::Type::SimilarPeers));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -178,13 +178,13 @@ object_ptr<Ui::RpWidget> InnerWidget::setupSharedMedia(
|
|||
icon,
|
||||
st::infoSharedMediaButtonIconPosition);
|
||||
};
|
||||
const auto addSimilarChannelsButton = [&](
|
||||
not_null<ChannelData*> channel,
|
||||
const auto addSimilarPeersButton = [&](
|
||||
not_null<PeerData*> peer,
|
||||
const style::icon &icon) {
|
||||
auto result = Media::AddSimilarChannelsButton(
|
||||
auto result = Media::AddSimilarPeersButton(
|
||||
content,
|
||||
_controller,
|
||||
channel,
|
||||
peer,
|
||||
tracker);
|
||||
object_ptr<Profile::FloatingIcon>(
|
||||
result,
|
||||
|
@ -248,10 +248,12 @@ object_ptr<Ui::RpWidget> InnerWidget::setupSharedMedia(
|
|||
addMediaButton(MediaType::Link, st::infoIconMediaLink);
|
||||
addMediaButton(MediaType::RoundVoiceFile, st::infoIconMediaVoice);
|
||||
addMediaButton(MediaType::GIF, st::infoIconMediaGif);
|
||||
if (const auto user = _peer->asUser()) {
|
||||
if (const auto bot = _peer->asBot()) {
|
||||
addSimilarPeersButton(bot, st::infoIconMediaBot);
|
||||
} else if (const auto channel = _peer->asBroadcast()) {
|
||||
addSimilarPeersButton(channel, st::infoIconMediaChannel);
|
||||
} else if (const auto user = _peer->asUser()) {
|
||||
addCommonGroupsButton(user, st::infoIconMediaGroup);
|
||||
} else if (const auto channel = _peer->asChannel()) {
|
||||
addSimilarChannelsButton(channel, st::infoIconMediaChannel);
|
||||
}
|
||||
|
||||
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
|
|
|
@ -570,16 +570,16 @@ rpl::producer<int> CommonGroupsCountValue(not_null<UserData*> user) {
|
|||
});
|
||||
}
|
||||
|
||||
rpl::producer<int> SimilarChannelsCountValue(
|
||||
not_null<ChannelData*> channel) {
|
||||
const auto participants = &channel->session().api().chatParticipants();
|
||||
participants->loadSimilarChannels(channel);
|
||||
return rpl::single(channel) | rpl::then(
|
||||
rpl::producer<int> SimilarPeersCountValue(
|
||||
not_null<PeerData*> peer) {
|
||||
const auto participants = &peer->session().api().chatParticipants();
|
||||
participants->loadSimilarPeers(peer);
|
||||
return rpl::single(peer) | rpl::then(
|
||||
participants->similarLoaded()
|
||||
) | rpl::filter(
|
||||
rpl::mappers::_1 == channel
|
||||
rpl::mappers::_1 == peer
|
||||
) | rpl::map([=] {
|
||||
const auto &similar = participants->similar(channel);
|
||||
const auto &similar = participants->similar(peer);
|
||||
return int(similar.list.size()) + similar.more;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -117,8 +117,8 @@ struct LinkWithUrl {
|
|||
Storage::SharedMediaType type);
|
||||
[[nodiscard]] rpl::producer<int> CommonGroupsCountValue(
|
||||
not_null<UserData*> user);
|
||||
[[nodiscard]] rpl::producer<int> SimilarChannelsCountValue(
|
||||
not_null<ChannelData*> channel);
|
||||
[[nodiscard]] rpl::producer<int> SimilarPeersCountValue(
|
||||
not_null<PeerData*> peer);
|
||||
[[nodiscard]] rpl::producer<int> SavedSublistCountValue(
|
||||
not_null<PeerData*> peer);
|
||||
[[nodiscard]] rpl::producer<int> PeerGiftsCountValue(
|
||||
|
|
|
@ -5,7 +5,7 @@ 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/similar_channels/info_similar_channels_widget.h"
|
||||
#include "info/similar_peers/info_similar_peers_widget.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_peer_values.h"
|
||||
#include "data/data_premium_limits.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "info/info_controller.h"
|
||||
#include "main/main_session.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
|
@ -27,14 +28,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "styles/style_info.h"
|
||||
#include "styles/style_widgets.h"
|
||||
|
||||
namespace Info::SimilarChannels {
|
||||
namespace Info::SimilarPeers {
|
||||
namespace {
|
||||
|
||||
class ListController final : public PeerListController {
|
||||
public:
|
||||
ListController(
|
||||
not_null<Controller*> controller,
|
||||
not_null<ChannelData*> channel);
|
||||
not_null<PeerData*> peer);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void prepare() override;
|
||||
|
@ -60,7 +61,7 @@ private:
|
|||
struct SavedState : SavedStateBase {
|
||||
};
|
||||
const not_null<Controller*> _controller;
|
||||
const not_null<ChannelData*> _channel;
|
||||
const not_null<PeerData*> _peer;
|
||||
Ui::RpWidget *_content = nullptr;
|
||||
Ui::RpWidget *_unlock = nullptr;
|
||||
rpl::variable<int> _unlockHeight;
|
||||
|
@ -69,14 +70,14 @@ private:
|
|||
|
||||
ListController::ListController(
|
||||
not_null<Controller*> controller,
|
||||
not_null<ChannelData*> channel)
|
||||
not_null<PeerData*> peer)
|
||||
: PeerListController()
|
||||
, _controller(controller)
|
||||
, _channel(channel) {
|
||||
, _peer(peer) {
|
||||
}
|
||||
|
||||
Main::Session &ListController::session() const {
|
||||
return _channel->session();
|
||||
return _peer->session();
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> ListController::createRow(
|
||||
|
@ -95,20 +96,22 @@ std::unique_ptr<PeerListRow> ListController::createRow(
|
|||
}
|
||||
|
||||
void ListController::prepare() {
|
||||
delegate()->peerListSetTitle(tr::lng_similar_channels_title());
|
||||
delegate()->peerListSetTitle(_peer->isBroadcast()
|
||||
? tr::lng_similar_channels_title()
|
||||
: tr::lng_similar_bots_title());
|
||||
|
||||
const auto participants = &_channel->session().api().chatParticipants();
|
||||
const auto participants = &_peer->session().api().chatParticipants();
|
||||
|
||||
Data::AmPremiumValue(
|
||||
&_channel->session()
|
||||
&_peer->session()
|
||||
) | rpl::start_with_next([=] {
|
||||
participants->loadSimilarChannels(_channel);
|
||||
participants->loadSimilarPeers(_peer);
|
||||
rebuild();
|
||||
}, lifetime());
|
||||
|
||||
participants->similarLoaded(
|
||||
) | rpl::filter(
|
||||
rpl::mappers::_1 == _channel
|
||||
rpl::mappers::_1 == _peer
|
||||
) | rpl::start_with_next([=] {
|
||||
rebuild();
|
||||
}, lifetime());
|
||||
|
@ -123,16 +126,16 @@ rpl::producer<int> ListController::unlockHeightValue() const {
|
|||
}
|
||||
|
||||
void ListController::rebuild() {
|
||||
const auto participants = &_channel->session().api().chatParticipants();
|
||||
const auto &list = participants->similar(_channel);
|
||||
for (const auto channel : list.list) {
|
||||
if (!delegate()->peerListFindRow(channel->id.value)) {
|
||||
delegate()->peerListAppendRow(createRow(channel));
|
||||
const auto participants = &_peer->session().api().chatParticipants();
|
||||
const auto &list = participants->similar(_peer);
|
||||
for (const auto peer : list.list) {
|
||||
if (!delegate()->peerListFindRow(peer->id.value)) {
|
||||
delegate()->peerListAppendRow(createRow(peer));
|
||||
}
|
||||
}
|
||||
if (!list.more
|
||||
|| _channel->session().premium()
|
||||
|| !_channel->session().premiumPossible()) {
|
||||
|| _peer->session().premium()
|
||||
|| !_peer->session().premiumPossible()) {
|
||||
delete base::take(_unlock);
|
||||
_unlockHeight = 0;
|
||||
} else if (!_unlock) {
|
||||
|
@ -149,7 +152,9 @@ void ListController::setupUnlock() {
|
|||
|
||||
const auto button = ::Settings::CreateLockedButton(
|
||||
_unlock,
|
||||
tr::lng_similar_channels_show_more(),
|
||||
(_peer->isBroadcast()
|
||||
? tr::lng_similar_channels_show_more()
|
||||
: tr::lng_similar_bots_show_more()),
|
||||
st::similarChannelsLock,
|
||||
rpl::single(true));
|
||||
button->setClickedCallback([=] {
|
||||
|
@ -158,16 +163,18 @@ void ListController::setupUnlock() {
|
|||
});
|
||||
|
||||
const auto upto = Data::PremiumLimits(
|
||||
&_channel->session()).similarChannelsPremium();
|
||||
&_peer->session()).similarChannelsPremium();
|
||||
const auto about = Ui::CreateChild<Ui::FlatLabel>(
|
||||
_unlock,
|
||||
tr::lng_similar_channels_premium_all(
|
||||
lt_count,
|
||||
rpl::single(upto * 1.),
|
||||
lt_link,
|
||||
tr::lng_similar_channels_premium_all_link(
|
||||
) | Ui::Text::ToBold() | Ui::Text::ToLink(),
|
||||
Ui::Text::RichLangValue),
|
||||
(_peer->isBroadcast()
|
||||
? tr::lng_similar_channels_premium_all
|
||||
: tr::lng_similar_bots_premium_all)(
|
||||
lt_count,
|
||||
rpl::single(upto * 1.),
|
||||
lt_link,
|
||||
tr::lng_similar_channels_premium_all_link(
|
||||
) | Ui::Text::ToBold() | Ui::Text::ToLink(),
|
||||
Ui::Text::RichLangValue),
|
||||
st::similarChannelsLockAbout);
|
||||
about->setClickHandlerFilter([=](const auto &...) {
|
||||
const auto window = _controller->parentController();
|
||||
|
@ -177,7 +184,9 @@ void ListController::setupUnlock() {
|
|||
|
||||
rpl::combine(
|
||||
_content->sizeValue(),
|
||||
tr::lng_similar_channels_show_more()
|
||||
(_peer->isBroadcast()
|
||||
? tr::lng_similar_channels_show_more()
|
||||
: tr::lng_similar_bots_show_more())
|
||||
) | rpl::start_with_next([=](QSize size, const auto &) {
|
||||
auto top = st::similarChannelsLockFade
|
||||
+ st::similarChannelsLockPadding.top();
|
||||
|
@ -263,10 +272,10 @@ public:
|
|||
InnerWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
not_null<ChannelData*> channel);
|
||||
not_null<PeerData*> peer);
|
||||
|
||||
[[nodiscard]] not_null<ChannelData*> channel() const {
|
||||
return _channel;
|
||||
[[nodiscard]] not_null<PeerData*> peer() const {
|
||||
return _peer;
|
||||
}
|
||||
|
||||
rpl::producer<Ui::ScrollToRequest> scrollToRequests() const;
|
||||
|
@ -305,7 +314,7 @@ private:
|
|||
|
||||
const std::shared_ptr<Main::SessionShow> _show;
|
||||
not_null<Controller*> _controller;
|
||||
const not_null<ChannelData*> _channel;
|
||||
const not_null<PeerData*> _peer;
|
||||
std::unique_ptr<ListController> _listController;
|
||||
object_ptr<ListWidget> _list;
|
||||
|
||||
|
@ -316,12 +325,12 @@ private:
|
|||
InnerWidget::InnerWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
not_null<ChannelData*> channel)
|
||||
not_null<PeerData*> peer)
|
||||
: RpWidget(parent)
|
||||
, _show(controller->uiShow())
|
||||
, _controller(controller)
|
||||
, _channel(channel)
|
||||
, _listController(std::make_unique<ListController>(controller, _channel))
|
||||
, _peer(peer)
|
||||
, _listController(std::make_unique<ListController>(controller, _peer))
|
||||
, _list(setupList(this, _listController.get())) {
|
||||
setContent(_list.data());
|
||||
_listController->setDelegate(static_cast<PeerListDelegate*>(this));
|
||||
|
@ -428,23 +437,19 @@ std::shared_ptr<Main::SessionShow> InnerWidget::peerListUiShow() {
|
|||
return _show;
|
||||
}
|
||||
|
||||
Memento::Memento(not_null<ChannelData*> channel)
|
||||
: ContentMemento(channel, nullptr, PeerId()) {
|
||||
Memento::Memento(not_null<PeerData*> peer)
|
||||
: ContentMemento(peer, nullptr, PeerId()) {
|
||||
}
|
||||
|
||||
Section Memento::section() const {
|
||||
return Section(Section::Type::SimilarChannels);
|
||||
}
|
||||
|
||||
not_null<ChannelData*> Memento::channel() const {
|
||||
return peer()->asChannel();
|
||||
return Section(Section::Type::SimilarPeers);
|
||||
}
|
||||
|
||||
object_ptr<ContentWidget> Memento::createWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
const QRect &geometry) {
|
||||
auto result = object_ptr<Widget>(parent, controller, channel());
|
||||
auto result = object_ptr<Widget>(parent, controller, peer());
|
||||
result->setInternalState(geometry, this);
|
||||
return result;
|
||||
}
|
||||
|
@ -462,20 +467,22 @@ Memento::~Memento() = default;
|
|||
Widget::Widget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
not_null<ChannelData*> channel)
|
||||
not_null<PeerData*> peer)
|
||||
: ContentWidget(parent, controller) {
|
||||
_inner = setInnerWidget(object_ptr<InnerWidget>(
|
||||
this,
|
||||
controller,
|
||||
channel));
|
||||
peer));
|
||||
}
|
||||
|
||||
rpl::producer<QString> Widget::title() {
|
||||
return tr::lng_similar_channels_title();
|
||||
return peer()->isBroadcast()
|
||||
? tr::lng_similar_channels_title()
|
||||
: tr::lng_similar_bots_title();
|
||||
}
|
||||
|
||||
not_null<ChannelData*> Widget::channel() const {
|
||||
return _inner->channel();
|
||||
not_null<PeerData*> Widget::peer() const {
|
||||
return _inner->peer();
|
||||
}
|
||||
|
||||
bool Widget::showInternal(not_null<ContentMemento*> memento) {
|
||||
|
@ -483,7 +490,7 @@ bool Widget::showInternal(not_null<ContentMemento*> memento) {
|
|||
return false;
|
||||
}
|
||||
if (auto similarMemento = dynamic_cast<Memento*>(memento.get())) {
|
||||
if (similarMemento->channel() == channel()) {
|
||||
if (similarMemento->peer() == peer()) {
|
||||
restoreState(similarMemento);
|
||||
return true;
|
||||
}
|
||||
|
@ -500,7 +507,7 @@ void Widget::setInternalState(
|
|||
}
|
||||
|
||||
std::shared_ptr<ContentMemento> Widget::doCreateMemento() {
|
||||
auto result = std::make_shared<Memento>(channel());
|
||||
auto result = std::make_shared<Memento>(peer());
|
||||
saveState(result.get());
|
||||
return result;
|
||||
}
|
||||
|
@ -515,4 +522,4 @@ void Widget::restoreState(not_null<Memento*> memento) {
|
|||
scrollTopRestore(memento->scrollTop());
|
||||
}
|
||||
|
||||
} // namespace Info::SimilarChannels
|
||||
} // namespace Info::SimilarPeers
|
|
@ -9,16 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "info/info_content_widget.h"
|
||||
|
||||
class ChannelData;
|
||||
class PeerData;
|
||||
struct PeerListState;
|
||||
|
||||
namespace Info::SimilarChannels {
|
||||
namespace Info::SimilarPeers {
|
||||
|
||||
class InnerWidget;
|
||||
|
||||
class Memento final : public ContentMemento {
|
||||
public:
|
||||
explicit Memento(not_null<ChannelData*> channel);
|
||||
explicit Memento(not_null<PeerData*> peer);
|
||||
|
||||
object_ptr<ContentWidget> createWidget(
|
||||
QWidget *parent,
|
||||
|
@ -27,8 +27,6 @@ public:
|
|||
|
||||
Section section() const override;
|
||||
|
||||
[[nodiscard]] not_null<ChannelData*> channel() const;
|
||||
|
||||
void setListState(std::unique_ptr<PeerListState> state);
|
||||
std::unique_ptr<PeerListState> listState();
|
||||
|
||||
|
@ -44,9 +42,9 @@ public:
|
|||
Widget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
not_null<ChannelData*> channel);
|
||||
not_null<PeerData*> peer);
|
||||
|
||||
[[nodiscard]] not_null<ChannelData*> channel() const;
|
||||
[[nodiscard]] not_null<PeerData*> peer() const;
|
||||
|
||||
bool showInternal(
|
||||
not_null<ContentMemento*> memento) override;
|
||||
|
@ -67,4 +65,4 @@ private:
|
|||
|
||||
};
|
||||
|
||||
} // namespace Info::SimilarChannels
|
||||
} // namespace Info::SimilarPeers
|
Loading…
Add table
Reference in a new issue