Initial forum support in bots data classes.

This commit is contained in:
John Preston
2025-09-05 14:23:06 +04:00
parent 6974c511ea
commit b4d1ba07a6
40 changed files with 369 additions and 182 deletions
@@ -159,6 +159,7 @@ void MessagesSearch::searchReceived(
// Don't apply cached data!
owner.processUsers(data.vusers());
owner.processChats(data.vchats());
_history->peer->processTopics(data.vtopics());
}
auto items = HistoryItemsFromTL(&owner, data.vmessages().v);
const auto total = int(data.vmessages().v.size());
@@ -168,6 +169,7 @@ void MessagesSearch::searchReceived(
// Don't apply cached data!
owner.processUsers(data.vusers());
owner.processChats(data.vchats());
_history->peer->processTopics(data.vtopics());
}
auto items = HistoryItemsFromTL(&owner, data.vmessages().v);
// data.vnext_rate() is used only in global search.
@@ -178,17 +180,14 @@ void MessagesSearch::searchReceived(
// Don't apply cached data!
owner.processUsers(data.vusers());
owner.processChats(data.vchats());
}
if (const auto channel = _history->peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
if (_requestId != 0) {
// Don't apply cached data!
channel->processTopics(data.vtopics());
if (const auto channel = _history->peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
} else {
LOG(("API Error: "
"received messages.channelMessages when no channel "
"was passed!"));
}
} else {
LOG(("API Error: "
"received messages.channelMessages when no channel "
"was passed!"));
_history->peer->processTopics(data.vtopics());
}
auto items = HistoryItemsFromTL(&owner, data.vmessages().v);
const auto total = int(data.vcount().v);
+8 -3
View File
@@ -362,6 +362,9 @@ void ApiWrap::savePinnedOrder(Data::Folder *folder) {
}
void ApiWrap::savePinnedOrder(not_null<Data::Forum*> forum) {
if (!forum->channel()) {
return;
}
const auto &order = _session->data().pinnedChatsOrder(forum);
const auto input = [](Dialogs::Key key) {
if (const auto topic = key.topic()) {
@@ -1889,7 +1892,7 @@ void ApiWrap::sendNotifySettingsUpdates() {
for (const auto topic : base::take(_updateNotifyTopics)) {
request(MTPaccount_UpdateNotifySettings(
MTP_inputNotifyForumTopic(
topic->channel()->input,
topic->peer()->input,
MTP_int(topic->rootId())),
topic->notify().serialize()
)).afterDelay(kSmallDelayMs).send();
@@ -3054,18 +3057,20 @@ void ApiWrap::requestMessageAfterDate(
return &messages.vmessages().v;
};
const auto list = result.match([&](
const MTPDmessages_messages &data) {
const MTPDmessages_messages &data) {
peer->processTopics(data.vtopics());
return handleMessages(data);
}, [&](const MTPDmessages_messagesSlice &data) {
peer->processTopics(data.vtopics());
return handleMessages(data);
}, [&](const MTPDmessages_channelMessages &data) {
if (const auto channel = peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
channel->processTopics(data.vtopics());
} else {
LOG(("API Error: received messages.channelMessages when "
"no channel was passed! (ApiWrap::jumpToDate)"));
}
peer->processTopics(data.vtopics());
return handleMessages(data);
}, [&](const MTPDmessages_messagesNotModified &) {
LOG(("API Error: received messages.messagesNotModified! "
@@ -983,7 +983,7 @@ void ChooseTopicSearchController::searchQuery(const QString &query) {
void ChooseTopicSearchController::searchOnServer() {
_requestId = _api.request(MTPmessages_GetForumTopics(
MTP_flags(MTPmessages_GetForumTopics::Flag::f_q),
_forum->channel()->input,
_forum->peer()->input,
MTP_string(_query),
MTP_int(_offsetDate),
MTP_int(_offsetId),
@@ -560,7 +560,7 @@ void EditForumTopicBox(
state->requestId = api->request(MTPmessages_EditForumTopic(
MTP_flags(Flag::f_title
| (topic->isGeneral() ? Flag() : Flag::f_icon_emoji_id)),
topic->channel()->input,
topic->peer()->input,
MTP_int(rootId),
MTP_string(title->getLastText().trimmed()),
MTP_long(state->iconId.current()),
+1 -1
View File
@@ -1392,7 +1392,7 @@ Window::Controller *Application::windowForShowingHistory(
Window::Controller *Application::windowForShowingForum(
not_null<Data::Forum*> forum) const {
const auto tabs = forum->channel()->useSubsectionTabs();
const auto tabs = forum->bot() || forum->peer()->useSubsectionTabs();
const auto id = Window::SeparateId(
tabs ? Window::SeparateType::Chat : Window::SeparateType::Forum,
forum->history());
@@ -1182,12 +1182,6 @@ void ChannelData::setStoriesState(StoriesState state) {
}
}
void ChannelData::processTopics(const MTPVector<MTPForumTopic> &topics) {
if (const auto forum = this->forum()) {
forum->applyReceivedTopics(topics);
}
}
int ChannelData::levelHint() const {
return _levelHint;
}
-2
View File
@@ -545,8 +545,6 @@ public:
return mgInfo ? mgInfo->monoforum() : nullptr;
}
void processTopics(const MTPVector<MTPForumTopic> &topics);
[[nodiscard]] int levelHint() const;
void updateLevelHint(int levelHint);
+30 -10
View File
@@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_forum_icons.h"
#include "data/data_forum_topic.h"
#include "data/data_replies_list.h"
#include "data/data_user.h"
#include "data/notify/data_notify_settings.h"
#include "history/history.h"
#include "history/history_item.h"
@@ -48,12 +49,13 @@ constexpr auto kShowTopicNamesCount = 8;
Forum::Forum(not_null<History*> history)
: _history(history)
, _topicsList(&session(), {}, owner().maxPinnedChatsLimitValue(this)) {
Expects(_history->peer->isChannel());
Expects(_history->peer->isChannel()
|| _history->peer->isBot());
if (_history->inChatList()) {
preloadTopics();
}
if (channel()->canCreateTopics()) {
if (peer()->canCreateTopics()) {
owner().forumIcons().requestDefaultIfUnknown();
}
}
@@ -98,7 +100,15 @@ not_null<History*> Forum::history() const {
return _history;
}
not_null<ChannelData*> Forum::channel() const {
not_null<PeerData*> Forum::peer() const {
return _history->peer;
}
UserData *Forum::bot() const {
return _history->peer->asBot();
}
ChannelData *Forum::channel() const {
return _history->peer->asChannel();
}
@@ -107,6 +117,14 @@ not_null<Dialogs::MainList*> Forum::topicsList() {
}
rpl::producer<> Forum::destroyed() const {
if (const auto bot = this->bot()) {
return bot->flagsValue(
) | rpl::filter([=](const UserData::Flags::Change &update) {
using Flag = UserData::Flag;
return (update.diff & Flag::Forum)
&& !(update.value & Flag::Forum);
}) | rpl::take(1) | rpl::to_empty;
}
return channel()->flagsValue(
) | rpl::filter([=](const ChannelData::Flags::Change &update) {
using Flag = ChannelData::Flag;
@@ -144,7 +162,7 @@ void Forum::requestTopics() {
const auto loadCount = firstLoad ? kTopicsFirstLoad : kTopicsPerPage;
_requestId = session().api().request(MTPmessages_GetForumTopics(
MTP_flags(0),
channel()->input,
peer()->input,
MTPstring(), // q
MTP_int(_offset.date),
MTP_int(_offset.id),
@@ -169,7 +187,7 @@ void Forum::requestTopics() {
}).fail([=](const MTP::Error &error) {
_requestId = 0;
_topicsList.setLoaded();
if (error.type() == u"CHANNEL_FORUM_MISSING"_q) {
if (error.type() == u"CHANNEL_FORUM_MISSING"_q && channel()) {
const auto flags = channel()->flags() & ~ChannelDataFlag::Forum;
channel()->setFlags(flags);
}
@@ -280,7 +298,7 @@ Thread *Forum::activeSubsectionThread() const {
}
void Forum::markUnreadCountsUnknown(MsgId readTillId) {
if (!channel()->useSubsectionTabs()) {
if (!peer()->useSubsectionTabs()) {
return;
}
for (const auto &[rootId, topic] : _topics) {
@@ -294,7 +312,7 @@ void Forum::markUnreadCountsUnknown(MsgId readTillId) {
void Forum::updateUnreadCounts(
MsgId readTillId,
const base::flat_map<not_null<ForumTopic*>, int> &counts) {
if (!channel()->useSubsectionTabs()) {
if (!peer()->useSubsectionTabs()) {
return;
}
for (const auto &[rootId, topic] : _topics) {
@@ -331,7 +349,9 @@ void Forum::applyReceivedTopics(
owner().processUsers(data.vusers());
owner().processChats(data.vchats());
owner().processMessages(data.vmessages(), NewMessageType::Existing);
channel()->ptsReceived(data.vpts().v);
if (const auto channel = this->channel()) {
channel->ptsReceived(data.vpts().v);
}
applyReceivedTopics(data.vtopics(), std::move(callback));
if (!_staleRootIds.empty()) {
requestSomeStale();
@@ -405,7 +425,7 @@ void Forum::requestSomeStale() {
Fn<void()> finish) {
return session().api().request(
MTPmessages_GetForumTopicsByID(
channel()->input,
peer()->input,
MTP_vector<MTPint>(rootIds))
).done([=](const MTPmessages_ForumTopics &result) {
_staleRequestId = 0;
@@ -439,7 +459,7 @@ void Forum::requestTopic(MsgId rootId, Fn<void()> done) {
if (!request.id
&& _staleRootIds.emplace(rootId).second
&& (_staleRootIds.size() == 1)) {
crl::on_main(&session(), [peer = channel()] {
crl::on_main(&session(), [peer = peer()] {
if (const auto forum = peer->forum()) {
forum->requestSomeStale();
}
+3 -1
View File
@@ -41,8 +41,10 @@ public:
[[nodiscard]] Session &owner() const;
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] not_null<PeerData*> peer() const;
[[nodiscard]] not_null<History*> history() const;
[[nodiscard]] not_null<ChannelData*> channel() const;
[[nodiscard]] UserData *bot() const;
[[nodiscard]] ChannelData *channel() const;
[[nodiscard]] not_null<Dialogs::MainList*> topicsList();
[[nodiscard]] rpl::producer<> destroyed() const;
[[nodiscard]] auto topicDestroyed() const
+21 -9
View File
@@ -265,7 +265,15 @@ std::shared_ptr<Data::RepliesList> ForumTopic::replies() const {
return _replies;
}
not_null<ChannelData*> ForumTopic::channel() const {
not_null<PeerData*> ForumTopic::peer() const {
return _forum->peer();
}
UserData *ForumTopic::bot() const {
return _forum->bot();
}
ChannelData *ForumTopic::channel() const {
return _forum->channel();
}
@@ -308,14 +316,18 @@ bool ForumTopic::my() const {
}
bool ForumTopic::canEdit() const {
return my() || channel()->canManageTopics();
return my() || peer()->canManageTopics();
}
bool ForumTopic::canDelete() const {
if (creating() || isGeneral()) {
return false;
} else if (channel()->canDeleteMessages()) {
} else if (bot()) {
return true;
} else if (const auto channel = this->channel()) {
if (channel->canDeleteMessages()) {
return true;
}
}
return my() && replies()->canDeleteMyTopic();
}
@@ -325,7 +337,7 @@ bool ForumTopic::canToggleClosed() const {
}
bool ForumTopic::canTogglePinned() const {
return !creating() && channel()->canManageTopics();
return !creating() && peer()->canManageTopics();
}
bool ForumTopic::creating() const {
@@ -405,7 +417,7 @@ void ForumTopic::applyTopic(const MTPDforumTopic &data) {
draft->match([&](const MTPDdraftMessage &data) {
Data::ApplyPeerCloudDraft(
&session(),
channel()->id,
peer()->id,
_rootId,
PeerId(),
data);
@@ -465,12 +477,12 @@ void ForumTopic::setClosedAndSave(bool closed) {
const auto weak = base::make_weak(this);
api->request(MTPmessages_EditForumTopic(
MTP_flags(MTPmessages_EditForumTopic::Flag::f_closed),
channel()->input,
peer()->input,
MTP_int(_rootId),
MTPstring(), // title
MTPlong(), // icon_emoji_id
MTP_bool(closed),
MTPBool() // hidden
MTPBool() // hiddenKO
)).done([=](const MTPUpdates &result) {
api->applyUpdates(result);
}).fail([=](const MTP::Error &error) {
@@ -527,7 +539,7 @@ int ForumTopic::chatListNameVersion() const {
void ForumTopic::applyTopicTopMessage(MsgId topMessageId) {
if (topMessageId) {
growLastKnownServerMessageId(topMessageId);
const auto itemId = FullMsgId(channel()->id, topMessageId);
const auto itemId = FullMsgId(peer()->id, topMessageId);
if (const auto item = owner().message(itemId)) {
setLastServerMessage(item);
resolveChatListMessageGroup();
@@ -895,7 +907,7 @@ Dialogs::BadgesState ForumTopic::chatListBadgesState() const {
Dialogs::CountInBadge::Messages,
Dialogs::IncludeInBadge::All);
if (!result.unread && _replies->inboxReadTillId() < 2) {
result.unread = channel()->amIn()
result.unread = (bot() || (channel() && channel()->amIn()))
&& (_lastKnownServerMessageId > history()->inboxReadTillId());
result.unreadMuted = muted();
}
+3 -1
View File
@@ -91,7 +91,9 @@ public:
}
[[nodiscard]] std::shared_ptr<RepliesList> replies() const;
[[nodiscard]] not_null<ChannelData*> channel() const;
[[nodiscard]] not_null<PeerData*> peer() const;
[[nodiscard]] UserData *bot() const;
[[nodiscard]] ChannelData *channel() const;
[[nodiscard]] not_null<History*> history() const;
[[nodiscard]] not_null<Forum*> forum() const;
[[nodiscard]] rpl::producer<> destroyed() const;
@@ -548,6 +548,7 @@ void Histories::requestFakeChatListMessage(
_fakeChatListRequests.erase(history);
history->setFakeChatListMessageFrom(MTP_messages_messages(
MTP_vector<MTPMessage>(0),
MTP_vector<MTPForumTopic>(0),
MTP_vector<MTPChat>(0),
MTP_vector<MTPUser>(0)));
finish();
+34 -4
View File
@@ -693,7 +693,9 @@ bool PeerData::canCreateTodoLists() const {
}
bool PeerData::canCreateTopics() const {
if (const auto channel = asChannel()) {
if (const auto bot = asBot()) {
return bot->isForum();
} else if (const auto channel = asChannel()) {
return channel->isForum()
&& !channel->amRestricted(ChatRestriction::CreateTopics);
}
@@ -701,7 +703,9 @@ bool PeerData::canCreateTopics() const {
}
bool PeerData::canManageTopics() const {
if (const auto channel = asChannel()) {
if (const auto bot = asBot()) {
return bot->isForum();
} else if (const auto channel = asChannel()) {
return channel->isForum()
&& (channel->amCreator()
|| (channel->adminRights() & ChatAdminRight::ManageTopics));
@@ -1436,7 +1440,9 @@ bool PeerData::isBroadcast() const {
}
bool PeerData::isForum() const {
if (const auto channel = asChannel()) {
if (const auto bot = asBot()) {
return bot->isForum();
} else if (const auto channel = asChannel()) {
return channel->isForum();
}
return false;
@@ -1517,7 +1523,9 @@ Ui::BotVerifyDetails *PeerData::botVerifyDetails() const {
}
Data::Forum *PeerData::forum() const {
if (const auto channel = asChannel()) {
if (const auto bot = asBot()) {
return bot->forum();
} else if (const auto channel = asChannel()) {
return channel->forum();
}
return nullptr;
@@ -1549,6 +1557,28 @@ Data::SavedSublist *PeerData::monoforumSublistFor(
return nullptr;
}
bool PeerData::useSubsectionTabs() const {
if (const auto bot = asBot()) {
return bot->isForum();
} else if (const auto channel = asChannel()) {
return channel->useSubsectionTabs();
}
return false;
}
bool PeerData::viewForumAsMessages() const {
if (const auto channel = asChannel()) {
return channel->viewForumAsMessages();
}
return false;
}
void PeerData::processTopics(const MTPVector<MTPForumTopic> &topics) {
if (const auto forum = this->forum()) {
forum->applyReceivedTopics(topics);
}
}
bool PeerData::allowsForwarding() const {
if (isUser()) {
return true;
+4
View File
@@ -271,6 +271,10 @@ public:
[[nodiscard]] Data::SavedSublist *monoforumSublistFor(
PeerId sublistPeerId) const;
[[nodiscard]] bool useSubsectionTabs() const;
[[nodiscard]] bool viewForumAsMessages() const;
void processTopics(const MTPVector<MTPForumTopic> &topics);
[[nodiscard]] Data::PeerNotifySettings &notify() {
return _notify;
}
+25 -24
View File
@@ -182,30 +182,31 @@ inline auto DefaultRestrictionValue(
| Flag::HasLink
| Flag::Forbidden
| Flag::Creator;
const auto channel = topic->channel();
return rpl::combine(
PeerFlagsValue(channel.get(), mask),
RestrictionsValue(channel, rights),
DefaultRestrictionsValue(channel, rights),
AdminRightsValue(channel, ChatAdminRight::ManageTopics),
topic->session().changes().topicFlagsValue(
topic,
TopicUpdate::Flag::Closed),
[=](
ChannelDataFlags flags,
ChatRestrictions sendRestriction,
ChatRestrictions defaultSendRestriction,
auto,
auto) {
const auto notAmInFlags = Flag::Left | Flag::Forbidden;
const auto allowed = !(flags & notAmInFlags)
|| ((flags & Flag::HasLink)
&& !(flags & Flag::JoinToWrite));
return allowed
&& ((flags & Flag::Creator)
|| (!sendRestriction && !defaultSendRestriction))
&& (!topic->closed() || topic->canToggleClosed());
});
if (const auto channel = topic->channel()) {
return rpl::combine(
PeerFlagsValue(channel, mask),
RestrictionsValue(channel, rights),
DefaultRestrictionsValue(channel, rights),
AdminRightsValue(channel, ChatAdminRight::ManageTopics),
topic->session().changes().topicFlagsValue(
topic,
TopicUpdate::Flag::Closed),
[=](
ChannelDataFlags flags,
ChatRestrictions sendRestriction,
ChatRestrictions defaultSendRestriction,
auto,
auto) {
const auto notAmInFlags = Flag::Left | Flag::Forbidden;
const auto allowed = !(flags & notAmInFlags)
|| ((flags & Flag::HasLink)
&& !(flags & Flag::JoinToWrite));
return allowed
&& ((flags & Flag::Creator)
|| (!sendRestriction && !defaultSendRestriction))
&& (!topic->closed() || topic->canToggleClosed());
});
}
}
return CanSendAnyOfValue(thread->peer(), rights, forbidInForums);
}
@@ -691,17 +691,19 @@ bool RepliesList::processMessagesIsEmpty(const MTPmessages_Messages &result) {
"(HistoryWidget::messagesReceived)"));
return 0;
}, [&](const MTPDmessages_messages &data) {
_history->peer->processTopics(data.vtopics());
return int(data.vmessages().v.size());
}, [&](const MTPDmessages_messagesSlice &data) {
_history->peer->processTopics(data.vtopics());
return data.vcount().v;
}, [&](const MTPDmessages_channelMessages &data) {
if (const auto channel = _history->peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
channel->processTopics(data.vtopics());
} else {
LOG(("API Error: received messages.channelMessages when "
"no channel was passed! (HistoryWidget::messagesReceived)"));
}
_history->peer->processTopics(data.vtopics());
return data.vcount().v;
});
@@ -372,17 +372,19 @@ bool SavedSublist::processMessagesIsEmpty(
"(HistoryWidget::messagesReceived)"));
return 0;
}, [&](const MTPDmessages_messages &data) {
owningHistory()->peer->processTopics(data.vtopics());
return int(data.vmessages().v.size());
}, [&](const MTPDmessages_messagesSlice &data) {
owningHistory()->peer->processTopics(data.vtopics());
return data.vcount().v;
}, [&](const MTPDmessages_channelMessages &data) {
if (const auto channel = owningHistory()->peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
channel->processTopics(data.vtopics());
} else {
LOG(("API Error: received messages.channelMessages when "
"no channel was passed! (HistoryWidget::messagesReceived)"));
}
owningHistory()->peer->processTopics(data.vtopics());
return data.vcount().v;
});
@@ -205,6 +205,7 @@ SearchResult ParseSearchResult(
auto &d = data.c_messages_messages();
peer->owner().processUsers(d.vusers());
peer->owner().processChats(d.vchats());
peer->processTopics(d.vtopics());
result.fullCount = d.vmessages().v.size();
return &d.vmessages().v;
} break;
@@ -213,21 +214,22 @@ SearchResult ParseSearchResult(
auto &d = data.c_messages_messagesSlice();
peer->owner().processUsers(d.vusers());
peer->owner().processChats(d.vchats());
peer->processTopics(d.vtopics());
result.fullCount = d.vcount().v;
return &d.vmessages().v;
} break;
case mtpc_messages_channelMessages: {
const auto &d = data.c_messages_channelMessages();
peer->owner().processUsers(d.vusers());
peer->owner().processChats(d.vchats());
if (const auto channel = peer->asChannel()) {
channel->ptsReceived(d.vpts().v);
channel->processTopics(d.vtopics());
} else {
LOG(("API Error: received messages.channelMessages when "
"no channel was passed! (ParseSearchResult)"));
}
peer->owner().processUsers(d.vusers());
peer->owner().processChats(d.vchats());
peer->processTopics(d.vtopics());
result.fullCount = d.vcount().v;
return &d.vmessages().v;
} break;
+30 -12
View File
@@ -397,15 +397,24 @@ void Session::clear() {
// We must clear all [mono]forums before clearing customEmojiManager.
// Because in Data::ForumTopic an Ui::Text::CustomEmoji is cached.
auto forums = base::flat_set<not_null<ChannelData*>>();
auto botForums = base::flat_set<not_null<UserData*>>();
auto channelForums = base::flat_set<not_null<ChannelData*>>();
for (const auto &[peerId, peer] : _peers) {
if (const auto bot = peer->asBot()) {
if (bot->isForum()) {
botForums.emplace(bot);
}
}
if (const auto channel = peer->asChannel()) {
if (channel->isForum() || channel->amMonoforumAdmin()) {
forums.emplace(channel);
channelForums.emplace(channel);
}
}
}
for (const auto &channel : forums) {
for (const auto &bot : botForums) {
bot->setFlags(bot->flags() & ~UserDataFlag::Forum);
}
for (const auto &channel : channelForums) {
channel->setFlags(channel->flags()
& ~(ChannelDataFlag::Forum | ChannelDataFlag::MonoforumAdmin));
}
@@ -564,6 +573,7 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
| Flag::Scam
| Flag::Fake
| Flag::BotInlineGeo
| Flag::Forum
| Flag::Premium
| Flag::Support
| Flag::HasRequirePremiumToWrite
@@ -590,6 +600,7 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
| (data.is_scam() ? Flag::Scam : Flag())
| (data.is_fake() ? Flag::Fake : Flag())
| (data.is_bot_inline_geo() ? Flag::BotInlineGeo : Flag())
| (data.is_bot_forum_view() ? Flag::Forum : Flag())
| (data.is_premium() ? Flag::Premium : Flag())
| (data.is_support() ? Flag::Support : Flag())
| (hasRequirePremiumToWrite
@@ -2681,15 +2692,6 @@ void Session::processMessages(
void Session::processExistingMessages(
ChannelData *channel,
const MTPmessages_Messages &data) {
data.match([&](const MTPDmessages_channelMessages &data) {
if (channel) {
channel->ptsReceived(data.vpts().v);
channel->processTopics(data.vtopics());
} else {
LOG(("App Error: received messages.channelMessages!"));
}
}, [](const auto &) {});
data.match([&](const MTPDmessages_messagesNotModified&) {
LOG(("API Error: received messages.messagesNotModified!"));
}, [&](const auto &data) {
@@ -2697,6 +2699,19 @@ void Session::processExistingMessages(
processChats(data.vchats());
processMessages(data.vmessages(), NewMessageType::Existing);
});
data.match([&](const MTPDmessages_channelMessages &data) {
if (channel) {
channel->ptsReceived(data.vpts().v);
} else {
LOG(("App Error: received messages.channelMessages!"));
}
}, [](const auto &) {});
data.match([&](const MTPDmessages_messagesNotModified&) {
}, [&](const auto &data) {
if (channel) {
channel->processTopics(data.vtopics());
}
});
}
const Session::Messages *Session::messagesList(PeerId peerId) const {
@@ -5174,6 +5189,9 @@ void Session::saveViewAsMessages(
not_null<Forum*> forum,
bool viewAsMessages) {
const auto channel = forum->channel();
if (!channel) {
return;
}
if (const auto requestId = _viewAsMessagesRequests.take(channel)) {
_session->api().request(*requestId).cancel();
}
+45 -2
View File
@@ -20,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/business/data_business_info.h"
#include "data/components/credits.h"
#include "data/data_cloud_themes.h"
#include "data/data_forum.h"
#include "data/data_forum_icons.h"
#include "data/data_saved_music.h"
#include "data/data_session.h"
#include "data/data_changes.h"
@@ -84,6 +86,28 @@ bool ApplyBotVerifierSettings(
BotInfo::BotInfo() = default;
BotInfo::~BotInfo() = default;
void BotInfo::ensureForum(not_null<UserData*> that) {
if (!_forum) {
const auto history = that->owner().history(that);
_forum = std::make_unique<Data::Forum>(history);
history->forumChanged(nullptr);
}
}
Data::Forum *BotInfo::forum() const {
return _forum.get();
}
std::unique_ptr<Data::Forum> BotInfo::takeForumData() {
if (auto result = base::take(_forum)) {
result->history()->forumChanged(result.get());
return result;
}
return nullptr;
}
Data::LastseenStatus LastseenFromMTP(
const MTPUserStatus &status,
Data::LastseenStatus currentStatus) {
@@ -471,12 +495,31 @@ void UserData::setAccessHash(uint64 accessHash) {
}
void UserData::setFlags(UserDataFlags which) {
if ((which & UserDataFlag::Deleted)
!= (flags() & UserDataFlag::Deleted)) {
if (!isBot()) {
which &= ~UserDataFlag::Forum;
}
const auto diff = flags() ^ which;
if (diff & UserDataFlag::Deleted) {
invalidateEmptyUserpic();
}
// Let Data::Forum live till the end of _flags.set.
// That way the data can be used in changes handler.
// Example: render frame for forum auto-closing animation.
const auto takenForum = (botInfo
&& (diff & Flag::Forum)
&& !(which & Flag::Forum))
? botInfo->takeForumData()
: nullptr;
if ((diff & Flag::Forum) && (which & Flag::Forum)) {
if (const auto info = botInfo.get()) {
info->ensureForum(this);
}
}
_flags.set((flags() & UserDataFlag::Self)
| (which & ~UserDataFlag::Self));
if (const auto raw = takenForum.get()) {
owner().forumIcons().clearUserpicsReset(raw);
}
}
void UserData::addFlags(UserDataFlags which) {
+17
View File
@@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/flags.h"
namespace Data {
class Forum;
struct BotCommand;
struct BusinessDetails;
} // namespace Data
@@ -55,6 +56,11 @@ struct BotVerifierSettings {
struct BotInfo {
BotInfo();
~BotInfo();
void ensureForum(not_null<UserData*> that);
[[nodiscard]] Data::Forum *forum() const;
[[nodiscard]] std::unique_ptr<Data::Forum> takeForumData();
QString description;
QString inlinePlaceholder;
@@ -92,6 +98,10 @@ struct BotInfo {
bool canManageEmojiStatus : 1 = false;
bool supportsBusiness : 1 = false;
bool hasMainApp : 1 = false;
private:
std::unique_ptr<Data::Forum> _forum;
};
enum class UserDataFlag : uint32 {
@@ -122,6 +132,7 @@ enum class UserDataFlag : uint32 {
MessageMoneyRestrictionsKnown = (1 << 24),
ReadDatesPrivate = (1 << 25),
StoriesCorrespondent = (1 << 26),
Forum = (1ULL << 27),
};
inline constexpr bool is_flag_type(UserDataFlag) { return true; };
using UserDataFlags = base::flags<UserDataFlag>;
@@ -188,6 +199,12 @@ public:
[[nodiscard]] bool messageMoneyRestrictionsKnown() const;
[[nodiscard]] bool canSendIgnoreMoneyRestrictions() const;
[[nodiscard]] bool readDatesPrivate() const;
[[nodiscard]] bool isForum() const {
return flags() & Flag::Forum;
}
[[nodiscard]] Data::Forum *forum() const {
return botInfo ? botInfo->forum() : nullptr;
}
void setStoriesCorrespondent(bool is);
[[nodiscard]] bool storiesCorrespondent() const;
+14 -7
View File
@@ -340,6 +340,16 @@ void WebPageData::ApplyChanges(
not_null<Main::Session*> session,
ChannelData *channel,
const MTPmessages_Messages &result) {
const auto list = result.match([](
const MTPDmessages_messagesNotModified &) {
LOG(("API Error: received messages.messagesNotModified! "
"(WebPageData::ApplyChanges)"));
return static_cast<const QVector<MTPMessage>*>(nullptr);
}, [&](const auto &data) {
session->data().processUsers(data.vusers());
session->data().processChats(data.vchats());
return &data.vmessages().v;
});
result.match([&](
const MTPDmessages_channelMessages &data) {
if (channel) {
@@ -351,15 +361,12 @@ void WebPageData::ApplyChanges(
}
}, [&](const auto &) {
});
const auto list = result.match([](
result.match([](
const MTPDmessages_messagesNotModified &) {
LOG(("API Error: received messages.messagesNotModified! "
"(WebPageData::ApplyChanges)"));
return static_cast<const QVector<MTPMessage>*>(nullptr);
}, [&](const auto &data) {
session->data().processUsers(data.vusers());
session->data().processChats(data.vchats());
return &data.vmessages().v;
if (channel) {
channel->processTopics(data.vtopics());
}
});
if (!list) {
return;
@@ -96,7 +96,7 @@ void NotifySettings::request(not_null<Thread*> thread) {
if (topic->notify().settingsUnknown()) {
topic->session().api().requestNotifySettings(
MTP_inputNotifyForumTopic(
topic->channel()->input,
topic->peer()->input,
MTP_int(topic->rootId())));
}
}
@@ -507,7 +507,7 @@ bool NotifySettings::soundUnknown(not_null<const Thread*> thread) const {
const auto topic = thread->asTopic();
return (topic && topic->notify().settingsUnknown())
|| ((!topic || !topic->notify().sound().has_value())
&& soundUnknown(topic->channel()));
&& soundUnknown(topic->peer()));
}
bool NotifySettings::isMuted(
@@ -1478,7 +1478,7 @@ bool InnerWidget::isRowActive(
return true;
} else if (const auto topic = entry.key.topic()) {
if (const auto history = key.history()) {
return (history->peer == topic->channel())
return (history->peer == topic->peer())
&& HistoryView::SubsectionTabs::UsedFor(history);
}
return false;
@@ -3611,18 +3611,24 @@ void InnerWidget::trackResultsHistory(not_null<History*> history) {
if (!_trackedHistories.emplace(history).second) {
return;
}
const auto channel = history->peer->asChannel();
if (!channel || channel->isBroadcast()) {
const auto peer = history->peer;
if (!peer->isBot() && !peer->isMegagroup()) {
return;
}
channel->flagsValue(
) | rpl::skip(
1
) | rpl::filter([=](const ChannelData::Flags::Change &change) {
return (change.diff & ChannelDataFlag::Forum);
}) | rpl::start_with_next([=] {
auto changes = peer->isBot()
? peer->asBot()->flagsValue() | rpl::skip(
1
) | rpl::filter([=](const UserData::Flags::Change &change) {
return change.diff & UserDataFlag::Forum;
}) | rpl::to_empty | rpl::type_erased()
: peer->asChannel()->flagsValue() | rpl::skip(
1
) | rpl::filter([=](const ChannelData::Flags::Change &change) {
return (change.diff & ChannelDataFlag::Forum);
}) | rpl::to_empty | rpl::type_erased();
std::move(changes) | rpl::start_with_next([=] {
for (const auto &row : _searchResults) {
if (row->item()->history()->peer == channel) {
if (row->item()->history()->peer == peer) {
row->invalidateTopic();
}
}
@@ -3630,7 +3636,7 @@ void InnerWidget::trackResultsHistory(not_null<History*> history) {
for (auto i = begin(_filterResultsGlobal)
; i != end(_filterResultsGlobal);) {
if (const auto topic = i->first.topic()) {
if (topic->channel() == channel) {
if (topic->peer() == peer) {
removed = true;
_filterResults.erase(
ranges::remove(
@@ -3651,7 +3657,7 @@ void InnerWidget::trackResultsHistory(not_null<History*> history) {
update();
}, _trackedLifetime);
if (const auto forum = channel->forum()) {
if (const auto forum = peer->forum()) {
forum->topicDestroyed(
) | rpl::start_with_next([=](not_null<Data::ForumTopic*> topic) {
auto removed = false;
@@ -4284,7 +4290,7 @@ void InnerWidget::updateSearchIn() {
const auto peer = _searchState.inChat.owningHistory()
? _searchState.inChat.owningHistory()->peer.get()
: _openedForum
? _openedForum->channel().get()
? _openedForum->peer().get()
: nullptr;
const auto paused = [window = _controller] {
return window->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
+37 -30
View File
@@ -875,7 +875,7 @@ void Widget::chosenRow(const ChosenRow &row) {
controller()->showInNewWindow(Window::SeparateId(topicJump));
} else {
if (!controller()->adaptive().isOneColumn()
&& !topicJump->channel()->useSubsectionTabs()) {
&& !topicJump->peer()->useSubsectionTabs()) {
controller()->showForum(
topicJump->forum(),
Window::SectionShow().withChildColumn());
@@ -919,13 +919,13 @@ void Widget::chosenRow(const ChosenRow &row) {
&& history->isForum()
&& !row.message.fullId
&& (!controller()->adaptive().isOneColumn()
|| !history->peer->forum()->channel()->viewForumAsMessages()
|| history->peer->forum()->channel()->useSubsectionTabs())) {
|| !history->peer->viewForumAsMessages()
|| history->peer->useSubsectionTabs())) {
const auto forum = history->peer->forum();
if (controller()->shownForum().current() == forum) {
controller()->closeForum();
} else if (row.newWindow) {
const auto type = forum->channel()->useSubsectionTabs()
const auto type = forum->peer()->useSubsectionTabs()
? Window::SeparateType::Chat
: Window::SeparateType::Forum;
controller()->showInNewWindow(Window::SeparateId(type, history));
@@ -935,7 +935,7 @@ void Widget::chosenRow(const ChosenRow &row) {
Window::SectionShow(
Window::SectionShow::Way::ClearStack).withChildColumn());
if (controller()->shownForum().current() == forum
&& forum->channel()->viewForumAsMessages()) {
&& forum->peer()->viewForumAsMessages()) {
controller()->showThread(
history,
ShowAtUnreadMsgId,
@@ -2016,24 +2016,24 @@ void Widget::refreshTopBars() {
}
_forumSearchRequested = false;
if (_openedForum) {
const auto channel = _openedForum->channel();
channel->updateFull();
const auto peer = _openedForum->peer();
peer->updateFull();
_forumReportBar = std::make_unique<HistoryView::ContactStatus>(
controller(),
this,
channel,
peer,
true);
_forumRequestsBar = std::make_unique<Ui::RequestsBar>(
this,
HistoryView::RequestsBarContentByPeer(
channel,
peer,
st::historyRequestsUserpics.size,
true));
_forumGroupCallBar = std::make_unique<Ui::GroupCallBar>(
this,
HistoryView::GroupCallBarContentByPeer(
channel,
peer,
st::historyGroupCallUserpics.size,
true),
Core::App().appDeactivatedValue());
@@ -2041,15 +2041,15 @@ void Widget::refreshTopBars() {
_forumRequestsBar->barClicks(
) | rpl::start_with_next([=] {
RequestsBoxController::Start(controller(), channel);
RequestsBoxController::Start(controller(), peer);
}, _forumRequestsBar->lifetime());
rpl::merge(
_forumGroupCallBar->barClicks(),
_forumGroupCallBar->joinClicks()
) | rpl::start_with_next([=] {
if (channel->groupCall()) {
controller()->startOrJoinGroupCall(channel);
if (peer->groupCall()) {
controller()->startOrJoinGroupCall(peer);
}
}, _forumGroupCallBar->lifetime());
@@ -2763,7 +2763,7 @@ void Widget::searchTopics() {
_api.request(base::take(_topicSearchRequest)).cancel();
_topicSearchRequest = _api.request(MTPmessages_GetForumTopics(
MTP_flags(MTPmessages_GetForumTopics::Flag::f_q),
_openedForum->channel()->input,
_openedForum->peer()->input,
MTP_string(_topicSearchQuery),
MTP_int(_topicSearchOffsetDate),
MTP_int(_topicSearchOffsetId),
@@ -3065,6 +3065,9 @@ void Widget::searchReceived(
// Don't apply cached data!
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
if (const auto peer = searchInPeer()) {
peer->processTopics(data.vtopics());
}
}
process->full = true;
auto list = processList(data.vmessages());
@@ -3075,6 +3078,9 @@ void Widget::searchReceived(
// Don't apply cached data!
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
if (const auto peer = searchInPeer()) {
peer->processTopics(data.vtopics());
}
}
auto list = processList(data.vmessages());
const auto nextRate = data.vnext_rate();
@@ -3092,24 +3098,24 @@ void Widget::searchReceived(
fullCount = data.vcount().v;
return list;
}, [&](const MTPDmessages_channelMessages &data) {
if (const auto peer = searchInPeer()) {
if (const auto channel = peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
channel->processTopics(data.vtopics());
if (!cacheResults) {
// Don't apply cached data!
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
if (const auto peer = searchInPeer()) {
if (const auto channel = peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
} else {
LOG(("API Error: "
"received messages.channelMessages when no channel "
"was passed! (Widget::searchReceived)"));
}
peer->processTopics(data.vtopics());
} else {
LOG(("API Error: "
"received messages.channelMessages when no channel "
"was passed! (Widget::searchReceived)"));
}
} else {
LOG(("API Error: "
"received messages.channelMessages when no channel "
"was passed! (Widget::searchReceived)"));
}
if (!cacheResults) {
// Don't apply cached data!
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
}
auto list = processList(data.vmessages());
if (list.empty()) {
@@ -3144,6 +3150,7 @@ void Widget::searchApplyEmpty(
type,
MTP_messages_messages(
MTP_vector<MTPMessage>(),
MTP_vector<MTPForumTopic>(),
MTP_vector<MTPChat>(),
MTP_vector<MTPUser>()),
process);
@@ -3364,7 +3371,7 @@ void Widget::openChildList(
controller(),
Layout::Child);
_childList->showForum(forum, copy);
_childListPeerId = forum->channel()->id;
_childListPeerId = forum->peer()->id;
}
_childListShadow = std::make_unique<Ui::RpWidget>(this);
@@ -4223,7 +4230,7 @@ PeerData *Widget::searchInPeer() const {
|| _searchState.tab == ChatSearchTab::PublicPosts)
? nullptr
: _openedForum
? _openedForum->channel().get()
? _openedForum->peer().get()
: _searchState.inChat.sublist()
? _searchState.inChat.sublist()->owningHistory()->peer.get()
: _searchState.inChat.peer();
@@ -4359,7 +4366,7 @@ bool Widget::cancelSearch(CancelSearchOptions options) {
updateForceDisplayWide();
if (clearingInChat) {
if (const auto forum = controller()->shownForum().current()) {
if (forum->channel()->useSubsectionTabs()) {
if (forum->peer()->useSubsectionTabs()) {
const auto id = controller()->windowId();
const auto initial = id.forum();
if (!initial) {
@@ -143,17 +143,19 @@ void Proxy::addSlice(const MTPmessages_Messages &slice, int alreadyLoaded) {
"(Proxy::addSlice)"));
return 0;
}, [&](const MTPDmessages_messages &data) {
history->peer->processTopics(data.vtopics());
return int(data.vmessages().v.size());
}, [&](const MTPDmessages_messagesSlice &data) {
history->peer->processTopics(data.vtopics());
return data.vcount().v;
}, [&](const MTPDmessages_channelMessages &data) {
if (const auto channel = history->peer->asChannel()) {
channel->ptsReceived(data.vpts().v);
channel->processTopics(data.vtopics());
} else {
LOG(("API Error: received messages.channelMessages when "
"no channel was passed! (Proxy::addSlice)"));
}
history->peer->processTopics(data.vtopics());
return data.vcount().v;
});
@@ -3848,6 +3848,7 @@ void HistoryWidget::messagesReceived(
auto &d(messages.c_messages_messages());
_history->owner().processUsers(d.vusers());
_history->owner().processChats(d.vchats());
peer->processTopics(d.vtopics());
histList = &d.vmessages().v;
count = histList->size();
} break;
@@ -3855,20 +3856,21 @@ void HistoryWidget::messagesReceived(
auto &d(messages.c_messages_messagesSlice());
_history->owner().processUsers(d.vusers());
_history->owner().processChats(d.vchats());
peer->processTopics(d.vtopics());
histList = &d.vmessages().v;
count = d.vcount().v;
} break;
case mtpc_messages_channelMessages: {
auto &d(messages.c_messages_channelMessages());
_history->owner().processUsers(d.vusers());
_history->owner().processChats(d.vchats());
if (const auto channel = peer->asChannel()) {
channel->ptsReceived(d.vpts().v);
channel->processTopics(d.vtopics());
} else {
LOG(("API Error: received messages.channelMessages when "
"no channel was passed! (HistoryWidget::messagesReceived)"));
}
_history->owner().processUsers(d.vusers());
_history->owner().processChats(d.vchats());
peer->processTopics(d.vtopics());
histList = &d.vmessages().v;
count = d.vcount().v;
} break;
@@ -352,7 +352,7 @@ void Item::setupTop() {
: Ui::CreateChild<Ui::FlatLabel>(
_top.get(),
(topic
? Info::Profile::NameValue(topic->channel())
? Info::Profile::NameValue(topic->peer())
: std::move(statusText)),
st::previewStatus);
if (status) {
@@ -1110,7 +1110,9 @@ TopicReopenBar::TopicReopenBar(
void TopicReopenBar::setupState() {
const auto channel = _topic->channel();
auto canToggle = (_topic->my() || channel->amCreator())
auto canToggle = !channel
? (rpl::single(false) | rpl::type_erased())
: (_topic->my() || channel->amCreator())
? (rpl::single(true) | rpl::type_erased())
: channel->adminRightsValue(
) | rpl::map([=] { return _topic->canToggleClosed(); });
@@ -1617,8 +1617,8 @@ void Element::recountThreadBarInBlocks() {
const auto item = data();
const auto topic = item->topic();
const auto sublist = item->savedSublist();
const auto parentChat = (topic && topic->channel()->useSubsectionTabs())
? topic->channel().get()
const auto parentChat = (topic && topic->peer()->useSubsectionTabs())
? topic->peer().get()
: sublist
? sublist->parentChat()
: nullptr;
@@ -1632,7 +1632,7 @@ void Element::recountThreadBarInBlocks() {
if (const auto previous = previousDisplayedInBlocks()) {
const auto prev = previous->data();
if (const auto prevTopic = prev->topic()) {
Assert(prevTopic->channel() == parentChat);
Assert(prevTopic->peer() == parentChat);
const auto topicRootId = topic->rootId();
if (prevTopic->rootId() == topicRootId) {
return nullptr;
@@ -1096,7 +1096,7 @@ void Message::refreshTopicButton() {
if (isAttachedToPrevious() || delegate()->elementHideTopicButton(this)) {
_topicButton = nullptr;
} else if (const auto topic = item->topic()) {
if (topic->channel()->useSubsectionTabs()) {
if (topic->peer()->useSubsectionTabs()) {
_topicButton = nullptr;
return;
}
@@ -846,7 +846,7 @@ void TopBarWidget::setActiveChat(
if (const auto topic = _activeChat.key.topic()) {
Info::Profile::NameValue(
topic->channel()
topic->peer()
) | rpl::start_with_next([=](const QString &name) {
_titlePeerText.setText(st::dialogsTextStyle, name);
_titlePeerTextOnline = false;
@@ -79,7 +79,7 @@ PeerData *Key::peer() const {
if (const auto peer = std::get_if<not_null<PeerData*>>(&_value)) {
return *peer;
} else if (const auto topic = this->topic()) {
return topic->channel();
return topic->peer();
} else if (const auto sublist = this->sublist()) {
return sublist->owningHistory()->peer;
}
@@ -86,7 +86,7 @@ Memento::Memento(not_null<PeerData*> peer, PeerId migratedPeerId, Type type)
}
Memento::Memento(not_null<Data::ForumTopic*> topic, Type type)
: Memento(topic->channel(), topic, nullptr, PeerId(), type) {
: Memento(topic->peer(), topic, nullptr, PeerId(), type) {
}
Memento::Memento(not_null<Data::SavedSublist*> sublist, Type type)
@@ -2142,14 +2142,14 @@ void DetailsFiller::addShowTopicsListButton(
using namespace rpl::mappers;
const auto window = _controller->parentController();
const auto channel = forum->channel();
const auto peer = forum->peer();
auto showTopicsVisible = rpl::combine(
window->adaptive().oneColumnValue(),
window->shownForum().value(),
_1 || (_2 != forum));
const auto callback = [=] {
if (const auto forum = channel->forum()) {
if (channel->useSubsectionTabs()) {
if (const auto forum = peer->forum()) {
if (peer->useSubsectionTabs()) {
window->searchInChat(forum->history());
} else {
window->showForum(forum);
@@ -560,7 +560,7 @@ Cover::Cover(
: Cover(
parent,
controller,
topic->channel(),
topic->peer(),
topic,
Role::Info,
TitleValue(topic),
@@ -281,10 +281,10 @@ rpl::producer<bool> NotificationsEnabledValue(
Data::TopicUpdate::Flag::Notifications
) | rpl::to_empty,
topic->session().changes().peerUpdates(
topic->channel(),
topic->peer(),
UpdateFlag::Notifications
) | rpl::to_empty,
topic->owner().notifySettings().defaultUpdates(topic->channel())
topic->owner().notifySettings().defaultUpdates(topic->peer())
) | rpl::map([=] {
return !topic->owner().notifySettings().isMuted(topic);
}) | rpl::distinct_until_changed();
@@ -50,7 +50,7 @@ Memento::Memento(
}
Memento::Memento(not_null<Data::ForumTopic*> topic)
: ContentMemento(topic->channel(), topic, nullptr, 0) {
: ContentMemento(topic->peer(), topic, nullptr, 0) {
}
Memento::Memento(not_null<Data::SavedSublist*> sublist)
@@ -415,8 +415,12 @@ void TogglePinnedThread(
controller->content()->dialogsToUp();
}
} else if (const auto topic = entry->asTopic()) {
const auto channel = topic->channel();
if (!channel) {
return;
}
owner->session().api().request(MTPchannels_UpdatePinnedForumTopic(
topic->channel()->inputChannel,
channel->inputChannel,
MTP_int(topic->rootId()),
MTP_bool(isPinned)
)).done([=](const MTPUpdates &result) {
@@ -1063,6 +1067,9 @@ void Filler::addTopicLink() {
return;
}
const auto channel = _topic->channel();
if (!channel) {
return;
}
const auto id = _topic->rootId();
const auto controller = _controller;
_addAction(tr::lng_context_copy_topic_link(tr::now), [=] {
@@ -1805,17 +1812,17 @@ void PeerMenuDeleteTopicWithConfirmation(
void PeerMenuDeleteTopic(
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel,
not_null<PeerData*> peer,
MsgId rootId) {
const auto api = &channel->session().api();
const auto api = &peer->session().api();
api->request(MTPmessages_DeleteTopicHistory(
channel->input,
peer->input,
MTP_int(rootId)
)).done([=](const MTPmessages_AffectedHistory &result) {
const auto offset = api->applyAffectedHistory(channel, result);
const auto offset = api->applyAffectedHistory(peer, result);
if (offset > 0) {
PeerMenuDeleteTopic(navigation, channel, rootId);
} else if (const auto forum = channel->forum()) {
PeerMenuDeleteTopic(navigation, peer, rootId);
} else if (const auto forum = peer->forum()) {
forum->applyTopicDeleted(rootId);
}
}).send();
@@ -1824,7 +1831,7 @@ void PeerMenuDeleteTopic(
void PeerMenuDeleteTopic(
not_null<Window::SessionNavigation*> navigation,
not_null<Data::ForumTopic*> topic) {
PeerMenuDeleteTopic(navigation, topic->channel(), topic->rootId());
PeerMenuDeleteTopic(navigation, topic->peer(), topic->rootId());
}
void PeerMenuShareContactBox(
@@ -623,7 +623,7 @@ void SessionNavigation::showPeerByLinkResolved(
if (controller->windowId().hasChatsList()
&& !controller->adaptive().isOneColumn()
&& controller->shownForum().current() != forum
&& !forum->channel()->useSubsectionTabs()) {
&& !forum->peer()->useSubsectionTabs()) {
controller->showForum(forum);
}
}
@@ -1991,11 +1991,11 @@ void SessionController::showForum(
const auto forced = params.forceTopicsList;
if (showForumInDifferentWindow(forum, params)) {
return;
} else if (!forced && forum->channel()->useSubsectionTabs()) {
} else if (!forced && forum->peer()->useSubsectionTabs()) {
if (const auto active = forum->activeSubsectionThread()) {
showThread(active, ShowAtUnreadMsgId, params);
} else {
showPeerHistory(forum->channel(), params);
showPeerHistory(forum->peer(), params);
}
return;
}
@@ -2038,14 +2038,16 @@ void SessionController::showForum(
}, _shownForumLifetime);
if (!forced) {
using FlagChange = Data::Flags<ChannelDataFlags>::Change;
forum->channel()->flagsValue(
) | rpl::start_with_next([=](FlagChange change) {
if (change.diff & ChannelDataFlag::ForumTabs) {
if (HistoryView::SubsectionTabs::UsedFor(history)) {
closeAndShowHistory(true);
if (const auto channel = forum->channel()) {
channel->flagsValue(
) | rpl::start_with_next([=](FlagChange change) {
if (change.diff & ChannelDataFlag::ForumTabs) {
if (HistoryView::SubsectionTabs::UsedFor(history)) {
closeAndShowHistory(true);
}
}
}
}, _shownForumLifetime);
}, _shownForumLifetime);
}
}
}