Load folder dialogs list.

This commit is contained in:
John Preston 2019-04-17 16:08:02 +04:00
parent be0cf8d379
commit 0367319934
10 changed files with 144 additions and 118 deletions

View File

@ -191,6 +191,7 @@ ApiWrap::ApiWrap(not_null<AuthSession*> session)
, _webPagesTimer([=] { resolveWebPages(); }) , _webPagesTimer([=] { resolveWebPages(); })
, _draftsSaveTimer([=] { saveDraftsToCloud(); }) , _draftsSaveTimer([=] { saveDraftsToCloud(); })
, _featuredSetsReadTimer([=] { readFeaturedSets(); }) , _featuredSetsReadTimer([=] { readFeaturedSets(); })
, _dialogsLoadState(std::make_unique<DialogsLoadState>())
, _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout)) , _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout))
//, _feedReadTimer([=] { readFeeds(); }) // #feed //, _feedReadTimer([=] { readFeeds(); }) // #feed
, _proxyPromotionTimer([=] { refreshProxyPromotion(); }) , _proxyPromotionTimer([=] { refreshProxyPromotion(); })
@ -706,28 +707,41 @@ void ApiWrap::requestContacts() {
} }
void ApiWrap::requestDialogs() { void ApiWrap::requestDialogs() {
if (_dialogsRequestId) { requestMoreDialogs(FolderId(0));
return; }
} else if (_dialogsFull) {
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(); _session->data().addAllSavedPeers();
}
return;
} else if (state->requestId) {
return; return;
} else if (_dialogsLoadBlockedByDate.current()) { } else if (_dialogsLoadBlockedByDate.current()) {
return; return;
} }
const auto firstLoad = !_dialogsOffsetDate; const auto firstLoad = !state->offsetDate;
const auto loadCount = firstLoad ? kDialogsFirstLoad : kDialogsPerPage; const auto loadCount = firstLoad ? kDialogsFirstLoad : kDialogsPerPage;
const auto flags = MTPmessages_GetDialogs::Flag::f_exclude_pinned const auto flags = MTPmessages_GetDialogs::Flag::f_exclude_pinned
| MTPmessages_GetDialogs::Flag::f_folder_id; | MTPmessages_GetDialogs::Flag::f_folder_id;
const auto folderId = 0;
const auto hash = 0; const auto hash = 0;
_dialogsRequestId = request(MTPmessages_GetDialogs( state->requestId = request(MTPmessages_GetDialogs(
MTP_flags(flags), MTP_flags(flags),
MTP_int(folderId), MTP_int(folderId),
MTP_int(_dialogsOffsetDate), MTP_int(state->offsetDate),
MTP_int(_dialogsOffsetId), MTP_int(state->offsetId),
(_dialogsOffsetPeer (state->offsetPeer
? _dialogsOffsetPeer->input ? state->offsetPeer->input
: MTP_inputPeerEmpty()), : MTP_inputPeerEmpty()),
MTP_int(loadCount), MTP_int(loadCount),
MTP_int(hash) MTP_int(hash)
@ -736,27 +750,36 @@ void ApiWrap::requestDialogs() {
LOG(("API Error: not-modified received for requested dialogs.")); LOG(("API Error: not-modified received for requested dialogs."));
}, [&](const auto &data) { }, [&](const auto &data) {
if constexpr (data.Is<MTPDmessages_dialogs>()) { if constexpr (data.Is<MTPDmessages_dialogs>()) {
_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().processUsers(data.vusers);
_session->data().processChats(data.vchats); _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; if (!folderId) {
requestDialogs(); requestDialogs();
if (!_dialogsRequestId) { if (!_dialogsLoadState || !_dialogsLoadState->requestId) {
refreshDialogsLoadBlocked(); refreshDialogsLoadBlocked();
} }
}
_session->data().moreChatsLoaded().notify(); _session->data().moreChatsLoaded().notify();
if (_dialogsFull && _pinnedDialogsReceived) { if (!folderId) {
if (!_dialogsLoadState && _pinnedDialogsReceived) {
_session->data().allChatsLoaded().set(true); _session->data().allChatsLoaded().set(true);
} }
requestContacts(); requestContacts();
}
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_dialogsRequestId = 0; dialogsLoadState(folderId)->requestId = 0;
}).send(); }).send();
if (!_pinnedDialogsReceived) { if (!_pinnedDialogsReceived) {
requestPinnedDialogs(); requestPinnedDialogs();
@ -765,16 +788,17 @@ void ApiWrap::requestDialogs() {
} }
void ApiWrap::refreshDialogsLoadBlocked() { void ApiWrap::refreshDialogsLoadBlocked() {
_dialogsLoadMayBlockByDate = !_dialogsFull _dialogsLoadMayBlockByDate = _dialogsLoadState
&& (_dialogsLoadTill > 0); && (_dialogsLoadTill > 0);
_dialogsLoadBlockedByDate = !_dialogsFull _dialogsLoadBlockedByDate = _dialogsLoadState
&& !_dialogsRequestId && !_dialogsLoadState->requestId
&& (_dialogsLoadTill > 0) && (_dialogsLoadTill > 0)
&& (_dialogsOffsetDate > 0) && (_dialogsLoadState->offsetDate > 0)
&& (_dialogsOffsetDate <= _dialogsLoadTill); && (_dialogsLoadState->offsetDate <= _dialogsLoadTill);
} }
void ApiWrap::updateDialogsOffset( void ApiWrap::updateDialogsOffset(
FolderId folderId,
const QVector<MTPDialog> &dialogs, const QVector<MTPDialog> &dialogs,
const QVector<MTPMessage> &messages) { const QVector<MTPMessage> &messages) {
auto lastDate = TimeId(0); auto lastDate = TimeId(0);
@ -808,11 +832,30 @@ void ApiWrap::updateDialogsOffset(
} }
} }
if (lastDate) { if (lastDate) {
_dialogsOffsetDate = lastDate; if (const auto state = dialogsLoadState(folderId)) {
_dialogsOffsetId = lastMsgId; state->offsetDate = lastDate;
_dialogsOffsetPeer = _session->data().peer(lastPeer); state->offsetId = lastMsgId;
state->offsetPeer = _session->data().peer(lastPeer);
state->requestId = 0;
}
} else { } 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) MTP_int(folderId)
)).done([=](const MTPmessages_PeerDialogs &result) { )).done([=](const MTPmessages_PeerDialogs &result) {
result.match([&](const MTPDmessages_peerDialogs &data) { result.match([&](const MTPDmessages_peerDialogs &data) {
const auto folderId = FolderId(0);
_session->data().processUsers(data.vusers); _session->data().processUsers(data.vusers);
_session->data().processChats(data.vchats); _session->data().processChats(data.vchats);
_session->data().applyPinnedDialogs(data.vdialogs.v); _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; _pinnedDialogsRequestId = 0;
_pinnedDialogsReceived = true; _pinnedDialogsReceived = true;
_session->data().moreChatsLoaded().notify(); _session->data().moreChatsLoaded().notify();
if (_dialogsFull) { if (!_dialogsLoadState) {
_session->data().allChatsLoaded().set(true); _session->data().allChatsLoaded().set(true);
} }
}); });
@ -846,9 +894,12 @@ void ApiWrap::requestPinnedDialogs() {
} }
void ApiWrap::requestMoreBlockedByDateDialogs() { void ApiWrap::requestMoreBlockedByDateDialogs() {
if (!_dialogsLoadState) {
return;
}
const auto max = _session->settings().supportChatsTimeSlice(); const auto max = _session->settings().supportChatsTimeSlice();
_dialogsLoadTill = _dialogsOffsetDate _dialogsLoadTill = _dialogsLoadState->offsetDate
? (_dialogsOffsetDate - max) ? (_dialogsLoadState->offsetDate - max)
: (unixtime() - max); : (unixtime() - max);
requestDialogs(); requestDialogs();
} }
@ -990,11 +1041,14 @@ void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) {
for (const auto &dialog : data.vdialogs.v) { for (const auto &dialog : data.vdialogs.v) {
dialog.match([&](const MTPDdialog &data) { dialog.match([&](const MTPDdialog &data) {
if (const auto peerId = peerFromMTP(data.vpeer)) { 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 MTPDdialogFolder &data) {
//const auto folder = _session->data().processFolder(data.vfolder); const auto folder = _session->data().processFolder(data.vfolder);
//folder->applyDialog(data); folder->applyDialog(data);
}); });
} }
_session->data().sendHistoryChangeNotifications(); _session->data().sendHistoryChangeNotifications();

View File

@ -80,6 +80,7 @@ public:
void requestContacts(); void requestContacts();
void requestDialogs(); void requestDialogs();
void requestFolderDialogs(FolderId folderId);
void requestPinnedDialogs(); void requestPinnedDialogs();
void requestMoreBlockedByDateDialogs(); void requestMoreBlockedByDateDialogs();
rpl::producer<bool> dialogsLoadMayBlockByDate() const; rpl::producer<bool> dialogsLoadMayBlockByDate() const;
@ -454,16 +455,23 @@ private:
crl::time received = 0; crl::time received = 0;
}; };
struct DialogsLoadState {
TimeId offsetDate = 0;
MsgId offsetId = 0;
PeerData *offsetPeer = nullptr;
mtpRequestId requestId = 0;
};
void setupSupportMode(); void setupSupportMode();
void refreshDialogsLoadBlocked(); void refreshDialogsLoadBlocked();
void updateDialogsOffset( void updateDialogsOffset(
FolderId folderId,
const QVector<MTPDialog> &dialogs, const QVector<MTPDialog> &dialogs,
const QVector<MTPMessage> &messages); const QVector<MTPMessage> &messages);
void applyReceivedDialogs( void requestMoreDialogs(FolderId folderId);
const QVector<MTPDialog> &dialogs, DialogsLoadState *dialogsLoadState(FolderId folderId);
const QVector<MTPMessage> &messages); void dialogsLoadFinish(FolderId folderId);
void updatesReceived(const MTPUpdates &updates);
void checkQuitPreventFinished(); void checkQuitPreventFinished();
void saveDraftsToCloud(); void saveDraftsToCloud();
@ -749,17 +757,16 @@ private:
// SliceType>> _feedMessagesRequestsPending; // SliceType>> _feedMessagesRequestsPending;
//mtpRequestId _saveDefaultFeedIdRequest = 0; //mtpRequestId _saveDefaultFeedIdRequest = 0;
bool _dialogsFull = false; std::unique_ptr<DialogsLoadState> _dialogsLoadState;
bool _pinnedDialogsReceived = false;
TimeId _dialogsLoadTill = 0; TimeId _dialogsLoadTill = 0;
TimeId _dialogsOffsetDate = 0;
MsgId _dialogsOffsetId = 0;
PeerData *_dialogsOffsetPeer = nullptr;
mtpRequestId _dialogsRequestId = 0;
mtpRequestId _pinnedDialogsRequestId = 0;
rpl::variable<bool> _dialogsLoadMayBlockByDate = false; rpl::variable<bool> _dialogsLoadMayBlockByDate = false;
rpl::variable<bool> _dialogsLoadBlockedByDate = false; rpl::variable<bool> _dialogsLoadBlockedByDate = false;
bool _pinnedDialogsReceived = false;
mtpRequestId _pinnedDialogsRequestId = 0;
base::flat_map<FolderId, DialogsLoadState> _foldersLoadState;
rpl::event_stream<SendOptions> _sendActions; rpl::event_stream<SendOptions> _sendActions;
struct ReadRequest { struct ReadRequest {

View File

@ -21,6 +21,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_dialogs.h" // st::dialogsArchiveUserpic #include "styles/style_dialogs.h" // st::dialogsArchiveUserpic
namespace Data { namespace Data {
namespace {
constexpr auto kLoadedChatsMinCount = 20;
} // namespace
// #feed // #feed
//MessagePosition FeedPositionFromMTP(const MTPFeedPosition &position) { //MessagePosition FeedPositionFromMTP(const MTPFeedPosition &position) {
@ -367,6 +372,10 @@ void Folder::applyDialog(const MTPDdialogFolder &data) {
//if (data.has_read_max_position()) { // #feed //if (data.has_read_max_position()) { // #feed
// setUnreadPosition(FeedPositionFromMTP(data.vread_max_position)); // setUnreadPosition(FeedPositionFromMTP(data.vread_max_position));
//} //}
if (_chatsList.size() < kLoadedChatsMinCount) {
session().api().requestFolderDialogs(_id);
}
} }
void Folder::changedInChatListHook(Dialogs::Mode list, bool added) { void Folder::changedInChatListHook(Dialogs::Mode list, bool added) {

View File

@ -1351,24 +1351,25 @@ void Session::applyPinnedDialogs(const QVector<MTPDialogPeer> &list) {
} }
void Session::applyDialogs( void Session::applyDialogs(
FolderId requestFolderId,
const QVector<MTPMessage> &messages, const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &dialogs) { const QVector<MTPDialog> &dialogs) {
App::feedMsgs(messages, NewMessageLast); App::feedMsgs(messages, NewMessageLast);
for (const auto &dialog : dialogs) { for (const auto &dialog : dialogs) {
dialog.match([&](const auto &data) { 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); const auto peerId = peerFromMTP(data.vpeer);
if (!peerId) { if (!peerId) {
return; return;
} }
const auto history = session().data().history(peerId); const auto history = session().data().history(peerId);
history->applyDialog(data); history->applyDialog(requestFolderId, data);
if (!history->useProxyPromotion() && !history->isPinnedDialog()) { if (!history->useProxyPromotion() && !history->isPinnedDialog()) {
const auto date = history->chatListTimeId(); 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); const auto folder = processFolder(dialog.vfolder);
folder->applyDialog(dialog); folder->applyDialog(dialog);

View File

@ -294,6 +294,7 @@ public:
void applyUpdate(const MTPDupdateChatDefaultBannedRights &update); void applyUpdate(const MTPDupdateChatDefaultBannedRights &update);
void applyDialogs( void applyDialogs(
FolderId requestFolderId,
const QVector<MTPMessage> &messages, const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &dialogs); const QVector<MTPDialog> &dialogs);
void addSavedPeersAfter(const QDateTime &date); void addSavedPeersAfter(const QDateTime &date);
@ -603,8 +604,8 @@ private:
int entriesFull, int entriesFull,
int entriesMuted) const; int entriesMuted) const;
void applyDialog(const MTPDdialog &data); void applyDialog(FolderId requestFolderId, const MTPDdialog &data);
void applyDialog(const MTPDdialogFolder &data); void applyDialog(FolderId requestFolderId, const MTPDdialogFolder &data);
void photoApplyFields( void photoApplyFields(
not_null<PhotoData*> photo, not_null<PhotoData*> photo,

View File

@ -1790,55 +1790,6 @@ void DialogsInner::itemRemoved(not_null<const HistoryItem*> item) {
} }
} }
void DialogsInner::dialogsReceived(const QVector<MTPDialog> &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 { bool DialogsInner::uniqueSearchResults() const {
return session().supportMode() return session().supportMode()
&& !session().settings().supportAllSearchResults() && !session().settings().supportAllSearchResults()

View File

@ -39,7 +39,6 @@ class DialogsInner
public: public:
DialogsInner(QWidget *parent, not_null<Window::Controller*> controller); DialogsInner(QWidget *parent, not_null<Window::Controller*> controller);
void dialogsReceived(const QVector<MTPDialog> &dialogs);
bool searchReceived( bool searchReceived(
const QVector<MTPMessage> &result, const QVector<MTPMessage> &result,
DialogsSearchRequestType type, DialogsSearchRequestType type,
@ -48,7 +47,6 @@ public:
const QString &query, const QString &query,
const QVector<MTPPeer> &my, const QVector<MTPPeer> &my,
const QVector<MTPPeer> &result); const QVector<MTPPeer> &result);
void showMore(int32 pixels);
void activate(); void activate();
@ -199,9 +197,6 @@ private:
Dialogs::RowDescriptor chatListEntryFirst() const; Dialogs::RowDescriptor chatListEntryFirst() const;
Dialogs::RowDescriptor chatListEntryLast() const; Dialogs::RowDescriptor chatListEntryLast() const;
void applyDialog(const MTPDdialog &dialog);
void applyFolderDialog(const MTPDdialogFolder &dialog);
void itemRemoved(not_null<const HistoryItem*> item); void itemRemoved(not_null<const HistoryItem*> item);
enum class UpdateRowSection { enum class UpdateRowSection {
Default = (1 << 0), Default = (1 << 0),

View File

@ -122,12 +122,6 @@ protected:
private: private:
void animationCallback(); void animationCallback();
void dialogsReceived(
const MTPmessages_Dialogs &result,
mtpRequestId requestId);
void pinnedDialogsReceived(
const MTPmessages_PeerDialogs &result,
mtpRequestId requestId);
void searchReceived( void searchReceived(
DialogsSearchRequestType type, DialogsSearchRequestType type,
const MTPmessages_Messages &result, const MTPmessages_Messages &result,

View File

@ -2431,7 +2431,7 @@ bool History::isServerSideUnread(not_null<const HistoryItem*> item) const {
: (!_inboxReadBefore || (item->id >= *_inboxReadBefore)); : (!_inboxReadBefore || (item->id >= *_inboxReadBefore));
} }
void History::applyDialog(const MTPDdialog &data) { void History::applyDialog(FolderId requestFolderId, const MTPDdialog &data) {
applyDialogFields( applyDialogFields(
data.vunread_count.v, data.vunread_count.v,
data.vread_inbox_max_id.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) { if (data.has_draft() && data.vdraft.type() == mtpc_draftMessage) {
Data::applyPeerCloudDraft(peer->id, data.vdraft.c_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); session().api().dialogEntryApplied(this);
} }

View File

@ -191,7 +191,7 @@ public:
bool lastMessageKnown() const; bool lastMessageKnown() const;
void unknownMessageDeleted(MsgId messageId); void unknownMessageDeleted(MsgId messageId);
void applyDialogTopMessage(MsgId topMessageId); void applyDialogTopMessage(MsgId topMessageId);
void applyDialog(const MTPDdialog &data); void applyDialog(FolderId requestFolderId, const MTPDdialog &data);
void applyDialogFields( void applyDialogFields(
int unreadCount, int unreadCount,
MsgId maxInboxRead, MsgId maxInboxRead,