From 2d1dcb36cb53f57b30473786799c77e6da3040e6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 23 Apr 2019 13:40:14 +0400 Subject: [PATCH] Use folder_id / still_unread_count from updates. --- Telegram/SourceFiles/apiwrap.cpp | 205 ++++-------------- Telegram/SourceFiles/apiwrap.h | 7 +- Telegram/SourceFiles/app.cpp | 15 -- Telegram/SourceFiles/app.h | 2 - Telegram/SourceFiles/data/data_channel.cpp | 109 ++++++++++ Telegram/SourceFiles/data/data_channel.h | 4 + Telegram/SourceFiles/data/data_chat.cpp | 41 +++- Telegram/SourceFiles/data/data_chat.h | 8 +- Telegram/SourceFiles/data/data_peer.cpp | 11 + Telegram/SourceFiles/data/data_peer.h | 2 + Telegram/SourceFiles/data/data_user.cpp | 45 ++++ Telegram/SourceFiles/data/data_user.h | 6 + Telegram/SourceFiles/history/history.cpp | 64 +++--- Telegram/SourceFiles/history/history.h | 10 +- Telegram/SourceFiles/history/history_item.cpp | 6 +- .../SourceFiles/history/history_widget.cpp | 2 +- Telegram/SourceFiles/mainwidget.cpp | 30 ++- 17 files changed, 343 insertions(+), 224 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 2f251066d7..714ed6d5d0 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1184,124 +1184,24 @@ void ApiWrap::gotChatFull( _session->data().processUsers(d.vusers); _session->data().processChats(d.vchats); - using UpdateFlag = Notify::PeerUpdate::Flag; - if (const auto chat = peer->asChat()) { - if (d.vfull_chat.type() != mtpc_chatFull) { - LOG(("MTP Error: bad type in gotChatFull for chat: %1" - ).arg(d.vfull_chat.type())); - return; - } - auto &f = d.vfull_chat.c_chatFull(); - Data::ApplyChatParticipants(chat, f.vparticipants); - if (f.has_bot_info()) { - for (const auto &item : f.vbot_info.v) { - item.match([&](const MTPDbotInfo &data) { - if (const auto bot = _session->data().userLoaded(data.vuser_id.v)) { - bot->setBotInfo(item); - fullPeerUpdated().notify(bot); - } - }); - } - } - chat->setFullFlags(f.vflags.v); - chat->setUserpicPhoto(f.has_chat_photo() - ? f.vchat_photo - : MTPPhoto(MTP_photoEmpty(MTP_long(0)))); - chat->setInviteLink( - (f.vexported_invite.type() == mtpc_chatInviteExported - ? qs(f.vexported_invite.c_chatInviteExported().vlink) - : QString())); - if (f.has_pinned_msg_id()) { - chat->setPinnedMessageId(f.vpinned_msg_id.v); + d.vfull_chat.match([&](const MTPDchatFull &data) { + if (const auto chat = peer->asChat()) { + Data::ApplyChatUpdate(chat, data); } else { - chat->clearPinnedMessage(); - } - chat->fullUpdated(); - - notifySettingReceived( - MTP_inputNotifyPeer(peer->input), - f.vnotify_settings); - } else if (const auto channel = peer->asChannel()) { - if (d.vfull_chat.type() != mtpc_channelFull) { LOG(("MTP Error: bad type in gotChatFull for channel: %1" ).arg(d.vfull_chat.type())); - return; } - auto &f = d.vfull_chat.c_channelFull(); - channel->setAvailableMinId(f.vavailable_min_id.v); - auto canViewAdmins = channel->canViewAdmins(); - auto canViewMembers = channel->canViewMembers(); - auto canEditStickers = channel->canEditStickers(); - - channel->setFullFlags(f.vflags.v); - channel->setUserpicPhoto(f.vchat_photo); - if (f.has_migrated_from_chat_id()) { - channel->addFlags(MTPDchannel::Flag::f_megagroup); - const auto chat = channel->owner().chat( - f.vmigrated_from_chat_id.v); - Data::ApplyMigration(chat, channel); - } - for (const auto &item : f.vbot_info.v) { - auto &owner = channel->owner(); - item.match([&](const MTPDbotInfo &info) { - if (const auto user = owner.userLoaded(info.vuser_id.v)) { - user->setBotInfo(item); - fullPeerUpdated().notify(user); - } - }); - } - channel->setAbout(qs(f.vabout)); - channel->setMembersCount(f.has_participants_count() ? f.vparticipants_count.v : 0); - channel->setAdminsCount(f.has_admins_count() ? f.vadmins_count.v : 0); - channel->setRestrictedCount(f.has_banned_count() ? f.vbanned_count.v : 0); - channel->setKickedCount(f.has_kicked_count() ? f.vkicked_count.v : 0); - channel->setInviteLink((f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString()); - if (const auto history = _session->data().historyLoaded(channel)) { - history->clearUpTill(f.vavailable_min_id.v); - if (history->folderKnown()) { - history->applyDialogFields( - history->folder(), - f.vunread_count.v, - f.vread_inbox_max_id.v, - f.vread_outbox_max_id.v); - } else { - requestDialogEntry(history); - } - } - if (f.has_pinned_msg_id()) { - channel->setPinnedMessageId(f.vpinned_msg_id.v); + }, [&](const MTPDchannelFull &data) { + if (const auto channel = peer->asChannel()) { + Data::ApplyChannelUpdate(channel, data); } else { - channel->clearPinnedMessage(); + LOG(("MTP Error: bad type in gotChatFull for chat: %1" + ).arg(d.vfull_chat.type())); } - if (channel->isMegagroup()) { - auto stickersChanged = (canEditStickers != channel->canEditStickers()); - auto stickerSet = (f.has_stickerset() ? &f.vstickerset.c_stickerSet() : nullptr); - auto newSetId = (stickerSet ? stickerSet->vid.v : 0); - auto oldSetId = (channel->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) - ? channel->mgInfo->stickerSet.c_inputStickerSetID().vid.v - : 0; - if (oldSetId != newSetId) { - channel->mgInfo->stickerSet = stickerSet - ? MTP_inputStickerSetID(stickerSet->vid, stickerSet->vaccess_hash) - : MTP_inputStickerSetEmpty(); - stickersChanged = true; - } - if (stickersChanged) { - Notify::peerUpdatedDelayed(channel, UpdateFlag::ChannelStickersChanged); - } - } - channel->fullUpdated(); - - if (canViewAdmins != channel->canViewAdmins() - || canViewMembers != channel->canViewMembers()) { - Notify::peerUpdatedDelayed(channel, UpdateFlag::RightsChanged); - } - - notifySettingReceived(MTP_inputNotifyPeer(peer->input), f.vnotify_settings); - } + }); if (req) { - auto i = _fullPeerRequests.find(peer); + const auto i = _fullPeerRequests.find(peer); if (i != _fullPeerRequests.cend() && i.value() == req) { _fullPeerRequests.erase(i); } @@ -1314,7 +1214,6 @@ void ApiWrap::gotUserFull( const MTPUserFull &result, mtpRequestId req) { const auto &d = result.c_userFull(); - if (user == _session->user() && !_session->validateSelf(d.vuser)) { constexpr auto kRequestUserAgainTimeout = crl::time(10000); App::CallDelayed(kRequestUserAgainTimeout, _session, [=] { @@ -1322,34 +1221,10 @@ void ApiWrap::gotUserFull( }); return; } - _session->data().processUser(d.vuser); - if (d.has_profile_photo()) { - _session->data().processPhoto(d.vprofile_photo); - } - App::feedUserLink(MTP_int(peerToUser(user->id)), d.vlink.c_contacts_link().vmy_link, d.vlink.c_contacts_link().vforeign_link); - if (App::main()) { - notifySettingReceived(MTP_inputNotifyPeer(user->input), d.vnotify_settings); - } - - if (d.has_bot_info()) { - user->setBotInfo(d.vbot_info); - } else { - user->setBotInfoVersion(-1); - } - if (d.has_pinned_msg_id()) { - user->setPinnedMessageId(d.vpinned_msg_id.v); - } else { - user->clearPinnedMessage(); - } - user->setFullFlags(d.vflags.v); - user->setBlockStatus(d.is_blocked() ? UserData::BlockStatus::Blocked : UserData::BlockStatus::NotBlocked); - user->setCallsStatus(d.is_phone_calls_private() ? UserData::CallsStatus::Private : d.is_phone_calls_available() ? UserData::CallsStatus::Enabled : UserData::CallsStatus::Disabled); - user->setAbout(d.has_about() ? qs(d.vabout) : QString()); - user->setCommonChatsCount(d.vcommon_chats_count.v); - user->fullUpdated(); + Data::ApplyUserUpdate(user, d); if (req) { - auto i = _fullPeerRequests.find(user); + const auto i = _fullPeerRequests.find(user); if (i != _fullPeerRequests.cend() && i.value() == req) { _fullPeerRequests.erase(i); } @@ -2356,18 +2231,20 @@ void ApiWrap::requestNotifySettings(const MTPInputNotifyPeer &peer) { if (_notifySettingRequests.find(key) != end(_notifySettingRequests)) { return; } - auto requestId = request(MTPaccount_GetNotifySettings( + const auto requestId = request(MTPaccount_GetNotifySettings( peer )).done([=](const MTPPeerNotifySettings &result) { - notifySettingReceived(peer, result); + applyNotifySettings(peer, result); _notifySettingRequests.erase(key); }).fail([=](const RPCError &error) { - notifySettingReceived(peer, MTP_peerNotifySettings( - MTP_flags(0), - MTPBool(), - MTPBool(), - MTPint(), - MTPstring())); + applyNotifySettings( + peer, + MTP_peerNotifySettings( + MTP_flags(0), + MTPBool(), + MTPBool(), + MTPint(), + MTPstring())); _notifySettingRequests.erase(key); }).send(); @@ -2765,7 +2642,7 @@ void ApiWrap::checkQuitPreventFinished() { } } -void ApiWrap::notifySettingReceived( +void ApiWrap::applyNotifySettings( MTPInputNotifyPeer notifyPeer, const MTPPeerNotifySettings &settings) { switch (notifyPeer.type()) { @@ -3744,17 +3621,18 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) { } break; case mtpc_updateReadMessagesContents: { - auto &d = update.c_updateReadMessagesContents(); + const auto &d = update.c_updateReadMessagesContents(); auto possiblyReadMentions = base::flat_set(); for (const auto &msgId : d.vmessages.v) { - if (auto item = App::histItemById(NoChannel, msgId.v)) { + if (const auto item = App::histItemById(NoChannel, msgId.v)) { if (item->isUnreadMedia() || item->isUnreadMention()) { item->markMediaRead(); _session->data().requestItemRepaint(item); - if (item->out() && item->history()->peer->isUser()) { - auto when = App::main()->requestingDifference() ? 0 : unixtime(); - item->history()->peer->asUser()->madeAction(when); + if (item->out() + && item->history()->peer->isUser() + && !App::main()->requestingDifference()) { + item->history()->peer->asUser()->madeAction(unixtime()); } } } else { @@ -3766,15 +3644,28 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) { } break; case mtpc_updateReadHistoryInbox: { - auto &d = update.c_updateReadHistoryInbox(); - App::feedInboxRead(peerFromMTP(d.vpeer), d.vmax_id.v); + const auto &d = update.c_updateReadHistoryInbox(); + const auto peer = peerFromMTP(d.vpeer); + if (const auto history = _session->data().historyLoaded(peer)) { + const auto folderId = d.has_folder_id() ? d.vfolder_id.v : 0; + history->applyInboxReadUpdate( + folderId, + d.vmax_id.v, + d.vstill_unread_count.v); + } } break; case mtpc_updateReadHistoryOutbox: { - auto &d = update.c_updateReadHistoryOutbox(); - auto peerId = peerFromMTP(d.vpeer); - auto when = App::main()->requestingDifference() ? 0 : unixtime(); - App::feedOutboxRead(peerId, d.vmax_id.v, when); + const auto &d = update.c_updateReadHistoryOutbox(); + const auto peer = peerFromMTP(d.vpeer); + if (const auto history = _session->data().historyLoaded(peer)) { + history->outboxRead(d.vmax_id.v); + if (!App::main()->requestingDifference()) { + if (const auto user = history->peer->asUser()) { + user->madeAction(unixtime()); + } + } + } } break; case mtpc_updateWebPage: { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 24315594ac..7b7a997828 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -63,6 +63,9 @@ public: ApiWrap(not_null session); void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0); + void applyNotifySettings( + MTPInputNotifyPeer peer, + const MTPPeerNotifySettings &settings); void savePinnedOrder(Data::Folder *folder); void toggleHistoryArchived( @@ -524,10 +527,6 @@ private: MsgRange range, const MTPupdates_ChannelDifference &result); - void notifySettingReceived( - MTPInputNotifyPeer peer, - const MTPPeerNotifySettings &settings); - void stickerSetDisenabled(mtpRequestId requestId); void stickersSaveOrder(); diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 5ebfd63c2f..16f3328189 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -230,21 +230,6 @@ namespace App { return feedMsgs(msgs.v, type); } - void feedInboxRead(const PeerId &peer, MsgId upTo) { - if (const auto history = Auth().data().historyLoaded(peer)) { - history->inboxRead(upTo); - } - } - - void feedOutboxRead(const PeerId &peer, MsgId upTo, TimeId when) { - if (auto history = Auth().data().historyLoaded(peer)) { - history->outboxRead(upTo); - if (const auto user = history->peer->asUser()) { - user->madeAction(when); - } - } - } - inline MsgsData *fetchMsgsData(ChannelId channelId, bool insert = true) { if (channelId == NoChannel) return &msgsData; ChannelMsgsData::iterator i = channelMsgsData.find(channelId); diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index f7051d83c0..c1fd3b6283 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -72,8 +72,6 @@ namespace App { void checkSavedGif(HistoryItem *item); void feedMsgs(const QVector &msgs, NewMessageType type); void feedMsgs(const MTPVector &msgs, NewMessageType type); - void feedInboxRead(const PeerId &peer, MsgId upTo); - void feedOutboxRead(const PeerId &peer, MsgId upTo, TimeId when); void feedWereDeleted(ChannelId channelId, const QVector &msgsIds); void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index b58b87577b..20f7a471db 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_session.h" #include "data/data_folder.h" +#include "history/history.h" #include "observer_peer.h" #include "auth_session.h" #include "apiwrap.h" @@ -549,4 +550,112 @@ void ApplyChannelUpdate( channel->setDefaultRestrictions(update.vdefault_banned_rights); } +void ApplyChannelUpdate( + not_null channel, + const MTPDchannelFull &update) { + channel->setAvailableMinId(update.vavailable_min_id.v); + auto canViewAdmins = channel->canViewAdmins(); + auto canViewMembers = channel->canViewMembers(); + auto canEditStickers = channel->canEditStickers(); + + channel->setFullFlags(update.vflags.v); + channel->setUserpicPhoto(update.vchat_photo); + if (update.has_migrated_from_chat_id()) { + channel->addFlags(MTPDchannel::Flag::f_megagroup); + const auto chat = channel->owner().chat( + update.vmigrated_from_chat_id.v); + Data::ApplyMigration(chat, channel); + } + for (const auto &item : update.vbot_info.v) { + auto &owner = channel->owner(); + item.match([&](const MTPDbotInfo &info) { + if (const auto user = owner.userLoaded(info.vuser_id.v)) { + user->setBotInfo(item); + channel->session().api().fullPeerUpdated().notify(user); + } + }); + } + channel->setAbout(qs(update.vabout)); + channel->setMembersCount(update.has_participants_count() + ? update.vparticipants_count.v + : 0); + channel->setAdminsCount(update.has_admins_count() + ? update.vadmins_count.v + : 0); + channel->setRestrictedCount(update.has_banned_count() + ? update.vbanned_count.v + : 0); + channel->setKickedCount(update.has_kicked_count() + ? update.vkicked_count.v + : 0); + channel->setInviteLink(update.vexported_invite.match([&]( + const MTPDchatInviteExported & data) { + return qs(data.vlink); + }, [&](const MTPDchatInviteEmpty &) { + return QString(); + })); + if (const auto history = channel->owner().historyLoaded(channel)) { + history->clearUpTill(update.vavailable_min_id.v); + + const auto folderId = update.has_folder_id() + ? update.vfolder_id.v + : 0; + const auto folder = folderId + ? channel->owner().folderLoaded(folderId) + : nullptr; + if (folder && history->folder() != folder) { + // If history folder is unknown or not synced, request both. + channel->session().api().requestDialogEntry(history); + channel->session().api().requestDialogEntry(folder); + } else if (!history->folderKnown() + || channel->pts() != update.vpts.v) { + channel->session().api().requestDialogEntry(history); + } else { + history->applyDialogFields( + history->folder(), + update.vunread_count.v, + update.vread_inbox_max_id.v, + update.vread_outbox_max_id.v); + } + } + if (update.has_pinned_msg_id()) { + channel->setPinnedMessageId(update.vpinned_msg_id.v); + } else { + channel->clearPinnedMessage(); + } + if (channel->isMegagroup()) { + const auto stickerSet = update.has_stickerset() + ? &update.vstickerset.c_stickerSet() + : nullptr; + const auto newSetId = (stickerSet ? stickerSet->vid.v : 0); + const auto oldSetId = (channel->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) + ? channel->mgInfo->stickerSet.c_inputStickerSetID().vid.v + : 0; + const auto stickersChanged = (canEditStickers != channel->canEditStickers()) + || (oldSetId != newSetId); + if (oldSetId != newSetId) { + channel->mgInfo->stickerSet = stickerSet + ? MTP_inputStickerSetID(stickerSet->vid, stickerSet->vaccess_hash) + : MTP_inputStickerSetEmpty(); + } + if (stickersChanged) { + Notify::peerUpdatedDelayed( + channel, + Notify::PeerUpdate::Flag::ChannelStickersChanged); + } + } + channel->fullUpdated(); + + if (canViewAdmins != channel->canViewAdmins() + || canViewMembers != channel->canViewMembers()) { + Notify::peerUpdatedDelayed( + channel, + Notify::PeerUpdate::Flag::RightsChanged); + } + + channel->session().api().applyNotifySettings( + MTP_inputNotifyPeer(channel->input), + update.vnotify_settings); +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 748f5cbce9..972069dcfa 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -394,4 +394,8 @@ void ApplyChannelUpdate( not_null channel, const MTPDupdateChatDefaultBannedRights &update); +void ApplyChannelUpdate( + not_null channel, + const MTPDchannelFull &update); + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index 1c2092d1c2..d4259b3224 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -186,7 +186,7 @@ namespace Data { void ApplyChatUpdate( not_null chat, const MTPDupdateChatParticipants &update) { - ApplyChatParticipants(chat, update.vparticipants); + ApplyChatUpdate(chat, update.vparticipants); } void ApplyChatUpdate( @@ -317,7 +317,44 @@ void ApplyChatUpdate( chat->setDefaultRestrictions(update.vdefault_banned_rights); } -void ApplyChatParticipants( +void ApplyChatUpdate(not_null chat, const MTPDchatFull &update) { + ApplyChatUpdate(chat, update.vparticipants); + + if (update.has_bot_info()) { + for (const auto &item : update.vbot_info.v) { + item.match([&](const MTPDbotInfo &data) { + const auto userId = data.vuser_id.v; + if (const auto bot = chat->owner().userLoaded(userId)) { + bot->setBotInfo(item); + chat->session().api().fullPeerUpdated().notify(bot); + } + }); + } + } + chat->setFullFlags(update.vflags.v); + chat->setUserpicPhoto(update.has_chat_photo() + ? update.vchat_photo + : MTPPhoto(MTP_photoEmpty(MTP_long(0)))); + chat->setInviteLink(update.vexported_invite.match([&]( + const MTPDchatInviteExported &data) { + return qs(data.vlink); + }, [&](const MTPDchatInviteEmpty &) { + return QString(); + })); + if (update.has_pinned_msg_id()) { + chat->setPinnedMessageId(update.vpinned_msg_id.v); + } else { + chat->clearPinnedMessage(); + } + chat->checkFolder(update.has_folder_id() ? update.vfolder_id.v : 0); + chat->fullUpdated(); + + chat->session().api().applyNotifySettings( + MTP_inputNotifyPeer(chat->input), + update.vnotify_settings); +} + +void ApplyChatUpdate( not_null chat, const MTPChatParticipants &participants) { participants.match([&](const MTPDchatParticipantsForbidden &data) { diff --git a/Telegram/SourceFiles/data/data_chat.h b/Telegram/SourceFiles/data/data_chat.h index 58919e6429..051091c7a6 100644 --- a/Telegram/SourceFiles/data/data_chat.h +++ b/Telegram/SourceFiles/data/data_chat.h @@ -207,9 +207,11 @@ void ApplyChatUpdate( void ApplyChatUpdate( not_null chat, const MTPDupdateChatDefaultBannedRights &update); - -void ApplyChatParticipants( +void ApplyChatUpdate( not_null chat, - const MTPChatParticipants &participants); + const MTPDchatFull &update); +void ApplyChatUpdate( + not_null chat, + const MTPChatParticipants &update); } // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index f0e685930a..4e5ee73dc3 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -416,6 +416,17 @@ bool PeerData::setAbout(const QString &newAbout) { return true; } +void PeerData::checkFolder(FolderId folderId) { + const auto folder = folderId + ? owner().folderLoaded(folderId) + : nullptr; + if (const auto history = owner().historyLoaded(this)) { + if (folder && history->folder() != folder) { + session().api().requestDialogEntry(history); + } + } +} + void PeerData::fillNames() { _nameWords.clear(); _nameFirstLetters.clear(); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index c0d01f06a4..e12f5323ee 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -282,6 +282,8 @@ public: return _about; } + void checkFolder(FolderId folderId); + enum LoadedStatus { NotLoaded = 0x00, MinimalLoaded = 0x01, diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index cba4c37ef7..60801e909e 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localstorage.h" #include "data/data_session.h" #include "ui/text_options.h" +#include "apiwrap.h" #include "lang/lang_keys.h" namespace { @@ -252,3 +253,47 @@ bool UserData::hasCalls() const { return (callsStatus() != CallsStatus::Disabled) && (callsStatus() != CallsStatus::Unknown); } + +namespace Data { + +void ApplyUserUpdate(not_null user, const MTPDuserFull &update) { + user->owner().processUser(update.vuser); + if (update.has_profile_photo()) { + user->owner().processPhoto(update.vprofile_photo); + } + update.vlink.match([&](const MTPDcontacts_link & link) { + App::feedUserLink( + MTP_int(peerToUser(user->id)), + link.vmy_link, + link.vforeign_link); + }); + user->session().api().applyNotifySettings( + MTP_inputNotifyPeer(user->input), + update.vnotify_settings); + + if (update.has_bot_info()) { + user->setBotInfo(update.vbot_info); + } else { + user->setBotInfoVersion(-1); + } + if (update.has_pinned_msg_id()) { + user->setPinnedMessageId(update.vpinned_msg_id.v); + } else { + user->clearPinnedMessage(); + } + user->setFullFlags(update.vflags.v); + user->setBlockStatus(update.is_blocked() + ? UserData::BlockStatus::Blocked + : UserData::BlockStatus::NotBlocked); + user->setCallsStatus(update.is_phone_calls_private() + ? UserData::CallsStatus::Private + : update.is_phone_calls_available() + ? UserData::CallsStatus::Enabled + : UserData::CallsStatus::Disabled); + user->setAbout(update.has_about() ? qs(update.vabout) : QString()); + user->setCommonChatsCount(update.vcommon_chats_count.v); + user->checkFolder(update.has_folder_id() ? update.vfolder_id.v : 0); + user->fullUpdated(); +} + +} // namespace Data diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index a2bc54b2d4..7a0fe63cc8 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -227,3 +227,9 @@ private: = 0xFFFFFFFFFFFFFFFFULL; }; + +namespace Data { + +void ApplyUserUpdate(not_null user, const MTPDuserFull &update); + +} // namespace Data diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index c78151ff5f..742aa40ac4 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -173,7 +173,7 @@ void History::itemVanished(not_null item) { if ((!item->out() || item->isPost()) && item->unread() && unreadCount() > 0) { - changeUnreadCount(-1); + setUnreadCount(unreadCount() - 1); } if (peer->pinnedMessageId() == item->id) { peer->clearPinnedMessage(); @@ -1494,8 +1494,8 @@ void History::addToSharedMedia( } } -int History::countUnread(MsgId upTo) { - int result = 0; +std::optional History::countUnread(MsgId upTo) const { + auto result = 0; for (auto i = blocks.cend(), e = blocks.cbegin(); i != e;) { --i; const auto &messages = (*i)->messages; @@ -1503,13 +1503,13 @@ int History::countUnread(MsgId upTo) { --j; const auto item = (*j)->data(); if (item->id > 0 && item->id <= upTo) { - break; - } else if (!item->out() && item->unread() && item->id > upTo) { + return result; + } else if (!item->out() && item->unread()) { ++result; } } } - return result; + return std::nullopt; } void History::calculateFirstUnreadMessage() { @@ -1539,19 +1539,41 @@ void History::calculateFirstUnreadMessage() { MsgId History::readInbox() { const auto upTo = msgIdForRead(); - changeUnreadCount(-unreadCount()); + setUnreadCount(0); if (upTo) { inboxRead(upTo); } return upTo; } -void History::inboxRead(MsgId upTo) { - if (const auto nowUnreadCount = unreadCount()) { - if (loadedAtBottom()) { - App::main()->historyToDown(this); - } - changeUnreadCount(countUnread(upTo) - nowUnreadCount); +void History::applyInboxReadUpdate( + FolderId folderId, + MsgId upTo, + int stillUnread, + int32 channelPts) { + const auto folder = folderId ? owner().folderLoaded(folderId) : nullptr; + if (folder && this->folder() != folder) { + // If history folder is unknown or not synced, request both. + session().api().requestDialogEntry(this); + session().api().requestDialogEntry(folder); + } + if (!peer->isChannel() || peer->asChannel()->pts() == channelPts) { + inboxRead(upTo, stillUnread); + } else { + inboxRead(upTo); + } +} + +void History::inboxRead(MsgId upTo, std::optional stillUnread) { + if (unreadCount() > 0 && loadedAtBottom()) { + App::main()->historyToDown(this); + } + if (stillUnread) { + setUnreadCount(*stillUnread); + } else if (const auto still = countUnread(upTo)) { + setUnreadCount(*still); + } else { + session().api().requestDialogEntry(this); } setInboxReadTill(upTo); updateChatListEntry(); @@ -1679,18 +1701,6 @@ bool History::unreadMark() const { return _unreadMark; } -void History::changeUnreadCount(int delta) { - if (_unreadCount) { - setUnreadCount(std::max(*_unreadCount + delta, 0)); - } - //if (const auto channel = peer->asChannel()) { // #feed - // if (const auto feed = channel->feed()) { - // const auto mutedCountDelta = mute() ? delta : 0; - // feed->unreadCountChanged(delta, mutedCountDelta); - // } - //} -} - bool History::mute() const { return _mute; } @@ -2449,7 +2459,7 @@ bool History::toImportant() const { void History::unknownMessageDeleted(MsgId messageId) { if (_inboxReadBefore && messageId >= *_inboxReadBefore) { - changeUnreadCount(-1); + session().api().requestDialogEntry(this); } } @@ -2993,7 +3003,7 @@ void History::clear(ClearType type) { } else { _notifications.clear(); owner().notifyHistoryCleared(this); - changeUnreadCount(-unreadCount()); + setUnreadCount(0); if (type == ClearType::DeleteChat) { setLastMessage(nullptr); } else if (_lastMessage && *_lastMessage) { diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 440414b601..2c7bd6802e 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -154,9 +154,13 @@ public: void newItemAdded(not_null item); - int countUnread(MsgId upTo); MsgId readInbox(); - void inboxRead(MsgId upTo); + void applyInboxReadUpdate( + FolderId folderId, + MsgId upTo, + int stillUnread, + int32 channelPts = 0); + void inboxRead(MsgId upTo, std::optional stillUnread = {}); void inboxRead(not_null wasRead); void outboxRead(MsgId upTo); void outboxRead(not_null wasRead); @@ -166,7 +170,6 @@ public: int unreadCount() const; bool unreadCountKnown() const; void setUnreadCount(int newUnreadCount); - void changeUnreadCount(int delta); void setUnreadMark(bool unread); bool unreadMark() const; int unreadCountForBadge() const; // unreadCount || unreadMark ? 1 : 0. @@ -456,6 +459,7 @@ private: HistoryItem *lastAvailableMessage() const; void getNextFirstUnreadMessage(); bool nonEmptyCountMoreThan(int count) const; + std::optional countUnread(MsgId upTo) const; // Creates if necessary a new block for adding item. // Depending on isBuildingFrontBlock() gets front or back block. diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 16c73b16d3..35deae8cb1 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -643,7 +643,9 @@ bool HistoryItem::needCheck() const { bool HistoryItem::unread() const { // Messages from myself are always read. - if (history()->peer->isSelf()) return false; + if (history()->peer->isSelf()) { + return false; + } if (out()) { // Outgoing messages in converted chats are always read. @@ -659,7 +661,7 @@ bool HistoryItem::unread() const { if (user->botInfo) { return false; } - } else if (auto channel = history()->peer->asChannel()) { + } else if (const auto channel = history()->peer->asChannel()) { if (!channel->isMegagroup()) { return false; } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 505b3b81d4..3601e84249 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -2196,7 +2196,7 @@ void HistoryWidget::newUnreadMsg( } Auth().notifications().schedule(history, item); if (history->unreadCountKnown()) { - history->changeUnreadCount(1); + history->setUnreadCount(history->unreadCount() + 1); } else { Auth().api().requestDialogEntry(history); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index b5ec3c2e4a..e55260b89c 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -3951,17 +3951,31 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { } break; case mtpc_updateReadChannelInbox: { - auto &d = update.c_updateReadChannelInbox(); - App::feedInboxRead(peerFromChannel(d.vchannel_id.v), d.vmax_id.v); + const auto &d = update.c_updateReadChannelInbox(); + const auto peer = peerFromChannel(d.vchannel_id.v); + if (const auto history = session().data().historyLoaded(peer)) { + const auto folderId = d.has_folder_id() ? d.vfolder_id.v : 0; + history->applyInboxReadUpdate( + folderId, + d.vmax_id.v, + d.vstill_unread_count.v, + d.vpts.v); + } } break; case mtpc_updateReadChannelOutbox: { - auto &d = update.c_updateReadChannelOutbox(); - auto peerId = peerFromChannel(d.vchannel_id.v); - auto when = requestingDifference() ? 0 : unixtime(); - App::feedOutboxRead(peerId, d.vmax_id.v, when); - if (_history->peer() && _history->peer()->id == peerId) { - _history->update(); + const auto &d = update.c_updateReadChannelOutbox(); + const auto peer = peerFromChannel(d.vchannel_id.v); + if (const auto history = session().data().historyLoaded(peer)) { + history->outboxRead(d.vmax_id.v); + if (!requestingDifference()) { + if (const auto user = history->peer->asUser()) { + user->madeAction(unixtime()); + } + } + if (_history->peer() && _history->peer()->id == peer) { + _history->update(); + } } } break;