From 0367319934a106b12f3e9434a195ea90f993c3be Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 17 Apr 2019 16:08:02 +0400 Subject: [PATCH] Load folder dialogs list. --- Telegram/SourceFiles/apiwrap.cpp | 132 ++++++++++++------ Telegram/SourceFiles/apiwrap.h | 29 ++-- Telegram/SourceFiles/data/data_folder.cpp | 9 ++ Telegram/SourceFiles/data/data_session.cpp | 14 +- Telegram/SourceFiles/data/data_session.h | 5 +- .../dialogs/dialogs_inner_widget.cpp | 49 ------- .../dialogs/dialogs_inner_widget.h | 5 - Telegram/SourceFiles/dialogs/dialogs_widget.h | 6 - Telegram/SourceFiles/history/history.cpp | 11 +- Telegram/SourceFiles/history/history.h | 2 +- 10 files changed, 144 insertions(+), 118 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 9a1e6a6e19..d0354e2938 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -191,6 +191,7 @@ ApiWrap::ApiWrap(not_null session) , _webPagesTimer([=] { resolveWebPages(); }) , _draftsSaveTimer([=] { saveDraftsToCloud(); }) , _featuredSetsReadTimer([=] { readFeaturedSets(); }) +, _dialogsLoadState(std::make_unique()) , _fileLoader(std::make_unique(kFileLoaderQueueStopTimeout)) //, _feedReadTimer([=] { readFeeds(); }) // #feed , _proxyPromotionTimer([=] { refreshProxyPromotion(); }) @@ -706,28 +707,41 @@ void ApiWrap::requestContacts() { } void ApiWrap::requestDialogs() { - if (_dialogsRequestId) { + requestMoreDialogs(FolderId(0)); +} + +void ApiWrap::requestFolderDialogs(FolderId folderId) { + if (!_foldersLoadState.contains(folderId)) { + _foldersLoadState.emplace(folderId, DialogsLoadState()); + } + requestMoreDialogs(folderId); +} + +void ApiWrap::requestMoreDialogs(FolderId folderId) { + const auto state = dialogsLoadState(folderId); + if (!state) { + if (!folderId) { + _session->data().addAllSavedPeers(); + } return; - } else if (_dialogsFull) { - _session->data().addAllSavedPeers(); + } else if (state->requestId) { return; } else if (_dialogsLoadBlockedByDate.current()) { return; } - const auto firstLoad = !_dialogsOffsetDate; + const auto firstLoad = !state->offsetDate; const auto loadCount = firstLoad ? kDialogsFirstLoad : kDialogsPerPage; const auto flags = MTPmessages_GetDialogs::Flag::f_exclude_pinned | MTPmessages_GetDialogs::Flag::f_folder_id; - const auto folderId = 0; const auto hash = 0; - _dialogsRequestId = request(MTPmessages_GetDialogs( + state->requestId = request(MTPmessages_GetDialogs( MTP_flags(flags), MTP_int(folderId), - MTP_int(_dialogsOffsetDate), - MTP_int(_dialogsOffsetId), - (_dialogsOffsetPeer - ? _dialogsOffsetPeer->input + MTP_int(state->offsetDate), + MTP_int(state->offsetId), + (state->offsetPeer + ? state->offsetPeer->input : MTP_inputPeerEmpty()), MTP_int(loadCount), MTP_int(hash) @@ -736,27 +750,36 @@ void ApiWrap::requestDialogs() { LOG(("API Error: not-modified received for requested dialogs.")); }, [&](const auto &data) { if constexpr (data.Is()) { - _dialogsFull = true; + dialogsLoadFinish(folderId); + } else { + updateDialogsOffset( + folderId, + data.vdialogs.v, + data.vmessages.v); } - updateDialogsOffset(data.vdialogs.v, data.vmessages.v); _session->data().processUsers(data.vusers); _session->data().processChats(data.vchats); - _session->data().applyDialogs(data.vmessages.v, data.vdialogs.v); + _session->data().applyDialogs( + folderId, + data.vmessages.v, + data.vdialogs.v); }); - _dialogsRequestId = 0; - requestDialogs(); - if (!_dialogsRequestId) { - refreshDialogsLoadBlocked(); + if (!folderId) { + requestDialogs(); + if (!_dialogsLoadState || !_dialogsLoadState->requestId) { + refreshDialogsLoadBlocked(); + } } - _session->data().moreChatsLoaded().notify(); - if (_dialogsFull && _pinnedDialogsReceived) { - _session->data().allChatsLoaded().set(true); + if (!folderId) { + if (!_dialogsLoadState && _pinnedDialogsReceived) { + _session->data().allChatsLoaded().set(true); + } + requestContacts(); } - requestContacts(); }).fail([=](const RPCError &error) { - _dialogsRequestId = 0; + dialogsLoadState(folderId)->requestId = 0; }).send(); if (!_pinnedDialogsReceived) { requestPinnedDialogs(); @@ -765,16 +788,17 @@ void ApiWrap::requestDialogs() { } void ApiWrap::refreshDialogsLoadBlocked() { - _dialogsLoadMayBlockByDate = !_dialogsFull + _dialogsLoadMayBlockByDate = _dialogsLoadState && (_dialogsLoadTill > 0); - _dialogsLoadBlockedByDate = !_dialogsFull - && !_dialogsRequestId + _dialogsLoadBlockedByDate = _dialogsLoadState + && !_dialogsLoadState->requestId && (_dialogsLoadTill > 0) - && (_dialogsOffsetDate > 0) - && (_dialogsOffsetDate <= _dialogsLoadTill); + && (_dialogsLoadState->offsetDate > 0) + && (_dialogsLoadState->offsetDate <= _dialogsLoadTill); } void ApiWrap::updateDialogsOffset( + FolderId folderId, const QVector &dialogs, const QVector &messages) { auto lastDate = TimeId(0); @@ -808,11 +832,30 @@ void ApiWrap::updateDialogsOffset( } } if (lastDate) { - _dialogsOffsetDate = lastDate; - _dialogsOffsetId = lastMsgId; - _dialogsOffsetPeer = _session->data().peer(lastPeer); + if (const auto state = dialogsLoadState(folderId)) { + state->offsetDate = lastDate; + state->offsetId = lastMsgId; + state->offsetPeer = _session->data().peer(lastPeer); + state->requestId = 0; + } } else { - _dialogsFull = true; + dialogsLoadFinish(folderId); + } +} + +auto ApiWrap::dialogsLoadState(FolderId folderId) -> DialogsLoadState* { + if (!folderId) { + return _dialogsLoadState.get(); + } + const auto i = _foldersLoadState.find(folderId); + return (i != end(_foldersLoadState)) ? &i->second : nullptr; +} + +void ApiWrap::dialogsLoadFinish(FolderId folderId) { + if (folderId) { + _foldersLoadState.remove(folderId); + } else { + _dialogsLoadState = nullptr; } } @@ -827,16 +870,21 @@ void ApiWrap::requestPinnedDialogs() { MTP_int(folderId) )).done([=](const MTPmessages_PeerDialogs &result) { result.match([&](const MTPDmessages_peerDialogs &data) { + const auto folderId = FolderId(0); + _session->data().processUsers(data.vusers); _session->data().processChats(data.vchats); _session->data().applyPinnedDialogs(data.vdialogs.v); - _session->data().applyDialogs(data.vmessages.v, data.vdialogs.v); + _session->data().applyDialogs( + folderId, + data.vmessages.v, + data.vdialogs.v); _pinnedDialogsRequestId = 0; _pinnedDialogsReceived = true; _session->data().moreChatsLoaded().notify(); - if (_dialogsFull) { + if (!_dialogsLoadState) { _session->data().allChatsLoaded().set(true); } }); @@ -846,9 +894,12 @@ void ApiWrap::requestPinnedDialogs() { } void ApiWrap::requestMoreBlockedByDateDialogs() { + if (!_dialogsLoadState) { + return; + } const auto max = _session->settings().supportChatsTimeSlice(); - _dialogsLoadTill = _dialogsOffsetDate - ? (_dialogsOffsetDate - max) + _dialogsLoadTill = _dialogsLoadState->offsetDate + ? (_dialogsLoadState->offsetDate - max) : (unixtime() - max); requestDialogs(); } @@ -990,11 +1041,14 @@ void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) { for (const auto &dialog : data.vdialogs.v) { dialog.match([&](const MTPDdialog &data) { if (const auto peerId = peerFromMTP(data.vpeer)) { - _session->data().history(peerId)->applyDialog(data); + const auto requestFolderId = FolderId(0); + _session->data().history(peerId)->applyDialog( + requestFolderId, + data); } - }, [&](const MTPDdialogFolder &data) { // #TODO archive - //const auto folder = _session->data().processFolder(data.vfolder); - //folder->applyDialog(data); + }, [&](const MTPDdialogFolder &data) { + const auto folder = _session->data().processFolder(data.vfolder); + folder->applyDialog(data); }); } _session->data().sendHistoryChangeNotifications(); diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index ce14ebaee7..e2a74cfb0c 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -80,6 +80,7 @@ public: void requestContacts(); void requestDialogs(); + void requestFolderDialogs(FolderId folderId); void requestPinnedDialogs(); void requestMoreBlockedByDateDialogs(); rpl::producer dialogsLoadMayBlockByDate() const; @@ -454,16 +455,23 @@ private: crl::time received = 0; }; + struct DialogsLoadState { + TimeId offsetDate = 0; + MsgId offsetId = 0; + PeerData *offsetPeer = nullptr; + mtpRequestId requestId = 0; + }; + void setupSupportMode(); void refreshDialogsLoadBlocked(); void updateDialogsOffset( + FolderId folderId, const QVector &dialogs, const QVector &messages); - void applyReceivedDialogs( - const QVector &dialogs, - const QVector &messages); + void requestMoreDialogs(FolderId folderId); + DialogsLoadState *dialogsLoadState(FolderId folderId); + void dialogsLoadFinish(FolderId folderId); - void updatesReceived(const MTPUpdates &updates); void checkQuitPreventFinished(); void saveDraftsToCloud(); @@ -749,17 +757,16 @@ private: // SliceType>> _feedMessagesRequestsPending; //mtpRequestId _saveDefaultFeedIdRequest = 0; - bool _dialogsFull = false; - bool _pinnedDialogsReceived = false; + std::unique_ptr _dialogsLoadState; TimeId _dialogsLoadTill = 0; - TimeId _dialogsOffsetDate = 0; - MsgId _dialogsOffsetId = 0; - PeerData *_dialogsOffsetPeer = nullptr; - mtpRequestId _dialogsRequestId = 0; - mtpRequestId _pinnedDialogsRequestId = 0; rpl::variable _dialogsLoadMayBlockByDate = false; rpl::variable _dialogsLoadBlockedByDate = false; + bool _pinnedDialogsReceived = false; + mtpRequestId _pinnedDialogsRequestId = 0; + + base::flat_map _foldersLoadState; + rpl::event_stream _sendActions; struct ReadRequest { diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index 451f51bdaf..3e5b48574e 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -21,6 +21,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_dialogs.h" // st::dialogsArchiveUserpic namespace Data { +namespace { + +constexpr auto kLoadedChatsMinCount = 20; + +} // namespace // #feed //MessagePosition FeedPositionFromMTP(const MTPFeedPosition &position) { @@ -367,6 +372,10 @@ void Folder::applyDialog(const MTPDdialogFolder &data) { //if (data.has_read_max_position()) { // #feed // setUnreadPosition(FeedPositionFromMTP(data.vread_max_position)); //} + + if (_chatsList.size() < kLoadedChatsMinCount) { + session().api().requestFolderDialogs(_id); + } } void Folder::changedInChatListHook(Dialogs::Mode list, bool added) { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index a808843725..460b3c2269 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1351,24 +1351,25 @@ void Session::applyPinnedDialogs(const QVector &list) { } void Session::applyDialogs( + FolderId requestFolderId, const QVector &messages, const QVector &dialogs) { App::feedMsgs(messages, NewMessageLast); for (const auto &dialog : dialogs) { dialog.match([&](const auto &data) { - applyDialog(data); + applyDialog(requestFolderId, data); }); } } -void Session::applyDialog(const MTPDdialog &data) { +void Session::applyDialog(FolderId requestFolderId, const MTPDdialog &data) { const auto peerId = peerFromMTP(data.vpeer); if (!peerId) { return; } const auto history = session().data().history(peerId); - history->applyDialog(data); + history->applyDialog(requestFolderId, data); if (!history->useProxyPromotion() && !history->isPinnedDialog()) { const auto date = history->chatListTimeId(); @@ -1387,7 +1388,12 @@ void Session::applyDialog(const MTPDdialog &data) { } } -void Session::applyDialog(const MTPDdialogFolder &dialog) { +void Session::applyDialog( + FolderId requestFolderId, + const MTPDdialogFolder &dialog) { + if (requestFolderId != 0) { + LOG(("API Error: requestFolderId != 0 for dialogFolder.")); + } const auto folder = processFolder(dialog.vfolder); folder->applyDialog(dialog); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 1317e66ce2..0492dea596 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -294,6 +294,7 @@ public: void applyUpdate(const MTPDupdateChatDefaultBannedRights &update); void applyDialogs( + FolderId requestFolderId, const QVector &messages, const QVector &dialogs); void addSavedPeersAfter(const QDateTime &date); @@ -603,8 +604,8 @@ private: int entriesFull, int entriesMuted) const; - void applyDialog(const MTPDdialog &data); - void applyDialog(const MTPDdialogFolder &data); + void applyDialog(FolderId requestFolderId, const MTPDdialog &data); + void applyDialog(FolderId requestFolderId, const MTPDdialogFolder &data); void photoApplyFields( not_null photo, diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 469fcdbea4..522450b3be 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1790,55 +1790,6 @@ void DialogsInner::itemRemoved(not_null item) { } } -void DialogsInner::dialogsReceived(const QVector &added) { - for (const auto &dialog : added) { - dialog.match([&](const MTPDdialog &data) { - applyDialog(data); - }, [&](const MTPDdialogFolder &data) { - applyFolderDialog(data); - }); - } - refresh(); -} - -void DialogsInner::applyDialog(const MTPDdialog &dialog) { - const auto peerId = peerFromMTP(dialog.vpeer); - if (!peerId) { - return; - } - - const auto history = session().data().history(peerId); - history->applyDialog(dialog); - - if (!history->useProxyPromotion() && !history->isPinnedDialog()) { - const auto date = history->chatListTimeId(); - if (date != 0) { - session().data().addSavedPeersAfter(ParseDateTime(date)); - } - } - if (const auto from = history->peer->migrateFrom()) { - if (const auto historyFrom = from->owner().historyLoaded(from)) { - removeDialog(historyFrom); - } - } else if (const auto to = history->peer->migrateTo()) { - if (to->amIn()) { - removeDialog(history); - } - } -} - -void DialogsInner::applyFolderDialog(const MTPDdialogFolder &dialog) { - const auto folder = session().data().processFolder(dialog.vfolder); - folder->applyDialog(dialog); - - if (!folder->useProxyPromotion() && !folder->isPinnedDialog()) { - const auto date = folder->chatListTimeId(); - if (date != 0) { - session().data().addSavedPeersAfter(ParseDateTime(date)); - } - } -} - bool DialogsInner::uniqueSearchResults() const { return session().supportMode() && !session().settings().supportAllSearchResults() diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 5474915fe6..1be1ebd7b4 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -39,7 +39,6 @@ class DialogsInner public: DialogsInner(QWidget *parent, not_null controller); - void dialogsReceived(const QVector &dialogs); bool searchReceived( const QVector &result, DialogsSearchRequestType type, @@ -48,7 +47,6 @@ public: const QString &query, const QVector &my, const QVector &result); - void showMore(int32 pixels); void activate(); @@ -199,9 +197,6 @@ private: Dialogs::RowDescriptor chatListEntryFirst() const; Dialogs::RowDescriptor chatListEntryLast() const; - void applyDialog(const MTPDdialog &dialog); - void applyFolderDialog(const MTPDdialogFolder &dialog); - void itemRemoved(not_null item); enum class UpdateRowSection { Default = (1 << 0), diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 799c7c3620..009b5e23a6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -122,12 +122,6 @@ protected: private: void animationCallback(); - void dialogsReceived( - const MTPmessages_Dialogs &result, - mtpRequestId requestId); - void pinnedDialogsReceived( - const MTPmessages_PeerDialogs &result, - mtpRequestId requestId); void searchReceived( DialogsSearchRequestType type, const MTPmessages_Messages &result, diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index e1e55c7bfe..6df80b744c 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -2431,7 +2431,7 @@ bool History::isServerSideUnread(not_null item) const { : (!_inboxReadBefore || (item->id >= *_inboxReadBefore)); } -void History::applyDialog(const MTPDdialog &data) { +void History::applyDialog(FolderId requestFolderId, const MTPDdialog &data) { applyDialogFields( data.vunread_count.v, data.vread_inbox_max_id.v, @@ -2461,6 +2461,15 @@ void History::applyDialog(const MTPDdialog &data) { if (data.has_draft() && data.vdraft.type() == mtpc_draftMessage) { Data::applyPeerCloudDraft(peer->id, data.vdraft.c_draftMessage()); } + + const auto folderId = data.has_folder_id() + ? data.vfolder_id.v + : requestFolderId; + if (folderId) { + setFolder(owner().folder(folderId)); + } else { + clearFolder(); + } session().api().dialogEntryApplied(this); } diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 361bbfee9c..d333fb6e82 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -191,7 +191,7 @@ public: bool lastMessageKnown() const; void unknownMessageDeleted(MsgId messageId); void applyDialogTopMessage(MsgId topMessageId); - void applyDialog(const MTPDdialog &data); + void applyDialog(FolderId requestFolderId, const MTPDdialog &data); void applyDialogFields( int unreadCount, MsgId maxInboxRead,