Add available_reactions_generation and increase it each time reactions are shown or hidden in the chat.

This commit is contained in:
levlam 2022-02-15 17:11:29 +03:00
parent ec4069b96a
commit b4d5d00f1e
2 changed files with 80 additions and 27 deletions

View File

@ -4866,6 +4866,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
bool are_message_media_timestamp_entities_found = true;
bool has_flags3 = true;
bool has_reactions = reactions != nullptr;
bool has_available_reactions_generation = has_reactions && available_reactions_generation != 0;
BEGIN_STORE_FLAGS();
STORE_FLAG(is_channel_post);
STORE_FLAG(is_outgoing);
@ -4937,6 +4938,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
STORE_FLAG(noforwards);
STORE_FLAG(has_explicit_sender);
STORE_FLAG(has_reactions);
STORE_FLAG(has_available_reactions_generation);
END_STORE_FLAGS();
}
@ -5058,6 +5060,9 @@ void MessagesManager::Message::store(StorerT &storer) const {
if (has_reactions) {
store(reactions, storer);
}
if (has_available_reactions_generation) {
store(available_reactions_generation, storer);
}
}
// do not forget to resolve message dependencies
@ -5102,6 +5107,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
bool has_max_reply_media_timestamp = false;
bool has_flags3 = false;
bool has_reactions = false;
bool has_available_reactions_generation = false;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_channel_post);
PARSE_FLAG(is_outgoing);
@ -5173,6 +5179,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
PARSE_FLAG(noforwards);
PARSE_FLAG(has_explicit_sender);
PARSE_FLAG(has_reactions);
PARSE_FLAG(has_available_reactions_generation);
END_PARSE_FLAGS();
}
@ -5301,6 +5308,9 @@ void MessagesManager::Message::parse(ParserT &parser) {
if (has_reactions) {
parse(reactions, parser);
}
if (has_available_reactions_generation) {
parse(available_reactions_generation, parser);
}
CHECK(content != nullptr);
is_content_secret |=
@ -5376,6 +5386,7 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
bool has_action_bar = action_bar != nullptr;
bool has_default_send_message_as_dialog_id = default_send_message_as_dialog_id.is_valid();
bool has_available_reactions = !available_reactions.empty();
bool has_available_reactions_generation = available_reactions_generation != 0;
BEGIN_STORE_FLAGS();
STORE_FLAG(has_draft_message);
STORE_FLAG(has_last_database_message);
@ -5454,6 +5465,7 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
STORE_FLAG(need_drop_default_send_message_as_dialog_id);
STORE_FLAG(has_available_reactions);
STORE_FLAG(is_available_reactions_inited);
STORE_FLAG(available_reactions_generation);
END_STORE_FLAGS();
}
@ -5560,6 +5572,9 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
if (has_available_reactions) {
store(available_reactions, storer);
}
if (has_available_reactions_generation) {
store(available_reactions_generation, storer);
}
}
// do not forget to resolve dialog dependencies including dependencies of last_message
@ -5606,6 +5621,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
bool has_action_bar = false;
bool has_default_send_message_as_dialog_id = false;
bool has_available_reactions = false;
bool has_available_reactions_generation = false;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_draft_message);
PARSE_FLAG(has_last_database_message);
@ -5699,6 +5715,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
PARSE_FLAG(need_drop_default_send_message_as_dialog_id);
PARSE_FLAG(has_available_reactions);
PARSE_FLAG(is_available_reactions_inited);
PARSE_FLAG(has_available_reactions_generation);
END_PARSE_FLAGS();
} else {
need_repair_action_bar = false;
@ -5850,6 +5867,9 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
if (has_available_reactions) {
parse(available_reactions, parser);
}
if (has_available_reactions_generation) {
parse(available_reactions_generation, parser);
}
(void)legacy_know_can_report_spam;
if (know_action_bar && !has_action_bar) {
@ -6995,6 +7015,9 @@ bool MessagesManager::is_visible_message_reactions(DialogId dialog_id, const Mes
if (get_message_active_reactions(d, m).empty()) {
return false;
}
if (m->reactions != nullptr && m->available_reactions_generation != d->available_reactions_generation) {
return false;
}
return true;
}
@ -7131,19 +7154,20 @@ bool MessagesManager::update_message_interaction_info(DialogId dialog_id, Messag
}
int32 new_dialog_unread_reaction_count = -1;
if (need_update_reactions || need_update_unread_reactions) {
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
CHECK(m->message_id.is_valid());
int32 unread_reaction_diff = 0;
unread_reaction_diff -= (has_unread_message_reactions(dialog_id, m) ? 1 : 0);
m->reactions = std::move(reactions);
m->available_reactions_generation = m->reactions == nullptr ? 0 : d->available_reactions_generation;
unread_reaction_diff += (has_unread_message_reactions(dialog_id, m) ? 1 : 0);
if (is_visible_message_reactions(dialog_id, m)) {
need_update |= need_update_reactions;
if (need_update_unread_reactions) {
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
if (unread_reaction_diff != 0) {
CHECK(m->message_id.is_valid());
// remove_message_notification_id(d, m, true, true);
if (d->unread_reaction_count + unread_reaction_diff < 0) {
@ -8398,36 +8422,38 @@ void MessagesManager::set_dialog_available_reactions(Dialog *d, vector<string> &
d->available_reactions = std::move(available_reactions);
d->is_available_reactions_inited = true;
on_dialog_updated(d->dialog_id, "set_dialog_available_reactions");
if (need_update_message_reactions_visibility) {
update_dialog_message_reactions_visibility(d);
if (!old_active_reactions.empty()) {
hide_dialog_message_reactions(d);
}
d->available_reactions_generation++;
}
on_dialog_updated(d->dialog_id, "set_dialog_available_reactions");
if (need_update) {
send_update_chat_available_reactions(d);
}
}
void MessagesManager::update_dialog_message_reactions_visibility(Dialog *d) {
void MessagesManager::hide_dialog_message_reactions(Dialog *d) {
vector<MessageId> message_ids;
find_messages(d->messages.get(), message_ids,
[](const Message *m) { return m->reactions != nullptr && !m->reactions->reactions_.empty(); });
int32 unread_reaction_count = 0;
for (auto message_id : message_ids) {
const auto *m = get_message(d, message_id);
Message *m = get_message(d, message_id);
CHECK(m != nullptr);
CHECK(m->reactions != nullptr);
send_update_message_interaction_info(d->dialog_id, m);
if (!m->reactions->unread_reactions_.empty()) {
if (has_unread_message_reactions(d->dialog_id, m)) {
unread_reaction_count++;
}
send_update_message_unread_reactions(d->dialog_id, m, unread_reaction_count);
bool need_update_unread_reactions = !m->reactions->unread_reactions_.empty();
m->reactions = nullptr;
// don't resave all messages to the database
if (need_update_unread_reactions) {
send_update_message_unread_reactions(d->dialog_id, m, d->unread_reaction_count);
}
send_update_message_interaction_info(d->dialog_id, m);
}
if (d->unread_reaction_count != unread_reaction_count) {
set_dialog_unread_reaction_count(d, unread_reaction_count);
if (d->unread_reaction_count != 0) {
set_dialog_unread_reaction_count(d, 0);
}
}
@ -8454,7 +8480,11 @@ void MessagesManager::set_active_reactions(vector<string> active_reactions) {
auto new_reactions = get_active_reactions(d->available_reactions, active_reactions_);
if (old_reactions != new_reactions) {
if (old_reactions.empty() != new_reactions.empty()) {
update_dialog_message_reactions_visibility(d);
if (!old_reactions.empty()) {
hide_dialog_message_reactions(d);
}
d->available_reactions_generation++;
on_dialog_updated(d->dialog_id, "set_active_reactions");
}
send_update_chat_available_reactions(d);
}
@ -14458,6 +14488,13 @@ FullMessageId MessagesManager::on_get_message(MessageInfo &&message_info, bool f
new_message->have_previous = have_previous;
new_message->have_next = have_next;
if (new_message->reactions != nullptr) {
const Dialog *d = get_dialog_force(dialog_id, "on_get_message");
if (d != nullptr) {
new_message->available_reactions_generation = d->available_reactions_generation;
}
}
bool need_update = from_update;
bool need_update_dialog_pos = false;
@ -23499,7 +23536,8 @@ void MessagesManager::preload_older_messages(const Dialog *d, MessageId min_mess
}
}
unique_ptr<MessagesManager::Message> MessagesManager::parse_message(DialogId dialog_id, MessageId expected_message_id,
unique_ptr<MessagesManager::Message> MessagesManager::parse_message(Dialog *d, DialogId dialog_id,
MessageId expected_message_id,
const BufferSlice &value, bool is_scheduled) {
auto m = make_unique<Message>();
@ -23537,6 +23575,18 @@ unique_ptr<MessagesManager::Message> MessagesManager::parse_message(DialogId dia
}
return nullptr;
}
if (m->reactions != nullptr && d != nullptr) {
if (m->available_reactions_generation < d->available_reactions_generation) {
m->reactions = nullptr;
m->available_reactions_generation = 0;
} else if (m->available_reactions_generation > d->available_reactions_generation) {
LOG(ERROR) << "Fix available_reactions_generation in " << dialog_id << " from "
<< d->available_reactions_generation << " to " << m->available_reactions_generation;
hide_dialog_message_reactions(d);
d->available_reactions_generation = m->available_reactions_generation;
on_dialog_updated(dialog_id, "parse_message");
}
}
LOG(INFO) << "Loaded " << m->message_id << " in " << dialog_id << " of size " << value.size() << " from database";
return m;
@ -23606,7 +23656,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
if (!d->first_database_message_id.is_valid() && !d->have_full_history) {
break;
}
auto message = parse_message(dialog_id, message_slice.message_id, message_slice.data, false);
auto message = parse_message(d, dialog_id, message_slice.message_id, message_slice.data, false);
if (message == nullptr) {
if (d->have_full_history) {
d->have_full_history = false;
@ -24044,7 +24094,7 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
Dependencies dependencies;
vector<MessageId> added_message_ids;
for (auto &message_slice : messages) {
auto message = parse_message(dialog_id, message_slice.message_id, message_slice.data, true);
auto message = parse_message(d, dialog_id, message_slice.message_id, message_slice.data, true);
if (message == nullptr) {
continue;
}
@ -24150,6 +24200,7 @@ void MessagesManager::set_message_reaction(FullMessageId full_message_id, string
m->reactions = make_unique<MessageReactions>();
m->reactions->can_get_added_reactions_ = can_get_added_reactions;
m->available_reactions_generation = d->available_reactions_generation;
}
bool is_found = false;
@ -33671,7 +33722,7 @@ MessagesManager::Message *MessagesManager::on_get_message_from_database(Dialog *
return nullptr;
}
auto m = parse_message(dialog_id, expected_message_id, value, is_scheduled);
auto m = parse_message(d, dialog_id, expected_message_id, value, is_scheduled);
if (m == nullptr) {
return nullptr;
}

View File

@ -1143,6 +1143,7 @@ class MessagesManager final : public Actor {
MessageReplyInfo reply_info;
unique_ptr<MessageReactions> reactions;
unique_ptr<DraftMessage> thread_draft_message;
uint32 available_reactions_generation = 0;
int32 interaction_info_update_date = 0;
int32 legacy_layer = 0;
@ -1231,6 +1232,7 @@ class MessagesManager final : public Actor {
MessageId reply_markup_message_id;
DialogNotificationSettings notification_settings;
vector<string> available_reactions;
uint32 available_reactions_generation = 0;
MessageTtl message_ttl;
unique_ptr<DraftMessage> draft_message;
unique_ptr<DialogActionBar> action_bar;
@ -2623,7 +2625,7 @@ class MessagesManager final : public Actor {
void set_dialog_available_reactions(Dialog *d, vector<string> &&available_reactions);
void update_dialog_message_reactions_visibility(Dialog *d);
void hide_dialog_message_reactions(Dialog *d);
vector<string> get_active_reactions(const vector<string> &available_reactions) const;
@ -3169,8 +3171,8 @@ class MessagesManager final : public Actor {
string get_message_search_text(const Message *m) const;
unique_ptr<Message> parse_message(DialogId dialog_id, MessageId expected_message_id, const BufferSlice &value,
bool is_scheduled);
unique_ptr<Message> parse_message(Dialog *d, DialogId dialog_id, MessageId expected_message_id,
const BufferSlice &value, bool is_scheduled);
unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value, const char *source);