Support similar bots section.

This commit is contained in:
John Preston 2025-01-10 11:26:07 +04:00
parent 232077b919
commit 6ff5e221ea
17 changed files with 226 additions and 157 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -158,7 +158,7 @@ public:
Media,
GlobalMedia,
CommonGroups,
SimilarChannels,
SimilarPeers,
RequestsList,
ReactionsList,
SavedSublists,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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