Pinned message notification support.

GitOrigin-RevId: f0a435fd3bb55daff2dee438c939b39f8b89f331
This commit is contained in:
levlam 2018-12-25 05:45:36 +03:00
parent c60ce3a434
commit 1d55e08fe4
6 changed files with 155 additions and 57 deletions

View File

@ -3983,15 +3983,16 @@ unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<tele
} }
case telegram_api::messageActionPinMessage::ID: { case telegram_api::messageActionPinMessage::ID: {
if (!reply_to_message_id.is_valid()) { if (!reply_to_message_id.is_valid()) {
LOG(ERROR) << "Receive pinned message with " << reply_to_message_id << " in " << owner_dialog_id; // possible in basic groups
LOG(INFO) << "Receive pinned message with " << reply_to_message_id << " in " << owner_dialog_id;
reply_to_message_id = MessageId(); reply_to_message_id = MessageId();
} }
return make_unique<MessagePinMessage>(reply_to_message_id); return make_unique<MessagePinMessage>(reply_to_message_id);
} }
case telegram_api::messageActionGameScore::ID: { case telegram_api::messageActionGameScore::ID: {
if (!reply_to_message_id.is_valid()) { if (!reply_to_message_id.is_valid()) {
LOG_IF(ERROR, !td->auth_manager_->is_bot()) // possible in basic groups
<< "Receive game score with " << reply_to_message_id << " in " << owner_dialog_id; LOG(INFO) << "Receive game score with " << reply_to_message_id << " in " << owner_dialog_id;
reply_to_message_id = MessageId(); reply_to_message_id = MessageId();
} }
auto game_score = move_tl_object_as<telegram_api::messageActionGameScore>(action); auto game_score = move_tl_object_as<telegram_api::messageActionGameScore>(action);

View File

@ -756,6 +756,9 @@ class MessagesDbImpl : public MessagesDbSyncInterface {
CHECK(dialog_id.is_valid()) << dialog_id; CHECK(dialog_id.is_valid()) << dialog_id;
CHECK(from_message_id.is_valid()); CHECK(from_message_id.is_valid());
LOG(INFO) << "Loading messages in " << dialog_id << " from " << from_message_id << " with offset = " << offset
<< " and limit = " << limit;
auto message_id = from_message_id.get(); auto message_id = from_message_id.get();
if (message_id >= MessageId::max().get()) { if (message_id >= MessageId::max().get()) {
@ -811,13 +814,15 @@ class MessagesDbImpl : public MessagesDbSyncInterface {
stmt.bind_int64(2, from_message_id).ensure(); stmt.bind_int64(2, from_message_id).ensure();
stmt.bind_int32(3, limit).ensure(); stmt.bind_int32(3, limit).ensure();
LOG(INFO) << "Load " << limit << " messages in " << DialogId(dialog_id) << " from " << MessageId(from_message_id)
<< " from database";
std::vector<BufferSlice> result; std::vector<BufferSlice> result;
stmt.step().ensure(); stmt.step().ensure();
while (stmt.has_row()) { while (stmt.has_row()) {
auto data_slice = stmt.view_blob(0); auto data_slice = stmt.view_blob(0);
result.emplace_back(data_slice); result.emplace_back(data_slice);
auto message_id = stmt.view_int64(1); auto message_id = stmt.view_int64(1);
LOG(INFO) << "Load " << MessageId(message_id) << " in " << DialogId(dialog_id) << " from database"; LOG(INFO) << "Loaded " << MessageId(message_id) << " in " << DialogId(dialog_id) << " from database";
stmt.step().ensure(); stmt.step().ensure();
} }
return std::move(result); return std::move(result);
@ -836,7 +841,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface {
} }
int32 date; int32 date;
td::parse(date, message_date_parser); td::parse(date, message_date_parser);
LOG(INFO) << "Load " << message_id << " sent at " << date << " by " << sender_user_id; LOG(INFO) << "Loaded " << message_id << " sent at " << date << " by " << sender_user_id;
return std::make_tuple(message_id, date); return std::make_tuple(message_id, date);
} }
}; };

View File

@ -3820,6 +3820,7 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
bool has_message_notification_group = message_notification_group.group_id.is_valid(); bool has_message_notification_group = message_notification_group.group_id.is_valid();
bool has_mention_notification_group = mention_notification_group.group_id.is_valid(); bool has_mention_notification_group = mention_notification_group.group_id.is_valid();
bool has_new_secret_chat_notification_id = new_secret_chat_notification_id.is_valid(); bool has_new_secret_chat_notification_id = new_secret_chat_notification_id.is_valid();
bool has_pinned_message_notification = pinned_message_notification_message_id.is_valid();
BEGIN_STORE_FLAGS(); BEGIN_STORE_FLAGS();
STORE_FLAG(has_draft_message); STORE_FLAG(has_draft_message);
STORE_FLAG(has_last_database_message); STORE_FLAG(has_last_database_message);
@ -3846,8 +3847,8 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
STORE_FLAG(is_marked_as_unread); STORE_FLAG(is_marked_as_unread);
STORE_FLAG(has_message_notification_group); STORE_FLAG(has_message_notification_group);
STORE_FLAG(has_mention_notification_group); STORE_FLAG(has_mention_notification_group);
STORE_FLAG(has_new_secret_chat_notification_id); // 25 STORE_FLAG(has_new_secret_chat_notification_id);
// STORE_FLAG(has_pinned_message_notification); // 26
// //
// //
//STORE_FLAG(has_flags2); //STORE_FLAG(has_flags2);
@ -3918,6 +3919,9 @@ void MessagesManager::Dialog::store(StorerT &storer) const {
if (has_new_secret_chat_notification_id) { if (has_new_secret_chat_notification_id) {
store(new_secret_chat_notification_id, storer); store(new_secret_chat_notification_id, storer);
} }
if (has_pinned_message_notification) {
store(pinned_message_notification_message_id, storer);
}
} }
// do not forget to resolve dialog dependencies including dependencies of last_message // do not forget to resolve dialog dependencies including dependencies of last_message
@ -3940,6 +3944,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
bool has_message_notification_group; bool has_message_notification_group;
bool has_mention_notification_group; bool has_mention_notification_group;
bool has_new_secret_chat_notification_id; bool has_new_secret_chat_notification_id;
bool has_pinned_message_notification;
BEGIN_PARSE_FLAGS(); BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_draft_message); PARSE_FLAG(has_draft_message);
PARSE_FLAG(has_last_database_message); PARSE_FLAG(has_last_database_message);
@ -3967,6 +3972,7 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
PARSE_FLAG(has_message_notification_group); PARSE_FLAG(has_message_notification_group);
PARSE_FLAG(has_mention_notification_group); PARSE_FLAG(has_mention_notification_group);
PARSE_FLAG(has_new_secret_chat_notification_id); PARSE_FLAG(has_new_secret_chat_notification_id);
PARSE_FLAG(has_pinned_message_notification);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
parse(dialog_id, parser); // must be stored at offset 4 parse(dialog_id, parser); // must be stored at offset 4
@ -4058,6 +4064,9 @@ void MessagesManager::Dialog::parse(ParserT &parser) {
if (has_new_secret_chat_notification_id) { if (has_new_secret_chat_notification_id) {
parse(new_secret_chat_notification_id, parser); parse(new_secret_chat_notification_id, parser);
} }
if (has_pinned_message_notification) {
parse(pinned_message_notification_message_id, parser);
}
} }
template <class StorerT> template <class StorerT>
@ -5145,10 +5154,13 @@ bool MessagesManager::update_message_contains_unread_mention(Dialog *d, Message
const char *source) { const char *source) {
CHECK(m != nullptr) << source; CHECK(m != nullptr) << source;
if (!contains_unread_mention && m->contains_unread_mention) { if (!contains_unread_mention && m->contains_unread_mention) {
remove_message_notification_id(d, m, true); // should be called before contains_unread_mention is updated
m->contains_unread_mention = false; m->contains_unread_mention = false;
if (d->unread_mention_count == 0) { if (d->unread_mention_count == 0) {
LOG_IF(ERROR, d->message_count_by_index[search_messages_filter_index(SearchMessagesFilter::UnreadMention)] != -1) if (d->message_count_by_index[search_messages_filter_index(SearchMessagesFilter::UnreadMention)] != -1) {
<< "Unread mention count of " << d->dialog_id << " became negative from " << source; LOG(ERROR) << "Unread mention count of " << d->dialog_id << " became negative from " << source;
}
} else { } else {
d->unread_mention_count--; d->unread_mention_count--;
d->message_count_by_index[search_messages_filter_index(SearchMessagesFilter::UnreadMention)] = d->message_count_by_index[search_messages_filter_index(SearchMessagesFilter::UnreadMention)] =
@ -5158,8 +5170,6 @@ bool MessagesManager::update_message_contains_unread_mention(Dialog *d, Message
LOG(INFO) << "Update unread mention message count in " << d->dialog_id << " to " << d->unread_mention_count LOG(INFO) << "Update unread mention message count in " << d->dialog_id << " to " << d->unread_mention_count
<< " by reading " << m->message_id << " from " << source; << " by reading " << m->message_id << " from " << source;
remove_message_notification_id(d, m, true);
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateMessageMentionRead>(d->dialog_id.get(), m->message_id.get(), make_tl_object<td_api::updateMessageMentionRead>(d->dialog_id.get(), m->message_id.get(),
d->unread_mention_count)); d->unread_mention_count));
@ -7888,9 +7898,9 @@ void MessagesManager::read_all_dialog_mentions(DialogId dialog_id, Promise<Unit>
CHECK(m != nullptr); CHECK(m != nullptr);
CHECK(m->contains_unread_mention); CHECK(m->contains_unread_mention);
CHECK(m->message_id == message_id); CHECK(m->message_id == message_id);
remove_message_notification_id(d, m, true); // should be called before contains_unread_mention is updated
m->contains_unread_mention = false; m->contains_unread_mention = false;
remove_message_notification_id(d, m, true);
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateMessageMentionRead>(dialog_id.get(), m->message_id.get(), 0)); make_tl_object<td_api::updateMessageMentionRead>(dialog_id.get(), m->message_id.get(), 0));
is_update_sent = true; is_update_sent = true;
@ -8320,9 +8330,9 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
} }
send_update_unread_chat_count(d->dialog_id, force_update, source); send_update_unread_chat_count(d->dialog_id, force_update, source);
} }
if (message_id != MessageId::min()) { if (message_id != MessageId::min() && d->last_read_inbox_message_id.is_valid() && d->order != DEFAULT_ORDER &&
if (d->last_read_inbox_message_id.is_valid() && d->message_notification_group.group_id.is_valid() && d->order != SPONSORED_DIALOG_ORDER) {
d->order != DEFAULT_ORDER && d->order != SPONSORED_DIALOG_ORDER) { if (d->message_notification_group.group_id.is_valid()) {
auto total_count = get_dialog_pending_notification_count(d, false); auto total_count = get_dialog_pending_notification_count(d, false);
if (total_count == 0) { if (total_count == 0) {
set_dialog_last_notification(d->dialog_id, d->message_notification_group, 0, NotificationId(), set_dialog_last_notification(d->dialog_id, d->message_notification_group, 0, NotificationId(),
@ -8337,6 +8347,12 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
d->message_notification_group.group_id, NotificationId(), d->last_read_inbox_message_id, d->message_notification_group.group_id, NotificationId(), d->last_read_inbox_message_id,
total_count, Promise<Unit>()); total_count, Promise<Unit>());
} }
if (d->mention_notification_group.group_id.is_valid() && d->pinned_message_notification_message_id.is_valid() &&
d->pinned_message_notification_message_id.get() <= d->last_read_inbox_message_id.get()) {
// remove pinned message notification when it is read
set_dialog_pinned_message_notification(d, MessageId());
}
} }
send_update_chat_read_inbox(d, force_update, source); send_update_chat_read_inbox(d, force_update, source);
@ -9937,6 +9953,22 @@ void MessagesManager::try_restore_dialog_reply_markup(Dialog *d, const Message *
} }
} }
void MessagesManager::set_dialog_pinned_message_notification(Dialog *d, MessageId message_id) {
auto old_message_id = d->pinned_message_notification_message_id;
CHECK(old_message_id != message_id);
VLOG(notifications) << "Change pinned message notification in " << d->dialog_id << " from " << old_message_id
<< " to " << message_id;
if (old_message_id.is_valid()) {
auto m = get_message_force(d, old_message_id);
if (m != nullptr && m->notification_id.is_valid() && is_message_notification_active(d, m)) {
remove_message_notification_id(d, m, true);
on_message_changed(d, m, false, "remove_message_notification_id");
}
}
d->pinned_message_notification_message_id = message_id;
on_dialog_updated(d->dialog_id, "set_dialog_pinned_message_notification");
}
bool MessagesManager::set_dialog_last_notification(DialogId dialog_id, NotificationGroupInfo &group_info, bool MessagesManager::set_dialog_last_notification(DialogId dialog_id, NotificationGroupInfo &group_info,
int32 last_notification_date, NotificationId last_notification_id, int32 last_notification_date, NotificationId last_notification_id,
const char *source) { const char *source) {
@ -10460,7 +10492,8 @@ void MessagesManager::remove_message_notification_id(Dialog *d, Message *m, bool
auto notification_id = m->notification_id; auto notification_id = m->notification_id;
VLOG(notifications) << "Remove " << notification_id << " from " << m->message_id << " in " << group_info.group_id VLOG(notifications) << "Remove " << notification_id << " from " << m->message_id << " in " << group_info.group_id
<< '/' << d->dialog_id << " from database"; << '/' << d->dialog_id << " from database, was_active = " << had_active_notification
<< ", is_permanent = " << is_permanent;
delete_notification_id_to_message_id_correspondence(d, notification_id, m->message_id); delete_notification_id_to_message_id_correspondence(d, notification_id, m->message_id);
m->notification_id = NotificationId(); m->notification_id = NotificationId();
if (group_info.last_notification_id == notification_id) { if (group_info.last_notification_id == notification_id) {
@ -10513,7 +10546,7 @@ void MessagesManager::fix_dialog_last_notification_id(Dialog *d, bool from_menti
} }
if (G()->parameters().use_message_db) { if (G()->parameters().use_message_db) {
do_get_message_notifications_from_database( do_get_message_notifications_from_database(
d, from_mentions, group_info.last_notification_id, message_id, 1, d, from_mentions, group_info.last_notification_id, group_info.last_notification_id, message_id, 1,
PromiseCreator::lambda( PromiseCreator::lambda(
[actor_id = actor_id(this), dialog_id = d->dialog_id, from_mentions, [actor_id = actor_id(this), dialog_id = d->dialog_id, from_mentions,
prev_last_notification_id = group_info.last_notification_id](Result<vector<Notification>> result) { prev_last_notification_id = group_info.last_notification_id](Result<vector<Notification>> result) {
@ -17693,14 +17726,44 @@ bool MessagesManager::is_from_mention_notification_group(const Dialog *d, const
bool MessagesManager::is_message_notification_active(const Dialog *d, const Message *m) { bool MessagesManager::is_message_notification_active(const Dialog *d, const Message *m) {
if (is_from_mention_notification_group(d, m)) { if (is_from_mention_notification_group(d, m)) {
return m->notification_id.get() > d->mention_notification_group.max_removed_notification_id.get() && return m->notification_id.get() > d->mention_notification_group.max_removed_notification_id.get() &&
((m->contains_unread_mention && m->message_id.get() > d->last_read_all_mentions_message_id.get()) || (m->contains_unread_mention || m->message_id == d->pinned_message_notification_message_id);
false /*TODO d->pinned_message_notification_message_id == m->message_id */);
} else { } else {
return m->notification_id.get() > d->message_notification_group.max_removed_notification_id.get() && return m->notification_id.get() > d->message_notification_group.max_removed_notification_id.get() &&
m->message_id.get() > d->last_read_inbox_message_id.get(); m->message_id.get() > d->last_read_inbox_message_id.get();
} }
} }
void MessagesManager::try_add_pinned_message_notification(Dialog *d, vector<Notification> &res,
NotificationId max_notification_id, int32 limit) {
CHECK(d != nullptr);
auto message_id = d->pinned_message_notification_message_id;
if (!message_id.is_valid()) {
return;
}
auto m = get_message_force(d, message_id);
if (m->notification_id.get() > d->mention_notification_group.max_removed_notification_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 pos = res.size();
res.emplace_back(m->notification_id, m->date, create_new_message_notification(message_id));
while (pos > 0 && res[pos - 1].type->get_message_id().get() < message_id.get()) {
std::swap(res[pos - 1], res[pos]);
pos--;
}
if (pos > 0 && res[pos - 1].type->get_message_id().get() == message_id.get()) {
res.erase(res.begin() + pos); // notification was already there
}
if (res.size() > static_cast<size_t>(limit)) {
res.pop_back();
CHECK(res.size() == static_cast<size_t>(limit));
}
}
} else {
set_dialog_pinned_message_notification(d, MessageId());
}
}
vector<Notification> MessagesManager::get_message_notifications_from_database_force(Dialog *d, bool from_mentions, vector<Notification> MessagesManager::get_message_notifications_from_database_force(Dialog *d, bool from_mentions,
int32 limit) { int32 limit) {
CHECK(d != nullptr); CHECK(d != nullptr);
@ -17711,19 +17774,18 @@ vector<Notification> MessagesManager::get_message_notifications_from_database_fo
auto &group_info = from_mentions ? d->mention_notification_group : d->message_notification_group; auto &group_info = from_mentions ? d->mention_notification_group : d->message_notification_group;
auto from_notification_id = NotificationId::max(); auto from_notification_id = NotificationId::max();
auto from_message_id = MessageId::max(); auto from_message_id = MessageId::max();
vector<Notification> res;
while (true) { while (true) {
auto result = do_get_message_notifications_from_database_force(d, from_mentions, from_notification_id, auto result = do_get_message_notifications_from_database_force(d, from_mentions, from_notification_id,
from_message_id, limit); from_message_id, limit);
if (result.is_error()) { if (result.is_error()) {
return {}; break;
} }
auto messages = result.move_as_ok(); auto messages = result.move_as_ok();
if (messages.empty()) { if (messages.empty()) {
return {}; break;
} }
vector<Notification> res;
res.reserve(messages.size());
bool is_found = false; bool is_found = false;
VLOG(notifications) << "Loaded " << messages.size() << (from_mentions ? " mention" : "") VLOG(notifications) << "Loaded " << messages.size() << (from_mentions ? " mention" : "")
<< " messages with notifications from database in " << group_info.group_id << '/' << " messages with notifications from database in " << group_info.group_id << '/'
@ -17756,9 +17818,13 @@ vector<Notification> MessagesManager::get_message_notifications_from_database_fo
} }
} }
if (!res.empty() || !is_found) { if (!res.empty() || !is_found) {
return res; break;
} }
} }
if (from_mentions) {
try_add_pinned_message_notification(d, res, NotificationId::max(), limit);
}
return res;
} }
Result<vector<BufferSlice>> MessagesManager::do_get_message_notifications_from_database_force( Result<vector<BufferSlice>> MessagesManager::do_get_message_notifications_from_database_force(
@ -17845,11 +17911,12 @@ void MessagesManager::get_message_notifications_from_database(DialogId dialog_id
return promise.set_value(std::move(notifications)); return promise.set_value(std::move(notifications));
} }
do_get_message_notifications_from_database(d, from_mentions, from_notification_id, from_message_id, limit, do_get_message_notifications_from_database(d, from_mentions, from_notification_id, from_notification_id,
std::move(promise)); from_message_id, limit, std::move(promise));
} }
void MessagesManager::do_get_message_notifications_from_database(Dialog *d, bool from_mentions, void MessagesManager::do_get_message_notifications_from_database(Dialog *d, bool from_mentions,
NotificationId initial_from_notification_id,
NotificationId from_notification_id, NotificationId from_notification_id,
MessageId from_message_id, int32 limit, MessageId from_message_id, int32 limit,
Promise<vector<Notification>> promise) { Promise<vector<Notification>> promise) {
@ -17862,11 +17929,12 @@ void MessagesManager::do_get_message_notifications_from_database(Dialog *d, bool
} }
auto dialog_id = d->dialog_id; auto dialog_id = d->dialog_id;
auto new_promise = PromiseCreator::lambda([actor_id = actor_id(this), from_mentions, dialog_id, limit, auto new_promise =
promise = std::move(promise)](Result<vector<BufferSlice>> result) mutable { PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, from_mentions, initial_from_notification_id, limit,
send_closure(actor_id, &MessagesManager::on_get_message_notifications_from_database, dialog_id, from_mentions, promise = std::move(promise)](Result<vector<BufferSlice>> result) mutable {
limit, std::move(result), std::move(promise)); send_closure(actor_id, &MessagesManager::on_get_message_notifications_from_database, dialog_id, from_mentions,
}); initial_from_notification_id, limit, std::move(result), std::move(promise));
});
auto *db = G()->td_db()->get_messages_db_async(); auto *db = G()->td_db()->get_messages_db_async();
if (!from_mentions) { if (!from_mentions) {
@ -17888,8 +17956,9 @@ void MessagesManager::do_get_message_notifications_from_database(Dialog *d, bool
} }
} }
void MessagesManager::on_get_message_notifications_from_database(DialogId dialog_id, bool from_mentions, int32 limit, void MessagesManager::on_get_message_notifications_from_database(DialogId dialog_id, bool from_mentions,
Result<vector<BufferSlice>> result, NotificationId initial_from_notification_id,
int32 limit, Result<vector<BufferSlice>> result,
Promise<vector<Notification>> promise) { Promise<vector<Notification>> promise) {
if (result.is_error()) { if (result.is_error()) {
return promise.set_error(result.move_as_error()); return promise.set_error(result.move_as_error());
@ -17937,13 +18006,17 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog
} }
} }
if (!res.empty() || !from_notification_id.is_valid() || static_cast<size_t>(limit) > messages.size()) { if (!res.empty() || !from_notification_id.is_valid() || static_cast<size_t>(limit) > messages.size()) {
if (from_mentions) {
try_add_pinned_message_notification(d, res, initial_from_notification_id, limit);
}
std::reverse(res.begin(), res.end()); std::reverse(res.begin(), res.end());
return promise.set_value(std::move(res)); return promise.set_value(std::move(res));
} }
// try again from adjusted from_notification_id and from_message_id // try again from adjusted from_notification_id and from_message_id
do_get_message_notifications_from_database(d, from_mentions, from_notification_id, from_message_id, limit, do_get_message_notifications_from_database(d, from_mentions, initial_from_notification_id, from_notification_id,
std::move(promise)); from_message_id, limit, std::move(promise));
} }
void MessagesManager::remove_message_notification(DialogId dialog_id, NotificationGroupId group_id, void MessagesManager::remove_message_notification(DialogId dialog_id, NotificationGroupId group_id,
@ -18044,8 +18117,7 @@ void MessagesManager::remove_message_notifications(DialogId dialog_id, Notificat
int32 MessagesManager::get_dialog_pending_notification_count(Dialog *d, bool from_mentions) { int32 MessagesManager::get_dialog_pending_notification_count(Dialog *d, bool from_mentions) {
CHECK(d != nullptr); CHECK(d != nullptr);
if (from_mentions) { if (from_mentions) {
// TODO pinned message return d->unread_mention_count + (d->pinned_message_notification_message_id.is_valid() ? 1 : 0);
return d->unread_mention_count;
} else { } else {
if (d->new_secret_chat_notification_id.is_valid()) { if (d->new_secret_chat_notification_id.is_valid()) {
return 1; return 1;
@ -18066,9 +18138,10 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f
if (m->is_outgoing || d->dialog_id == get_my_dialog_id() || td_->auth_manager_->is_bot()) { if (m->is_outgoing || d->dialog_id == get_my_dialog_id() || td_->auth_manager_->is_bot()) {
return false; return false;
} }
m->notification_id = NotificationId::max(); // temporary for check auto from_mentions = is_from_mention_notification_group(d, m);
bool is_active = is_message_notification_active(d, m); bool is_pinned = m->content->get_type() == MessageContentType::PinMessage;
m->notification_id = NotificationId(); 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) { if (!is_active) {
VLOG(notifications) << "Disable inactive notification for " << m->message_id << " in " << d->dialog_id; VLOG(notifications) << "Disable inactive notification for " << m->message_id << " in " << d->dialog_id;
return false; return false;
@ -18103,10 +18176,12 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f
std::tie(have_settings, mute_until) = get_dialog_mute_until(settings_dialog_id, settings_dialog); std::tie(have_settings, mute_until) = get_dialog_mute_until(settings_dialog_id, settings_dialog);
if (mute_until > G()->unix_time()) { if (mute_until > G()->unix_time()) {
VLOG(notifications) << "Disable notification, because " << settings_dialog_id << " is muted"; VLOG(notifications) << "Disable notification, because " << settings_dialog_id << " is muted";
if (is_pinned) {
set_dialog_pinned_message_notification(d, MessageId());
}
return false; return false;
} }
auto from_mentions = is_from_mention_notification_group(d, m);
auto &pending_notifications = auto &pending_notifications =
from_mentions ? d->pending_new_mention_notifications : d->pending_new_message_notifications; from_mentions ? d->pending_new_mention_notifications : d->pending_new_message_notifications;
if (!force && (!have_settings || !pending_notifications.empty())) { if (!force && (!have_settings || !pending_notifications.empty())) {
@ -18159,6 +18234,9 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f
bool is_changed = set_dialog_last_notification(d->dialog_id, group_info, m->date, m->notification_id, bool is_changed = set_dialog_last_notification(d->dialog_id, group_info, m->date, m->notification_id,
"add_new_message_notification"); "add_new_message_notification");
CHECK(is_changed); CHECK(is_changed);
if (is_pinned) {
set_dialog_pinned_message_notification(d, from_mentions ? m->message_id : MessageId());
}
VLOG(notifications) << "Create " << m->notification_id << " with " << m->message_id << " in " << group_info.group_id VLOG(notifications) << "Create " << m->notification_id << " with " << m->message_id << " in " << group_info.group_id
<< '/' << d->dialog_id; << '/' << d->dialog_id;
send_closure_later(G()->notification_manager(), &NotificationManager::add_notification, notification_group_id, send_closure_later(G()->notification_manager(), &NotificationManager::add_notification, notification_group_id,
@ -20976,6 +21054,12 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
} }
if (*need_update) { if (*need_update) {
if (message_content_type == MessageContentType::PinMessage &&
!get_message_content_pinned_message_id(message->content.get()).is_valid()) {
// treat message pin without pinned message as ordinary message
message->contains_mention = false;
}
// notification must be added before updating unread_count to have correct total notification count // notification must be added before updating unread_count to have correct total notification count
// in get_message_notification_group_force // in get_message_notification_group_force
add_new_message_notification(d, message.get(), false); add_new_message_notification(d, message.get(), false);
@ -21088,10 +21172,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
td_->contacts_manager_->speculative_add_channel_participants(dialog_id.get_channel_id(), new_participant_count, td_->contacts_manager_->speculative_add_channel_participants(dialog_id.get_channel_id(), new_participant_count,
m->sender_user_id == my_user_id); m->sender_user_id == my_user_id);
} }
auto pinned_message_id = get_message_content_pinned_message_id(m->content.get());
if (pinned_message_id.is_valid()) {
td_->contacts_manager_->on_update_channel_pinned_message(dialog_id.get_channel_id(), pinned_message_id);
}
} }
if (from_update && message_id.is_server()) { if (from_update && message_id.is_server()) {
auto pinned_message_id = get_message_content_pinned_message_id(m->content.get()); auto pinned_message_id = get_message_content_pinned_message_id(m->content.get());
@ -21099,9 +21179,9 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
switch (dialog_id.get_type()) { switch (dialog_id.get_type()) {
case DialogType::User: case DialogType::User:
case DialogType::Chat: case DialogType::Chat:
// nothing to do yet
break; break;
case DialogType::SecretChat: case DialogType::SecretChat:
// nothing to do yet
break; break;
case DialogType::Channel: case DialogType::Channel:
td_->contacts_manager_->on_update_channel_pinned_message(dialog_id.get_channel_id(), pinned_message_id); td_->contacts_manager_->on_update_channel_pinned_message(dialog_id.get_channel_id(), pinned_message_id);

View File

@ -904,6 +904,7 @@ class MessagesManager : public Actor {
NotificationGroupInfo message_notification_group; NotificationGroupInfo message_notification_group;
NotificationGroupInfo mention_notification_group; NotificationGroupInfo mention_notification_group;
NotificationId new_secret_chat_notification_id; // secret chats only NotificationId new_secret_chat_notification_id; // secret chats only
MessageId pinned_message_notification_message_id;
bool has_contact_registered_message = false; bool has_contact_registered_message = false;
@ -1519,17 +1520,22 @@ class MessagesManager : public Actor {
NotificationId get_next_notification_id(Dialog *d, NotificationGroupId notification_group_id, MessageId message_id); NotificationId get_next_notification_id(Dialog *d, NotificationGroupId notification_group_id, MessageId message_id);
void try_add_pinned_message_notification(Dialog *d, vector<Notification> &res, NotificationId max_notification_id,
int32 limit);
vector<Notification> get_message_notifications_from_database_force(Dialog *d, bool from_mentions, int32 limit); vector<Notification> get_message_notifications_from_database_force(Dialog *d, bool from_mentions, int32 limit);
Result<vector<BufferSlice>> do_get_message_notifications_from_database_force(Dialog *d, bool from_mentions, Result<vector<BufferSlice>> do_get_message_notifications_from_database_force(Dialog *d, bool from_mentions,
NotificationId from_notification_id, NotificationId from_notification_id,
MessageId from_message_id, int32 limit); MessageId from_message_id, int32 limit);
void do_get_message_notifications_from_database(Dialog *d, bool from_mentions, NotificationId from_notification_id, void do_get_message_notifications_from_database(Dialog *d, bool from_mentions,
MessageId from_message_id, int32 limit, NotificationId initial_from_notification_id,
Promise<vector<Notification>> promise); NotificationId from_notification_id, MessageId from_message_id,
int32 limit, Promise<vector<Notification>> promise);
void on_get_message_notifications_from_database(DialogId dialog_id, bool from_mentions, int32 limit, void on_get_message_notifications_from_database(DialogId dialog_id, bool from_mentions,
NotificationId initial_from_notification_id, int32 limit,
Result<vector<BufferSlice>> result, Result<vector<BufferSlice>> result,
Promise<vector<Notification>> promise); Promise<vector<Notification>> promise);
@ -1632,6 +1638,8 @@ class MessagesManager : public Actor {
void try_restore_dialog_reply_markup(Dialog *d, const Message *m); void try_restore_dialog_reply_markup(Dialog *d, const Message *m);
void set_dialog_pinned_message_notification(Dialog *d, MessageId message_id);
bool set_dialog_last_notification(DialogId dialog_id, NotificationGroupInfo &group_info, int32 last_notification_date, bool set_dialog_last_notification(DialogId dialog_id, NotificationGroupInfo &group_info, int32 last_notification_date,
NotificationId last_notification_id, const char *source); NotificationId last_notification_id, const char *source);

View File

@ -1008,7 +1008,8 @@ void NotificationManager::flush_pending_updates(int32 group_id, const char *sour
updates[i]->get_id() == td_api::updateNotificationGroup::ID) { updates[i]->get_id() == td_api::updateNotificationGroup::ID) {
auto last_update_ptr = static_cast<td_api::updateNotificationGroup *>(updates[last_update_pos].get()); auto last_update_ptr = static_cast<td_api::updateNotificationGroup *>(updates[last_update_pos].get());
auto update_ptr = static_cast<td_api::updateNotificationGroup *>(updates[i].get()); auto update_ptr = static_cast<td_api::updateNotificationGroup *>(updates[i].get());
if (last_update_ptr->notification_settings_chat_id_ == update_ptr->notification_settings_chat_id_ && if ((last_update_ptr->notification_settings_chat_id_ == update_ptr->notification_settings_chat_id_ ||
last_update_ptr->added_notifications_.empty()) &&
!has_common_notifications(last_update_ptr->added_notifications_, update_ptr->removed_notification_ids_) && !has_common_notifications(last_update_ptr->added_notifications_, update_ptr->removed_notification_ids_) &&
!has_common_notifications(update_ptr->added_notifications_, last_update_ptr->removed_notification_ids_)) { !has_common_notifications(update_ptr->added_notifications_, last_update_ptr->removed_notification_ids_)) {
// combine updates // combine updates
@ -1019,6 +1020,7 @@ void NotificationManager::flush_pending_updates(int32 group_id, const char *sour
if (last_update_ptr->is_silent_ && !update_ptr->is_silent_) { if (last_update_ptr->is_silent_ && !update_ptr->is_silent_) {
last_update_ptr->is_silent_ = false; last_update_ptr->is_silent_ = false;
} }
last_update_ptr->notification_settings_chat_id_ = update_ptr->notification_settings_chat_id_;
last_update_ptr->type_ = std::move(update_ptr->type_); last_update_ptr->type_ = std::move(update_ptr->type_);
last_update_ptr->total_count_ = update_ptr->total_count_; last_update_ptr->total_count_ = update_ptr->total_count_;
append(last_update_ptr->added_notifications_, std::move(update_ptr->added_notifications_)); append(last_update_ptr->added_notifications_, std::move(update_ptr->added_notifications_));
@ -1543,11 +1545,13 @@ void NotificationManager::remove_notification_group(NotificationGroupId group_id
pending_delete_end = it + 1; pending_delete_end = it + 1;
} }
} }
group_it->second.pending_notifications.erase(group_it->second.pending_notifications.begin(), pending_delete_end); if (pending_delete_end != group_it->second.pending_notifications.begin()) {
if (group_it->second.pending_notifications.empty()) { group_it->second.pending_notifications.erase(group_it->second.pending_notifications.begin(), pending_delete_end);
group_it->second.pending_notifications_flush_time = 0; if (group_it->second.pending_notifications.empty()) {
flush_pending_notifications_timeout_.cancel_timeout(group_id.get()); group_it->second.pending_notifications_flush_time = 0;
on_pending_notification_update_count_changed(-1); flush_pending_notifications_timeout_.cancel_timeout(group_id.get());
on_pending_notification_update_count_changed(-1);
}
} }
if (new_total_count != -1) { if (new_total_count != -1) {
new_total_count -= static_cast<int32>(group_it->second.pending_notifications.size()); new_total_count -= static_cast<int32>(group_it->second.pending_notifications.size());

View File

@ -3248,7 +3248,7 @@ class CliClient final : public Actor {
std::tie(supergroup_id, message_id) = split(args); std::tie(supergroup_id, message_id) = split(args);
send_request(make_tl_object<td_api::pinSupergroupMessage>(to_integer<int32>(supergroup_id), send_request(make_tl_object<td_api::pinSupergroupMessage>(to_integer<int32>(supergroup_id),
as_message_id(message_id), false)); as_message_id(message_id), true));
} else if (op == "upsgm" || op == "upchm") { } else if (op == "upsgm" || op == "upchm") {
send_request(make_tl_object<td_api::unpinSupergroupMessage>(to_integer<int32>(args))); send_request(make_tl_object<td_api::unpinSupergroupMessage>(to_integer<int32>(args)));
} else if (op == "grib") { } else if (op == "grib") {