Fix updating unread message reactions.

This commit is contained in:
John Preston 2022-01-28 10:44:12 +03:00
parent 8da9638563
commit 15719b73b4
3 changed files with 80 additions and 11 deletions

View file

@ -517,6 +517,60 @@ void MessageReactions::remove() {
add(QString());
}
bool MessageReactions::checkIfChanged(
const QVector<MTPReactionCount> &list,
const QVector<MTPMessagePeerReaction> &recent) const {
auto &owner = _item->history()->owner();
if (owner.reactions().sending(_item)) {
// We'll apply non-stale data from the request response.
return false;
}
auto existing = base::flat_set<QString>();
for (const auto &count : list) {
const auto changed = count.match([&](const MTPDreactionCount &data) {
const auto reaction = qs(data.vreaction());
const auto nowCount = data.vcount().v;
const auto i = _list.find(reaction);
const auto wasCount = (i != end(_list)) ? i->second : 0;
if (wasCount != nowCount) {
return true;
}
existing.emplace(reaction);
return false;
});
if (changed) {
return true;
}
}
for (const auto &[reaction, count] : _list) {
if (!existing.contains(reaction)) {
return true;
}
}
auto parsed = base::flat_map<QString, std::vector<RecentReaction>>();
for (const auto &reaction : recent) {
reaction.match([&](const MTPDmessagePeerReaction &data) {
const auto emoji = qs(data.vreaction());
if (_list.contains(emoji)) {
parsed[emoji].push_back(RecentReaction{
.peer = owner.peer(peerFromMTP(data.vpeer_id())),
.unread = data.is_unread(),
.big = data.is_big(),
});
}
});
}
return !ranges::equal(_recent, parsed, [](
const auto &a,
const auto &b) {
return ranges::equal(a.second, b.second, [](
const RecentReaction &a,
const RecentReaction &b) {
return (a.peer == b.peer) && (a.big == b.big);
});
});
}
void MessageReactions::set(
const QVector<MTPReactionCount> &list,
const QVector<MTPMessagePeerReaction> &recent,
@ -531,10 +585,13 @@ void MessageReactions::set(
for (const auto &count : list) {
count.match([&](const MTPDreactionCount &data) {
const auto reaction = qs(data.vreaction());
if (data.is_chosen() && !ignoreChosen) {
if (_chosen != reaction) {
if (!ignoreChosen) {
if (data.is_chosen() && _chosen != reaction) {
_chosen = reaction;
changed = true;
} else if (!data.is_chosen() && _chosen == reaction) {
_chosen = QString();
changed = true;
}
}
const auto nowCount = data.vcount().v;

View file

@ -149,6 +149,9 @@ public:
const QVector<MTPReactionCount> &list,
const QVector<MTPMessagePeerReaction> &recent,
bool ignoreChosen);
[[nodiscard]] bool checkIfChanged(
const QVector<MTPReactionCount> &list,
const QVector<MTPMessagePeerReaction> &recent) const;
[[nodiscard]] const base::flat_map<QString, int> &list() const;
[[nodiscard]] auto recent() const
-> const base::flat_map<QString, std::vector<RecentReaction>> &;

View file

@ -850,12 +850,8 @@ void HistoryItem::updateReactions(const MTPMessageReactions *reactions) {
const auto toContact = toUser && toUser->isContact();
const auto hadUnread = hasUnreadReaction();
setReactions(reactions);
const auto unreadReaction = _reactions
? _reactions->findUnread()
: QString();
const auto hasUnread = !unreadReaction.isEmpty();
const auto hasUnread = hasUnreadReaction();
if (hasUnread && !hadUnread) {
_flags |= MessageFlag::HasUnreadReaction;
addToUnreadThings(HistoryUnreadThings::AddType::New);
if (toContact) {
const auto notification = ItemNotification{
@ -894,16 +890,29 @@ void HistoryItem::setReactions(const MTPMessageReactions *reactions) {
if (data.vresults().v.isEmpty()) {
if (_reactions) {
_reactions = nullptr;
if (hasUnreadReaction()) {
markReactionsRead();
}
history()->owner().notifyItemDataChange(this);
}
return;
} else if (!_reactions) {
_reactions = std::make_unique<Data::MessageReactions>(this);
}
_reactions->set(
data.vresults().v,
data.vrecent_reactions().value_or_empty(),
data.is_min());
const auto min = data.is_min();
const auto &list = data.vresults().v;
const auto &recent = data.vrecent_reactions().value_or_empty();
if (min && hasUnreadReaction()) {
// We can't update reactions from min if we have unread.
if (_reactions->checkIfChanged(list, recent)) {
updateReactionsUnknown();
}
} else {
_reactions->set(list, recent, min);
if (!_reactions->findUnread().isEmpty()) {
_flags |= MessageFlag::HasUnreadReaction;
}
}
});
}