2022-09-20 09:35:47 +00:00
|
|
|
/*
|
|
|
|
This file is part of Telegram Desktop,
|
|
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
|
|
|
|
For license and copyright information please follow this link:
|
|
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
|
|
*/
|
|
|
|
#include "data/data_forum.h"
|
|
|
|
|
2022-09-20 18:12:30 +00:00
|
|
|
#include "data/data_channel.h"
|
|
|
|
#include "data/data_session.h"
|
|
|
|
#include "data/data_forum_topic.h"
|
|
|
|
#include "history/history.h"
|
|
|
|
#include "history/history_item.h"
|
|
|
|
#include "main/main_session.h"
|
|
|
|
#include "base/random.h"
|
|
|
|
#include "apiwrap.h"
|
|
|
|
#include "lang/lang_keys.h"
|
|
|
|
#include "ui/layers/generic_box.h"
|
|
|
|
#include "ui/widgets/input_fields.h"
|
|
|
|
#include "window/window_session_controller.h"
|
|
|
|
#include "styles/style_boxes.h"
|
|
|
|
|
2022-09-20 09:35:47 +00:00
|
|
|
namespace Data {
|
2022-09-20 18:12:30 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
constexpr auto kTopicsFirstLoad = 20;
|
|
|
|
constexpr auto kTopicsPerPage = 500;
|
|
|
|
|
|
|
|
} // namespace
|
2022-09-20 09:35:47 +00:00
|
|
|
|
2022-09-26 13:37:32 +00:00
|
|
|
Forum::Forum(not_null<History*> history)
|
|
|
|
: _history(history)
|
|
|
|
, _topicsList(&_history->session(), FilterId(0), rpl::single(1)) {
|
|
|
|
Expects(_history->peer->isChannel());
|
2022-09-20 18:12:30 +00:00
|
|
|
}
|
2022-09-20 09:35:47 +00:00
|
|
|
|
2022-09-26 13:37:32 +00:00
|
|
|
Forum::~Forum() {
|
|
|
|
if (_requestId) {
|
|
|
|
_history->session().api().request(_requestId).cancel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
not_null<History*> Forum::history() const {
|
|
|
|
return _history;
|
|
|
|
}
|
|
|
|
|
|
|
|
not_null<ChannelData*> Forum::channel() const {
|
|
|
|
return _history->peer->asChannel();
|
|
|
|
}
|
2022-09-20 09:35:47 +00:00
|
|
|
|
2022-09-20 18:12:30 +00:00
|
|
|
not_null<Dialogs::MainList*> Forum::topicsList() {
|
|
|
|
return &_topicsList;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Forum::requestTopics() {
|
|
|
|
if (_allLoaded || _requestId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto firstLoad = !_offsetDate;
|
|
|
|
const auto loadCount = firstLoad ? kTopicsFirstLoad : kTopicsPerPage;
|
2022-09-26 13:37:32 +00:00
|
|
|
const auto api = &_history->session().api();
|
2022-09-20 18:12:30 +00:00
|
|
|
_requestId = api->request(MTPchannels_GetForumTopics(
|
|
|
|
MTP_flags(0),
|
2022-09-26 13:37:32 +00:00
|
|
|
channel()->inputChannel,
|
2022-09-20 18:12:30 +00:00
|
|
|
MTPstring(), // q
|
|
|
|
MTP_int(_offsetDate),
|
|
|
|
MTP_int(_offsetId),
|
|
|
|
MTP_int(_offsetTopicId),
|
|
|
|
MTP_int(loadCount)
|
|
|
|
)).done([=](const MTPmessages_ForumTopics &result) {
|
2022-09-27 06:25:26 +00:00
|
|
|
applyReceivedTopics(result, true);
|
2022-09-20 18:12:30 +00:00
|
|
|
_requestId = 0;
|
|
|
|
_chatsListChanges.fire({});
|
|
|
|
if (_allLoaded) {
|
|
|
|
_chatsListLoadedEvents.fire({});
|
|
|
|
}
|
|
|
|
}).fail([=](const MTP::Error &error) {
|
|
|
|
_allLoaded = true;
|
|
|
|
_requestId = 0;
|
|
|
|
}).send();
|
|
|
|
}
|
|
|
|
|
2022-09-27 06:25:26 +00:00
|
|
|
void Forum::applyReceivedTopics(const MTPmessages_ForumTopics &result) {
|
|
|
|
applyReceivedTopics(result, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Forum::applyReceivedTopics(
|
|
|
|
const MTPmessages_ForumTopics &topics,
|
|
|
|
bool updateOffset) {
|
|
|
|
const auto &data = topics.data();
|
|
|
|
const auto owner = &channel()->owner();
|
|
|
|
owner->processUsers(data.vusers());
|
|
|
|
owner->processChats(data.vchats());
|
|
|
|
owner->processMessages(data.vmessages(), NewMessageType::Existing);
|
|
|
|
channel()->ptsReceived(data.vpts().v);
|
|
|
|
const auto &list = data.vtopics().v;
|
|
|
|
for (const auto &topic : list) {
|
|
|
|
const auto rootId = MsgId(topic.data().vid().v);
|
|
|
|
const auto i = _topics.find(rootId);
|
|
|
|
const auto creating = (i == end(_topics));
|
|
|
|
const auto raw = creating
|
|
|
|
? _topics.emplace(
|
|
|
|
rootId,
|
|
|
|
std::make_unique<ForumTopic>(_history, rootId)
|
|
|
|
).first->second.get()
|
|
|
|
: i->second.get();
|
|
|
|
raw->applyTopic(topic);
|
|
|
|
if (updateOffset) {
|
|
|
|
if (const auto last = raw->lastServerMessage()) {
|
|
|
|
_offsetDate = last->date();
|
|
|
|
_offsetId = last->id;
|
|
|
|
}
|
|
|
|
_offsetTopicId = rootId;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (updateOffset
|
|
|
|
&& (list.isEmpty() || list.size() == data.vcount().v)) {
|
|
|
|
_allLoaded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-27 16:52:35 +00:00
|
|
|
void Forum::applyTopicAdded(
|
|
|
|
MsgId rootId,
|
|
|
|
const QString &title,
|
|
|
|
DocumentId iconId) {
|
2022-09-20 18:12:30 +00:00
|
|
|
if (const auto i = _topics.find(rootId); i != end(_topics)) {
|
2022-09-23 19:21:31 +00:00
|
|
|
i->second->applyTitle(title);
|
2022-09-27 16:52:35 +00:00
|
|
|
i->second->applyIconId(iconId);
|
2022-09-20 18:12:30 +00:00
|
|
|
} else {
|
|
|
|
const auto raw = _topics.emplace(
|
|
|
|
rootId,
|
2022-09-26 13:37:32 +00:00
|
|
|
std::make_unique<ForumTopic>(_history, rootId)
|
2022-09-20 18:12:30 +00:00
|
|
|
).first->second.get();
|
2022-09-23 19:21:31 +00:00
|
|
|
raw->applyTitle(title);
|
2022-09-27 16:52:35 +00:00
|
|
|
raw->applyIconId(iconId);
|
|
|
|
if (!creating(rootId)) {
|
|
|
|
raw->addToChatList(FilterId(), topicsList());
|
|
|
|
_chatsListChanges.fire({});
|
|
|
|
}
|
2022-09-20 18:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-23 19:21:31 +00:00
|
|
|
void Forum::applyTopicRemoved(MsgId rootId) {
|
|
|
|
//if (const auto i = _topics.find(rootId)) {
|
|
|
|
// _topics.erase(i);
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
2022-09-27 16:52:35 +00:00
|
|
|
MsgId Forum::reserveCreatingId(
|
|
|
|
const QString &title,
|
|
|
|
DocumentId iconId) {
|
|
|
|
const auto result = _history->owner().nextLocalMessageId();
|
|
|
|
_creatingRootIds.emplace(result);
|
|
|
|
applyTopicAdded(result, title, iconId);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Forum::discardCreatingId(MsgId rootId) {
|
|
|
|
Expects(creating(rootId));
|
|
|
|
|
|
|
|
const auto i = _topics.find(rootId);
|
|
|
|
if (i != end(_topics)) {
|
|
|
|
Assert(!i->second->inChatList());
|
|
|
|
_topics.erase(i);
|
|
|
|
}
|
|
|
|
_creatingRootIds.remove(rootId);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Forum::creating(MsgId rootId) const {
|
|
|
|
return _creatingRootIds.contains(rootId);
|
|
|
|
}
|
|
|
|
|
2022-09-23 19:21:31 +00:00
|
|
|
ForumTopic *Forum::topicFor(not_null<HistoryItem*> item) {
|
2022-09-27 17:47:30 +00:00
|
|
|
const auto maybe = topicFor(item->replyToTop());
|
|
|
|
return maybe ? maybe : topicFor(item->topicRootId());
|
2022-09-26 13:37:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ForumTopic *Forum::topicFor(MsgId rootId) {
|
|
|
|
if (rootId != ForumTopic::kGeneralId) {
|
2022-09-23 19:21:31 +00:00
|
|
|
if (const auto i = _topics.find(rootId); i != end(_topics)) {
|
|
|
|
return i->second.get();
|
|
|
|
}
|
2022-09-26 13:37:32 +00:00
|
|
|
} else {
|
|
|
|
// #TODO forum lang
|
2022-09-27 16:52:35 +00:00
|
|
|
applyTopicAdded(rootId, "General! Created.", DocumentId(0));
|
2022-09-26 13:37:32 +00:00
|
|
|
return _topics.find(rootId)->second.get();
|
2022-09-23 19:21:31 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2022-09-20 18:12:30 +00:00
|
|
|
rpl::producer<> Forum::chatsListChanges() const {
|
|
|
|
return _chatsListChanges.events();
|
|
|
|
}
|
|
|
|
|
|
|
|
rpl::producer<> Forum::chatsListLoadedEvents() const {
|
|
|
|
return _chatsListLoadedEvents.events();
|
|
|
|
}
|
|
|
|
|
2022-09-20 09:35:47 +00:00
|
|
|
} // namespace Data
|