| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- /*
- 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_saved_messages.h"
- #include "apiwrap.h"
- #include "data/data_peer.h"
- #include "data/data_saved_sublist.h"
- #include "data/data_session.h"
- #include "history/history.h"
- #include "history/history_item.h"
- #include "main/main_session.h"
- namespace Data {
- namespace {
- constexpr auto kPerPage = 50;
- constexpr auto kFirstPerPage = 10;
- constexpr auto kListPerPage = 100;
- constexpr auto kListFirstPerPage = 20;
- } // namespace
- SavedMessages::SavedMessages(not_null<Session*> owner)
- : _owner(owner)
- , _chatsList(
- &owner->session(),
- FilterId(),
- owner->maxPinnedChatsLimitValue(this))
- , _loadMore([=] { sendLoadMoreRequests(); }) {
- }
- SavedMessages::~SavedMessages() = default;
- bool SavedMessages::supported() const {
- return !_unsupported;
- }
- Session &SavedMessages::owner() const {
- return *_owner;
- }
- Main::Session &SavedMessages::session() const {
- return _owner->session();
- }
- not_null<Dialogs::MainList*> SavedMessages::chatsList() {
- return &_chatsList;
- }
- not_null<SavedSublist*> SavedMessages::sublist(not_null<PeerData*> peer) {
- const auto i = _sublists.find(peer);
- if (i != end(_sublists)) {
- return i->second.get();
- }
- return _sublists.emplace(
- peer,
- std::make_unique<SavedSublist>(peer)).first->second.get();
- }
- void SavedMessages::loadMore() {
- _loadMoreScheduled = true;
- _loadMore.call();
- }
- void SavedMessages::loadMore(not_null<SavedSublist*> sublist) {
- _loadMoreSublistsScheduled.emplace(sublist);
- _loadMore.call();
- }
- void SavedMessages::sendLoadMore() {
- if (_loadMoreRequestId || _chatsList.loaded()) {
- return;
- } else if (!_pinnedLoaded) {
- loadPinned();
- }
- _loadMoreRequestId = _owner->session().api().request(
- MTPmessages_GetSavedDialogs(
- MTP_flags(MTPmessages_GetSavedDialogs::Flag::f_exclude_pinned),
- MTP_int(_offsetDate),
- MTP_int(_offsetId),
- _offsetPeer ? _offsetPeer->input : MTP_inputPeerEmpty(),
- MTP_int(_offsetId ? kListPerPage : kListFirstPerPage),
- MTP_long(0)) // hash
- ).done([=](const MTPmessages_SavedDialogs &result) {
- apply(result, false);
- }).fail([=](const MTP::Error &error) {
- if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) {
- _unsupported = true;
- }
- _chatsList.setLoaded();
- _loadMoreRequestId = 0;
- }).send();
- }
- void SavedMessages::loadPinned() {
- if (_pinnedRequestId) {
- return;
- }
- _pinnedRequestId = _owner->session().api().request(
- MTPmessages_GetPinnedSavedDialogs()
- ).done([=](const MTPmessages_SavedDialogs &result) {
- apply(result, true);
- }).fail([=](const MTP::Error &error) {
- if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) {
- _unsupported = true;
- } else {
- _pinnedLoaded = true;
- }
- _pinnedRequestId = 0;
- }).send();
- }
- void SavedMessages::sendLoadMore(not_null<SavedSublist*> sublist) {
- if (_loadMoreRequests.contains(sublist) || sublist->isFullLoaded()) {
- return;
- }
- const auto &list = sublist->messages();
- const auto offsetId = list.empty() ? MsgId(0) : list.back()->id;
- const auto offsetDate = list.empty() ? MsgId(0) : list.back()->date();
- const auto limit = offsetId ? kPerPage : kFirstPerPage;
- const auto requestId = _owner->session().api().request(
- MTPmessages_GetSavedHistory(
- sublist->peer()->input,
- MTP_int(offsetId),
- MTP_int(offsetDate),
- MTP_int(0), // add_offset
- MTP_int(limit),
- MTP_int(0), // max_id
- MTP_int(0), // min_id
- MTP_long(0)) // hash
- ).done([=](const MTPmessages_Messages &result) {
- auto count = 0;
- auto list = (const QVector<MTPMessage>*)nullptr;
- result.match([](const MTPDmessages_channelMessages &) {
- LOG(("API Error: messages.channelMessages in sublist."));
- }, [](const MTPDmessages_messagesNotModified &) {
- LOG(("API Error: messages.messagesNotModified in sublist."));
- }, [&](const auto &data) {
- owner().processUsers(data.vusers());
- owner().processChats(data.vchats());
- list = &data.vmessages().v;
- if constexpr (MTPDmessages_messages::Is<decltype(data)>()) {
- count = int(list->size());
- } else {
- count = data.vcount().v;
- }
- });
- _loadMoreRequests.remove(sublist);
- if (!list) {
- sublist->setFullLoaded();
- return;
- }
- auto items = std::vector<not_null<HistoryItem*>>();
- items.reserve(list->size());
- for (const auto &message : *list) {
- const auto item = owner().addNewMessage(
- message,
- {},
- NewMessageType::Existing);
- if (item) {
- items.push_back(item);
- }
- }
- sublist->append(std::move(items), count);
- if (result.type() == mtpc_messages_messages) {
- sublist->setFullLoaded();
- }
- }).fail([=](const MTP::Error &error) {
- if (error.type() == u"SAVED_DIALOGS_UNSUPPORTED"_q) {
- _unsupported = true;
- }
- sublist->setFullLoaded();
- _loadMoreRequests.remove(sublist);
- }).send();
- _loadMoreRequests[sublist] = requestId;
- }
- void SavedMessages::apply(
- const MTPmessages_SavedDialogs &result,
- bool pinned) {
- auto list = (const QVector<MTPSavedDialog>*)nullptr;
- result.match([](const MTPDmessages_savedDialogsNotModified &) {
- LOG(("API Error: messages.savedDialogsNotModified."));
- }, [&](const auto &data) {
- _owner->processUsers(data.vusers());
- _owner->processChats(data.vchats());
- _owner->processMessages(
- data.vmessages(),
- NewMessageType::Existing);
- list = &data.vdialogs().v;
- });
- if (pinned) {
- _pinnedRequestId = 0;
- _pinnedLoaded = true;
- } else {
- _loadMoreRequestId = 0;
- }
- if (!list) {
- if (!pinned) {
- _chatsList.setLoaded();
- }
- return;
- }
- auto lastValid = false;
- auto offsetDate = TimeId();
- auto offsetId = MsgId();
- auto offsetPeer = (PeerData*)nullptr;
- const auto selfId = _owner->session().userPeerId();
- for (const auto &dialog : *list) {
- const auto &data = dialog.data();
- const auto peer = _owner->peer(peerFromMTP(data.vpeer()));
- const auto topId = MsgId(data.vtop_message().v);
- if (const auto item = _owner->message(selfId, topId)) {
- offsetPeer = peer;
- offsetDate = item->date();
- offsetId = topId;
- lastValid = true;
- const auto entry = sublist(peer);
- const auto entryPinned = pinned || data.is_pinned();
- entry->applyMaybeLast(item);
- _owner->setPinnedFromEntryList(entry, entryPinned);
- } else {
- lastValid = false;
- }
- }
- if (pinned) {
- } else if (!lastValid) {
- LOG(("API Error: Unknown message in the end of a slice."));
- _chatsList.setLoaded();
- } else if (result.type() == mtpc_messages_savedDialogs) {
- _chatsList.setLoaded();
- } else if ((_offsetDate > 0 && offsetDate > _offsetDate)
- || (offsetDate == _offsetDate
- && offsetId == _offsetId
- && offsetPeer == _offsetPeer)) {
- LOG(("API Error: Bad order in messages.savedDialogs."));
- _chatsList.setLoaded();
- } else {
- _offsetDate = offsetDate;
- _offsetId = offsetId;
- _offsetPeer = offsetPeer;
- }
- }
- void SavedMessages::sendLoadMoreRequests() {
- if (_loadMoreScheduled) {
- sendLoadMore();
- }
- for (const auto sublist : base::take(_loadMoreSublistsScheduled)) {
- sendLoadMore(sublist);
- }
- }
- void SavedMessages::apply(const MTPDupdatePinnedSavedDialogs &update) {
- const auto list = update.vorder();
- if (!list) {
- loadPinned();
- return;
- }
- const auto &order = list->v;
- const auto notLoaded = [&](const MTPDialogPeer &peer) {
- return peer.match([&](const MTPDdialogPeer &data) {
- const auto peer = _owner->peer(peerFromMTP(data.vpeer()));
- return !_sublists.contains(peer);
- }, [&](const MTPDdialogPeerFolder &data) {
- LOG(("API Error: "
- "updatePinnedSavedDialogs has folders."));
- return false;
- });
- };
- if (!ranges::none_of(order, notLoaded)) {
- loadPinned();
- } else {
- _chatsList.pinned()->applyList(this, order);
- _owner->notifyPinnedDialogsOrderUpdated();
- }
- }
- void SavedMessages::apply(const MTPDupdateSavedDialogPinned &update) {
- update.vpeer().match([&](const MTPDdialogPeer &data) {
- const auto peer = _owner->peer(peerFromMTP(data.vpeer()));
- const auto i = _sublists.find(peer);
- if (i != end(_sublists)) {
- const auto entry = i->second.get();
- _owner->setChatPinned(entry, FilterId(), update.is_pinned());
- } else {
- loadPinned();
- }
- }, [&](const MTPDdialogPeerFolder &data) {
- DEBUG_LOG(("API Error: Folder in updateSavedDialogPinned."));
- });
- }
- } // namespace Data
|