diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 2cafe5c4e..878a0c600 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -3766,6 +3766,7 @@ void MessagesManager::NotificationGroupInfo::store(StorerT &storer) const { store(last_notification_date, storer); store(last_notification_id, storer); store(max_removed_notification_id, storer); + store(max_removed_message_id, storer); } template @@ -3775,6 +3776,9 @@ void MessagesManager::NotificationGroupInfo::parse(ParserT &parser) { parse(last_notification_date, parser); parse(last_notification_id, parser); parse(max_removed_notification_id, parser); + if (parser.version() >= static_cast(Version::AddNotificationGroupInfoMaxRemovedMessageId)) { + parse(max_removed_message_id, parser); + } } template @@ -4387,6 +4391,7 @@ void MessagesManager::try_reuse_notification_group(NotificationGroupInfo &group_ notification_group_id_to_dialog_id_.erase(group_info.group_id); group_info.group_id = NotificationGroupId(); group_info.max_removed_notification_id = NotificationId(); + group_info.max_removed_message_id = MessageId(); } void MessagesManager::update_message_count_by_index(Dialog *d, int diff, const Message *m) { @@ -7998,7 +8003,9 @@ void MessagesManager::delete_all_dialog_messages(Dialog *d, bool remove_from_dia set_dialog_last_clear_history_date(d, last_message_date, last_clear_history_message_id, "delete_all_dialog_messages"); d->last_read_all_mentions_message_id = MessageId(); // it is not needed anymore d->message_notification_group.max_removed_notification_id = NotificationId(); // it is not needed anymore + d->message_notification_group.max_removed_message_id = MessageId(); // it is not needed anymore d->mention_notification_group.max_removed_notification_id = NotificationId(); // it is not needed anymore + d->mention_notification_group.max_removed_message_id = MessageId(); // it is not needed anymore std::fill(d->message_count_by_index.begin(), d->message_count_by_index.end(), 0); CHECK(d->notification_id_to_message_id.empty()); @@ -18506,9 +18513,11 @@ bool MessagesManager::is_from_mention_notification_group(const Dialog *d, const bool MessagesManager::is_message_notification_active(const Dialog *d, const Message *m) { if (is_from_mention_notification_group(d, m)) { return m->notification_id.get() > d->mention_notification_group.max_removed_notification_id.get() && + m->message_id.get() > d->mention_notification_group.max_removed_message_id.get() && (m->contains_unread_mention || m->message_id == d->pinned_message_notification_message_id); } else { return m->notification_id.get() > d->message_notification_group.max_removed_notification_id.get() && + m->message_id.get() > d->message_notification_group.max_removed_message_id.get() && m->message_id.get() > d->last_read_inbox_message_id.get(); } } @@ -18522,7 +18531,8 @@ void MessagesManager::try_add_pinned_message_notification(Dialog *d, vectornotification_id.get() > d->mention_notification_group.max_removed_notification_id.get()) { + if (m != nullptr && m->notification_id.get() > d->mention_notification_group.max_removed_notification_id.get() && + m->message_id.get() > d->mention_notification_group.max_removed_message_id.get()) { if (m->notification_id.get() < max_notification_id.get()) { VLOG(notifications) << "Add " << m->notification_id << " about pinned " << message_id << " in " << d->dialog_id; auto pinned_message_id = get_message_content_pinned_message_id(m->content.get()); @@ -18584,9 +18594,11 @@ vector MessagesManager::get_message_notifications_from_database_fo } if (m->notification_id.get() <= group_info.max_removed_notification_id.get() || + m->message_id.get() <= group_info.max_removed_message_id.get() || (!from_mentions && m->message_id.get() <= d->last_read_inbox_message_id.get())) { - // if message still has notification_id, but it was removed via max_removed_notification_id - // or last_read_inbox_message_id, then there will be no more messages with active notifications + // if message still has notification_id, but it was removed via max_removed_notification_id, + // or max_removed_message_id, or last_read_inbox_message_id, + // then there will be no more messages with active notifications is_found = false; break; } @@ -18602,9 +18614,10 @@ vector MessagesManager::get_message_notifications_from_database_fo << from_mentions << " " << is_from_mention_notification_group(d, m) << " " << d->dialog_id << " " << m->message_id << " " << m->notification_id << " " << from_message_id << " " << from_notification_id << " " << group_info.group_id << " " << group_info.last_notification_date << " " << group_info.last_notification_id - << " " << group_info.max_removed_notification_id << " " << d->last_new_message_id << " " << d->last_message_id - << " " << d->first_database_message_id << " " << d->last_database_message_id << " " << d->max_added_message_id - << " " << d->pinned_message_notification_message_id << " " << d->is_last_message_deleted_locally << " " + << " " << group_info.max_removed_notification_id << " " << group_info.max_removed_message_id << " " + << d->last_new_message_id << " " << d->last_message_id << " " << d->first_database_message_id << " " + << d->last_database_message_id << " " << d->max_added_message_id << " " + << d->pinned_message_notification_message_id << " " << d->is_last_message_deleted_locally << " " << d->debug_last_new_message_id << " " << d->debug_first_database_message_id << " " << d->debug_last_database_message_id; from_notification_id = m->notification_id; @@ -18728,6 +18741,7 @@ void MessagesManager::do_get_message_notifications_from_database(Dialog *d, bool auto &group_info = from_mentions ? d->mention_notification_group : d->message_notification_group; if (from_notification_id.get() <= group_info.max_removed_notification_id.get() || + from_message_id.get() <= group_info.max_removed_message_id.get() || (!from_mentions && from_message_id.get() <= d->last_read_inbox_message_id.get())) { return promise.set_value(vector()); } @@ -18791,9 +18805,11 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog } if (m->notification_id.get() <= group_info.max_removed_notification_id.get() || + m->message_id.get() <= group_info.max_removed_message_id.get() || (!from_mentions && m->message_id.get() <= d->last_read_inbox_message_id.get())) { - // if message still has notification_id, but it was removed via max_removed_notification_id - // or last_read_inbox_message_id, then there will be no more messages with active notifications + // if message still has notification_id, but it was removed via max_removed_notification_id, + // or max_removed_message_id, or last_read_inbox_message_id, + // then there will be no more messages with active notifications from_notification_id = NotificationId(); // stop requesting database break; } @@ -18810,9 +18826,10 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog << from_mentions << " " << is_from_mention_notification_group(d, m) << " " << dialog_id << " " << m->message_id << " " << m->notification_id << " " << from_message_id << " " << from_notification_id << " " << group_info.group_id << " " << group_info.last_notification_date << " " << group_info.last_notification_id - << " " << group_info.max_removed_notification_id << " " << d->last_new_message_id << " " << d->last_message_id - << " " << d->first_database_message_id << " " << d->last_database_message_id << " " << d->max_added_message_id - << " " << d->pinned_message_notification_message_id << " " << d->is_last_message_deleted_locally << " " + << " " << group_info.max_removed_notification_id << " " << group_info.max_removed_message_id << " " + << d->last_new_message_id << " " << d->last_message_id << " " << d->first_database_message_id << " " + << d->last_database_message_id << " " << d->max_added_message_id << " " + << d->pinned_message_notification_message_id << " " << d->is_last_message_deleted_locally << " " << d->debug_last_new_message_id << " " << d->debug_first_database_message_id << " " << d->debug_last_database_message_id; @@ -18901,7 +18918,7 @@ void MessagesManager::do_remove_message_notification(DialogId dialog_id, bool fr } void MessagesManager::remove_message_notifications(DialogId dialog_id, NotificationGroupId group_id, - NotificationId max_notification_id) { + NotificationId max_notification_id, MessageId max_message_id) { Dialog *d = get_dialog_force(dialog_id); if (d == nullptr) { LOG(ERROR) << "Can't find " << dialog_id; @@ -18926,6 +18943,11 @@ void MessagesManager::remove_message_notifications(DialogId dialog_id, Notificat if (max_notification_id.get() <= group_info.max_removed_notification_id.get()) { return; } + if (max_message_id.get() > group_info.max_removed_message_id.get()) { + VLOG(notifications) << "Set max_removed_message_id in " << group_info.group_id << '/' << dialog_id << " to " + << max_message_id; + group_info.max_removed_message_id = max_message_id; + } VLOG(notifications) << "Set max_removed_notification_id in " << group_info.group_id << '/' << dialog_id << " to " << max_notification_id; @@ -19064,6 +19086,12 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f bool is_pinned = m->content->get_type() == MessageContentType::PinMessage; bool is_active = from_mentions ? m->contains_unread_mention || is_pinned : m->message_id.get() > d->last_read_inbox_message_id.get(); + if (is_active) { + auto &group = from_mentions ? d->mention_notification_group : d->message_notification_group; + if (group.max_removed_message_id.get() >= m->message_id.get()) { + is_active = false; + } + } if (!is_active) { VLOG(notifications) << "Disable inactive notification for " << m->message_id << " in " << d->dialog_id; if (is_pinned) { @@ -19232,6 +19260,10 @@ void MessagesManager::remove_all_dialog_notifications(Dialog *d, NotificationGro VLOG(notifications) << "Set max_removed_notification_id in " << group_info.group_id << '/' << d->dialog_id << " to " << group_info.last_notification_id << " from " << source; group_info.max_removed_notification_id = group_info.last_notification_id; + if (d->max_notification_message_id.get() > group_info.max_removed_message_id.get()) { + group_info.max_removed_message_id = d->max_notification_message_id; + } + // remove_message_notifications will be called by NotificationManager send_closure_later(G()->notification_manager(), &NotificationManager::remove_notification_group, group_info.group_id, group_info.last_notification_id, MessageId(), 0, true, Promise()); if (d->new_secret_chat_notification_id.is_valid() && &group_info == &d->message_notification_group) { @@ -23687,12 +23719,14 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab VLOG(notifications) << "Have " << dialog_id << " with message " << d->message_notification_group.group_id << " with last " << d->message_notification_group.last_notification_id << " sent at " << d->message_notification_group.last_notification_date << ", max removed " - << d->message_notification_group.max_removed_notification_id << " and new secret chat " + << d->message_notification_group.max_removed_notification_id << "/" + << d->message_notification_group.max_removed_message_id << " and new secret chat " << d->new_secret_chat_notification_id; VLOG(notifications) << "Have " << dialog_id << " with mention " << d->mention_notification_group.group_id << " with last " << d->mention_notification_group.last_notification_id << " sent at " << d->mention_notification_group.last_notification_date << ", max removed " - << d->mention_notification_group.max_removed_notification_id << " and pinned message " + << d->mention_notification_group.max_removed_notification_id << "/" + << d->mention_notification_group.max_removed_message_id << " and pinned message " << d->pinned_message_notification_message_id; VLOG(notifications) << "In " << dialog_id << " have last_read_inbox_message_id = " << d->last_read_inbox_message_id << ", last_new_message_id = " << d->last_new_message_id diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index dd6566619..b29d00a4c 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -722,7 +722,7 @@ class MessagesManager : public Actor { void remove_message_notification(DialogId dialog_id, NotificationGroupId group_id, NotificationId notification_id); void remove_message_notifications(DialogId dialog_id, NotificationGroupId group_id, - NotificationId max_notification_id); + NotificationId max_notification_id, MessageId max_message_id); void upload_dialog_photo(DialogId dialog_id, FileId file_id, Promise &&promise); @@ -905,6 +905,7 @@ class MessagesManager : public Actor { int32 last_notification_date = 0; // date of last notification in the group NotificationId last_notification_id; // identifier of last notification in the group NotificationId max_removed_notification_id; // notification identifier, up to which all notifications are removed + MessageId max_removed_message_id; // message identifier, up to which all notifications are removed bool is_changed = false; // true, if the group needs to be saved to database bool try_reuse = false; // true, if the group needs to be deleted from database and tried to be reused diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index 4076e30f3..6878cff48 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -502,6 +502,27 @@ MessageId NotificationManager::get_last_message_id(const NotificationGroup &grou return MessageId(); } +MessageId NotificationManager::get_last_message_id_by_notification_id(const NotificationGroup &group, + NotificationId max_notification_id) { + for (auto ¬ification : reversed(group.pending_notifications)) { + if (notification.notification_id.get() <= max_notification_id.get()) { + auto message_id = notification.type->get_message_id(); + if (message_id.is_valid()) { + return message_id; + } + } + } + for (auto ¬ification : reversed(group.notifications)) { + if (notification.notification_id.get() <= max_notification_id.get()) { + auto message_id = notification.type->get_message_id(); + if (message_id.is_valid()) { + return message_id; + } + } + } + return MessageId(); +} + void NotificationManager::load_message_notifications_from_database(const NotificationGroupKey &group_key, NotificationGroup &group, size_t desired_size) { if (!G()->parameters().use_message_db) { @@ -1865,7 +1886,9 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id max_notification_id = current_notification_id_; } if (group_it->second.type != NotificationGroupType::Calls) { - td_->messages_manager_->remove_message_notifications(group_it->first.dialog_id, group_id, max_notification_id); + td_->messages_manager_->remove_message_notifications( + group_it->first.dialog_id, group_id, max_notification_id, + get_last_message_id_by_notification_id(group_it->second, max_notification_id)); } } diff --git a/td/telegram/NotificationManager.h b/td/telegram/NotificationManager.h index e31caa061..f9ed21a4b 100644 --- a/td/telegram/NotificationManager.h +++ b/td/telegram/NotificationManager.h @@ -219,6 +219,9 @@ class NotificationManager : public Actor { static MessageId get_last_message_id(const NotificationGroup &group); + static MessageId get_last_message_id_by_notification_id(const NotificationGroup &group, + NotificationId max_notification_id); + static int32 get_temporary_notification_total_count(const NotificationGroup &group); void remove_temporary_notifications(NotificationGroupId group_id); diff --git a/td/telegram/Version.h b/td/telegram/Version.h index 41f8a19b9..14890c6bd 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -28,6 +28,7 @@ enum class Version : int32 { AddContactVcard, AddMessageUnsupportedVersion, SupportInstantView2_0, + AddNotificationGroupInfoMaxRemovedMessageId, Next };