Use folder_id / still_unread_count from updates.

This commit is contained in:
John Preston 2019-04-23 13:40:14 +04:00
parent 01d5589594
commit 2d1dcb36cb
17 changed files with 343 additions and 224 deletions

View File

@ -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<MsgId>();
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: {

View File

@ -63,6 +63,9 @@ public:
ApiWrap(not_null<AuthSession*> 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();

View File

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

View File

@ -72,8 +72,6 @@ namespace App {
void checkSavedGif(HistoryItem *item);
void feedMsgs(const QVector<MTPMessage> &msgs, NewMessageType type);
void feedMsgs(const MTPVector<MTPMessage> &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<MTPint> &msgsIds);
void feedUserLink(MTPint userId, const MTPContactLink &myLink, const MTPContactLink &foreignLink);

View File

@ -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<ChannelData*> 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

View File

@ -394,4 +394,8 @@ void ApplyChannelUpdate(
not_null<ChannelData*> channel,
const MTPDupdateChatDefaultBannedRights &update);
void ApplyChannelUpdate(
not_null<ChannelData*> channel,
const MTPDchannelFull &update);
} // namespace Data

View File

@ -186,7 +186,7 @@ namespace Data {
void ApplyChatUpdate(
not_null<ChatData*> 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<ChatData*> 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<ChatData*> chat,
const MTPChatParticipants &participants) {
participants.match([&](const MTPDchatParticipantsForbidden &data) {

View File

@ -207,9 +207,11 @@ void ApplyChatUpdate(
void ApplyChatUpdate(
not_null<ChatData*> chat,
const MTPDupdateChatDefaultBannedRights &update);
void ApplyChatParticipants(
void ApplyChatUpdate(
not_null<ChatData*> chat,
const MTPChatParticipants &participants);
const MTPDchatFull &update);
void ApplyChatUpdate(
not_null<ChatData*> chat,
const MTPChatParticipants &update);
} // namespace Data

View File

@ -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();

View File

@ -282,6 +282,8 @@ public:
return _about;
}
void checkFolder(FolderId folderId);
enum LoadedStatus {
NotLoaded = 0x00,
MinimalLoaded = 0x01,

View File

@ -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<UserData*> 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

View File

@ -227,3 +227,9 @@ private:
= 0xFFFFFFFFFFFFFFFFULL;
};
namespace Data {
void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update);
} // namespace Data

View File

@ -173,7 +173,7 @@ void History::itemVanished(not_null<HistoryItem*> 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<int> 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<int> 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) {

View File

@ -154,9 +154,13 @@ public:
void newItemAdded(not_null<HistoryItem*> 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<int> stillUnread = {});
void inboxRead(not_null<const HistoryItem*> wasRead);
void outboxRead(MsgId upTo);
void outboxRead(not_null<const HistoryItem*> 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<int> countUnread(MsgId upTo) const;
// Creates if necessary a new block for adding item.
// Depending on isBuildingFrontBlock() gets front or back block.

View File

@ -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;
}

View File

@ -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);
}

View File

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