mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Initial forum support in bots data classes.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -545,8 +545,6 @@ public:
|
||||
return mgInfo ? mgInfo->monoforum() : nullptr;
|
||||
}
|
||||
|
||||
void processTopics(const MTPVector<MTPForumTopic> &topics);
|
||||
|
||||
[[nodiscard]] int levelHint() const;
|
||||
void updateLevelHint(int levelHint);
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ¬ify() {
|
||||
return _notify;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user