diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 2870bde616..4aad67183b 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -146,6 +146,29 @@ void ApiWrap::applyUpdates( App::main()->feedUpdates(updates, sentMessageRandomId); } +void ApiWrap::applyDialogsPinned(const QVector &list) { + for (auto i = list.size(); i != 0;) { + const auto &dialog = list[--i]; + switch (dialog.type()) { + case mtpc_dialog: { + const auto &dialogData = dialog.c_dialog(); + if (const auto peer = peerFromMTP(dialogData.vpeer)) { + const auto history = App::history(peer); + history->setPinnedDialog(dialogData.is_pinned()); + } + } break; + + case mtpc_dialogFeed: { + const auto &feedData = dialog.c_dialogFeed(); + const auto feedId = feedData.vfeed_id.v; + // #TODO feeds + } break; + + default: Unexpected("Type in ApiWrap::applyDialogsPinned."); + } + } +} + void ApiWrap::sendMessageFail(const RPCError &error) { if (error.type() == qstr("PEER_FLOOD")) { Ui::show(Box( diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index b7aae651e3..9c708f9841 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -45,8 +45,13 @@ public: void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0); + void applyDialogsPinned(const QVector &list); + using RequestMessageDataCallback = base::lambda; - void requestMessageData(ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback); + void requestMessageData( + ChannelData *channel, + MsgId msgId, + RequestMessageDataCallback callback); void requestContacts(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 8e15941719..f80bd0261a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1494,59 +1494,73 @@ void DialogsInner::itemRemoved(not_null item) { void DialogsInner::dialogsReceived(const QVector &added) { for (const auto &dialog : added) { - if (dialog.type() != mtpc_dialog) { - continue; - } - - const auto &d = dialog.c_dialog(); - const auto peerId = peerFromMTP(d.vpeer); - if (!peerId) { - continue; - } - - auto history = App::historyFromDialog(peerId, d.vunread_count.v, d.vread_inbox_max_id.v, d.vread_outbox_max_id.v); - history->setUnreadMentionsCount(d.vunread_mentions_count.v); - auto peer = history->peer; - if (auto channel = peer->asChannel()) { - if (d.has_pts()) { - channel->ptsReceived(d.vpts.v); - } - if (!channel->amCreator()) { - if (auto topMsg = App::histItemById(channel, d.vtop_message.v)) { - if (topMsg->date <= date(channel->date)) { - Auth().api().requestSelfParticipant(channel); - } - } - } - } - App::main()->applyNotifySetting( - MTP_notifyPeer(d.vpeer), - d.vnotify_settings, - history); - - if (!history->isPinnedDialog() && !history->lastMsgDate.isNull()) { - addSavedPeersAfter(history->lastMsgDate); - } - _contactsNoDialogs->del(peer); - if (peer->migrateFrom()) { - removeDialog(App::historyLoaded(peer->migrateFrom()->id)); - } else if (peer->migrateTo() && peer->migrateTo()->amIn()) { - removeDialog(history); - } - - if (d.has_draft() && d.vdraft.type() == mtpc_draftMessage) { - auto &draft = d.vdraft.c_draftMessage(); - Data::applyPeerCloudDraft(peerId, draft); + switch (dialog.type()) { + case mtpc_dialog: applyDialog(dialog.c_dialog()); break; + case mtpc_dialogFeed: applyFeedDialog(dialog.c_dialogFeed()); break; + default: Unexpected("Type in DialogsInner::dialogsReceived"); } } Notify::unreadCounterUpdated(); refresh(); } +void DialogsInner::applyDialog(const MTPDdialog &dialog) { + const auto peerId = peerFromMTP(dialog.vpeer); + if (!peerId) { + return; + } + + const auto history = App::historyFromDialog( + peerId, + dialog.vunread_count.v, + dialog.vread_inbox_max_id.v, + dialog.vread_outbox_max_id.v); + history->setUnreadMentionsCount(dialog.vunread_mentions_count.v); + const auto peer = history->peer; + if (const auto channel = peer->asChannel()) { + if (dialog.has_pts()) { + channel->ptsReceived(dialog.vpts.v); + } + if (!channel->amCreator()) { + const auto topMsgId = FullMsgId( + peerToChannel(channel->id), + dialog.vtop_message.v); + if (const auto topMsg = App::histItemById(topMsgId)) { + if (topMsg->date <= date(channel->date)) { + Auth().api().requestSelfParticipant(channel); + } + } + } + } + App::main()->applyNotifySetting( + MTP_notifyPeer(dialog.vpeer), + dialog.vnotify_settings, + history); + + if (!history->isPinnedDialog() && !history->lastMsgDate.isNull()) { + addSavedPeersAfter(history->lastMsgDate); + } + _contactsNoDialogs->del(peer); + if (peer->migrateFrom()) { + removeDialog(App::historyLoaded(peer->migrateFrom()->id)); + } else if (peer->migrateTo() && peer->migrateTo()->amIn()) { + removeDialog(history); + } + + if (dialog.has_draft() && dialog.vdraft.type() == mtpc_draftMessage) { + const auto &draft = dialog.vdraft.c_draftMessage(); + Data::applyPeerCloudDraft(peerId, draft); + } +} + +void DialogsInner::applyFeedDialog(const MTPDdialogFeed &dialog) { + // #TODO feeds +} + void DialogsInner::addSavedPeersAfter(const QDateTime &date) { - SavedPeersByTime &saved(cRefSavedPeersByTime()); + auto &saved = cRefSavedPeersByTime(); while (!saved.isEmpty() && (date.isNull() || date < saved.lastKey())) { - History *history = App::history(saved.last()->id); + const auto history = App::history(saved.last()->id); history->setChatsListDate(saved.lastKey()); _contactsNoDialogs->del(history->peer); saved.remove(saved.lastKey(), saved.last()); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 2a88cfa845..1f1b14b052 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -152,12 +152,27 @@ private: void setPeerSearchPressed(int pressed); void setSearchedPressed(int pressed); bool isPressed() const { - return _importantSwitchPressed || _pressed || (_hashtagPressed >= 0) || (_filteredPressed >= 0) || (_peerSearchPressed >= 0) || (_searchedPressed >= 0); + return _importantSwitchPressed + || _pressed + || (_hashtagPressed >= 0) + || (_filteredPressed >= 0) + || (_peerSearchPressed >= 0) + || (_searchedPressed >= 0); } bool isSelected() const { - return _importantSwitchSelected || _selected || (_hashtagSelected >= 0) || (_filteredSelected >= 0) || (_peerSearchSelected >= 0) || (_searchedSelected >= 0); + return _importantSwitchSelected + || _selected + || (_hashtagSelected >= 0) + || (_filteredSelected >= 0) + || (_peerSearchSelected >= 0) + || (_searchedSelected >= 0); } - void handlePeerNameChange(not_null peer, const PeerData::NameFirstChars &oldChars); + void handlePeerNameChange( + not_null peer, + const PeerData::NameFirstChars &oldChars); + + void applyDialog(const MTPDdialog &dialog); + void applyFeedDialog(const MTPDdialogFeed &dialog); void itemRemoved(not_null item); enum class UpdateRowSection { @@ -170,7 +185,11 @@ private: using UpdateRowSections = base::flags; friend inline constexpr auto is_flag_type(UpdateRowSection) { return true; }; - void updateDialogRow(PeerData *peer, MsgId msgId, QRect updateRect, UpdateRowSections sections = UpdateRowSection::All); + void updateDialogRow( + PeerData *peer, + MsgId msgId, + QRect updateRect, + UpdateRowSections sections = UpdateRowSection::All); int dialogsOffset() const; int filteredOffset() const; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index e5cf36237b..f9f01ba719 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -313,127 +313,122 @@ void DialogsWidget::notify_historyMuteUpdated(History *history) { _inner->notify_historyMuteUpdated(history); } -void DialogsWidget::unreadCountsReceived(const QVector &dialogs) { -} - void DialogsWidget::dialogsReceived( const MTPmessages_Dialogs &dialogs, mtpRequestId requestId) { if (_dialogsRequestId != requestId) return; - const QVector *dialogsList = 0; - const QVector *messagesList = 0; - switch (dialogs.type()) { - case mtpc_messages_dialogs: { - auto &data = dialogs.c_messages_dialogs(); - App::feedUsers(data.vusers); - App::feedChats(data.vchats); - messagesList = &data.vmessages.v; - dialogsList = &data.vdialogs.v; - _dialogsFull = true; - } break; - case mtpc_messages_dialogsSlice: { - auto &data = dialogs.c_messages_dialogsSlice(); - App::feedUsers(data.vusers); - App::feedChats(data.vchats); - messagesList = &data.vmessages.v; - dialogsList = &data.vdialogs.v; - } break; - } - - Auth().api().requestContacts(); - - if (dialogsList) { - TimeId lastDate = 0; - PeerId lastPeer = 0; - MsgId lastMsgId = 0; - for (int i = dialogsList->size(); i > 0;) { - auto &dialog = dialogsList->at(--i); - if (dialog.type() != mtpc_dialog) { - continue; - } - - const auto &dialogData = dialog.c_dialog(); - if (const auto peer = peerFromMTP(dialogData.vpeer)) { - const auto history = App::history(peer); - history->setPinnedDialog(dialogData.is_pinned()); - - if (!lastDate) { - if (!lastPeer) lastPeer = peer; - if (auto msgId = dialogData.vtop_message.v) { - if (!lastMsgId) lastMsgId = msgId; - for (int j = messagesList->size(); j > 0;) { - auto &message = messagesList->at(--j); - if (idFromMessage(message) == msgId && peerFromMessage(message) == peer) { - if (auto date = dateFromMessage(message)) { - lastDate = date; - } - break; - } - } - } - } - } - } - if (lastDate) { - _dialogsOffsetDate = lastDate; - _dialogsOffsetId = lastMsgId; - _dialogsOffsetPeer = App::peer(lastPeer); - } else { + const auto [dialogsList, messagesList] = [&] { + const auto process = [&](const auto &data) { + App::feedUsers(data.vusers); + App::feedChats(data.vchats); + return std::make_tuple(&data.vdialogs.v, &data.vmessages.v); + }; + switch (dialogs.type()) { + case mtpc_messages_dialogs: _dialogsFull = true; + return process(dialogs.c_messages_dialogs()); + + case mtpc_messages_dialogsSlice: + return process(dialogs.c_messages_dialogsSlice()); } + Unexpected("Type in DialogsWidget::dialogsReceived"); + }(); - Assert(messagesList != nullptr); - App::feedMsgs(*messagesList, NewMessageLast); + updateDialogsOffset(*dialogsList, *messagesList); - unreadCountsReceived(*dialogsList); - _inner->dialogsReceived(*dialogsList); - onListScroll(); - } else { - _dialogsFull = true; - } + applyReceivedDialogs(*dialogsList, *messagesList); _dialogsRequestId = 0; loadDialogs(); Auth().data().moreChatsLoaded().notify(); - if (_dialogsFull) { + if (_dialogsFull && _pinnedDialogsReceived) { Auth().data().allChatsLoaded().set(true); } + Auth().api().requestContacts(); +} + +void DialogsWidget::updateDialogsOffset( + const QVector &dialogs, + const QVector &messages) { + auto lastDate = TimeId(0); + auto lastPeer = PeerId(0); + auto lastMsgId = MsgId(0); + const auto fillFromDialog = [&](const auto &dialog) { + const auto peer = peerFromMTP(dialog.vpeer); + const auto msgId = dialog.vtop_message.v; + if (!peer || !msgId) { + return; + } + if (!lastPeer) { + lastPeer = peer; + } + if (!lastMsgId) { + lastMsgId = msgId; + } + for (auto j = messages.size(); j != 0;) { + const auto &message = messages[--j]; + if (idFromMessage(message) == msgId + && peerFromMessage(message) == peer) { + if (const auto date = dateFromMessage(message)) { + lastDate = date; + } + return; + } + } + }; + for (auto i = dialogs.size(); i != 0;) { + const auto &dialog = dialogs[--i]; + switch (dialog.type()) { + case mtpc_dialog: fillFromDialog(dialog.c_dialog()); break; + case mtpc_dialogFeed: fillFromDialog(dialog.c_dialogFeed()); break; + default: Unexpected("Type in DialogsWidget::updateDialogsOffset"); + } + if (lastDate) { + break; + } + } + if (lastDate) { + _dialogsOffsetDate = lastDate; + _dialogsOffsetId = lastMsgId; + _dialogsOffsetPeer = App::peer(lastPeer); + } else { + _dialogsFull = true; + } } -void DialogsWidget::pinnedDialogsReceived(const MTPmessages_PeerDialogs &dialogs, mtpRequestId requestId) { +void DialogsWidget::pinnedDialogsReceived( + const MTPmessages_PeerDialogs &result, + mtpRequestId requestId) { + Expects(result.type() == mtpc_messages_peerDialogs); + if (_pinnedDialogsRequestId != requestId) return; - if (dialogs.type() == mtpc_messages_peerDialogs) { - App::histories().clearPinned(); + App::histories().clearPinned(); - auto &dialogsData = dialogs.c_messages_peerDialogs(); - App::feedUsers(dialogsData.vusers); - App::feedChats(dialogsData.vchats); - auto &list = dialogsData.vdialogs.v; - for (auto i = list.size(); i > 0;) { - auto &dialog = list[--i]; - if (dialog.type() != mtpc_dialog) { - continue; - } + auto &data = result.c_messages_peerDialogs(); + App::feedUsers(data.vusers); + App::feedChats(data.vchats); - const auto &dialogData = dialog.c_dialog(); - if (const auto peer = peerFromMTP(dialogData.vpeer)) { - const auto history = App::history(peer); - history->setPinnedDialog(dialogData.is_pinned()); - } - } - App::feedMsgs(dialogsData.vmessages, NewMessageLast); - unreadCountsReceived(list); - _inner->dialogsReceived(list); - onListScroll(); - } + applyReceivedDialogs(data.vdialogs.v, data.vmessages.v); _pinnedDialogsRequestId = 0; _pinnedDialogsReceived = true; Auth().data().moreChatsLoaded().notify(); + if (_dialogsFull && _pinnedDialogsReceived) { + Auth().data().allChatsLoaded().set(true); + } +} + +void DialogsWidget::applyReceivedDialogs( + const QVector &dialogs, + const QVector &messages) { + Auth().api().applyDialogsPinned(dialogs); + App::feedMsgs(messages, NewMessageLast); + _inner->dialogsReceived(dialogs); + onListScroll(); } bool DialogsWidget::dialogsFailed(const RPCError &error, mtpRequestId requestId) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 02f0c9ab0a..b031db3ebc 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -131,10 +131,20 @@ protected: private: void animationCallback(); - void dialogsReceived(const MTPmessages_Dialogs &dialogs, mtpRequestId requestId); - void pinnedDialogsReceived(const MTPmessages_PeerDialogs &dialogs, mtpRequestId requestId); + void dialogsReceived( + const MTPmessages_Dialogs &result, + mtpRequestId requestId); + void pinnedDialogsReceived( + const MTPmessages_PeerDialogs &result, + mtpRequestId requestId); void searchReceived(DialogsSearchRequestType type, const MTPmessages_Messages &result, mtpRequestId requestId); void peerSearchReceived(const MTPcontacts_Found &result, mtpRequestId requestId); + void updateDialogsOffset( + const QVector &dialogs, + const QVector &messages); + void applyReceivedDialogs( + const QVector &dialogs, + const QVector &messages); void setSearchInPeer(PeerData *peer, UserData *from = nullptr); void showSearchFrom(); @@ -146,7 +156,6 @@ private: void updateControlsGeometry(); void updateForwardBar(); - void unreadCountsReceived(const QVector &dialogs); bool dialogsFailed(const RPCError &error, mtpRequestId req); bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); bool peopleFailed(const RPCError &error, mtpRequestId req);