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(); })
, _draftsSaveTimer([=] { saveDraftsToCloud(); })
, _featuredSetsReadTimer([=] { readFeaturedSets(); })
, _dialogsLoadState(std::make_unique<DialogsLoadState>())
, _fileLoader(std::make_unique<TaskQueue>(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<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().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<MTPDialog> &dialogs,
const QVector<MTPMessage> &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();

View File

@ -80,6 +80,7 @@ public:
void requestContacts();
void requestDialogs();
void requestFolderDialogs(FolderId folderId);
void requestPinnedDialogs();
void requestMoreBlockedByDateDialogs();
rpl::producer<bool> 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<MTPDialog> &dialogs,
const QVector<MTPMessage> &messages);
void applyReceivedDialogs(
const QVector<MTPDialog> &dialogs,
const QVector<MTPMessage> &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> _dialogsLoadState;
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> _dialogsLoadBlockedByDate = false;
bool _pinnedDialogsReceived = false;
mtpRequestId _pinnedDialogsRequestId = 0;
base::flat_map<FolderId, DialogsLoadState> _foldersLoadState;
rpl::event_stream<SendOptions> _sendActions;
struct ReadRequest {

View File

@ -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) {

View File

@ -1351,24 +1351,25 @@ void Session::applyPinnedDialogs(const QVector<MTPDialogPeer> &list) {
}
void Session::applyDialogs(
FolderId requestFolderId,
const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &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);

View File

@ -294,6 +294,7 @@ public:
void applyUpdate(const MTPDupdateChatDefaultBannedRights &update);
void applyDialogs(
FolderId requestFolderId,
const QVector<MTPMessage> &messages,
const QVector<MTPDialog> &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<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 {
return session().supportMode()
&& !session().settings().supportAllSearchResults()

View File

@ -39,7 +39,6 @@ class DialogsInner
public:
DialogsInner(QWidget *parent, not_null<Window::Controller*> controller);
void dialogsReceived(const QVector<MTPDialog> &dialogs);
bool searchReceived(
const QVector<MTPMessage> &result,
DialogsSearchRequestType type,
@ -48,7 +47,6 @@ public:
const QString &query,
const QVector<MTPPeer> &my,
const QVector<MTPPeer> &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<const HistoryItem*> item);
enum class UpdateRowSection {
Default = (1 << 0),

View File

@ -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,

View File

@ -2431,7 +2431,7 @@ bool History::isServerSideUnread(not_null<const HistoryItem*> 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);
}

View File

@ -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,