Implement update_dialog_lists.

GitOrigin-RevId: 86e87827fe15c6404d1a0e859a99063ea2173557
This commit is contained in:
levlam 2020-05-09 23:39:11 +03:00
parent 3c93bf8da2
commit f6b7ce83f7
4 changed files with 237 additions and 198 deletions

View File

@ -669,7 +669,7 @@ chatSourcePublicServiceAnnouncement type:string text:string = ChatSource;
//@description Describes a position of a chat in a chat list //@description Describes a position of a chat in a chat list
//@list The chat list //@list The chat list
//@order A parameter used to determine order of the chat in the chat list. Chats must be sorted by the pair (order, chat.id) in descending order. If 0, the position of the chat in the list is undetermined //@order A parameter used to determine order of the chat in the chat list. Chats must be sorted by the pair (order, chat.id) in descending order
//@is_pinned True, if the chat is pinned in the chat list //@is_pinned True, if the chat is pinned in the chat list
//@source Source of the chat in the chat list; may be null //@source Source of the chat in the chat list; may be null
chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPosition; chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPosition;
@ -2896,7 +2896,7 @@ updateChatPermissions chat_id:int53 permissions:chatPermissions = Update;
//@description The last message of a chat was changed. If last_message is null, then the last message in the chat became unknown. Some new unknown messages might be added to the chat in this case @chat_id Chat identifier @last_message The new last message in the chat; may be null @positions The new chat positions in the chat lists //@description The last message of a chat was changed. If last_message is null, then the last message in the chat became unknown. Some new unknown messages might be added to the chat in this case @chat_id Chat identifier @last_message The new last message in the chat; may be null @positions The new chat positions in the chat lists
updateChatLastMessage chat_id:int53 last_message:message positions:vector<chatPosition> = Update; updateChatLastMessage chat_id:int53 last_message:message positions:vector<chatPosition> = Update;
//@description The position of a chat in a chat list has changed. Instead of this update updateChatLastMessage or updateChatDraftMessage might be sent @chat_id Chat identifier @position New chat position //@description The position of a chat in a chat list has changed. Instead of this update updateChatLastMessage or updateChatDraftMessage might be sent @chat_id Chat identifier @position New chat position. If new order is 0, then the chat needs to be removed from the list
updateChatPosition chat_id:int53 position:chatPosition = Update; updateChatPosition chat_id:int53 position:chatPosition = Update;
//@description A chat was marked as unread or was read @chat_id Chat identifier @is_marked_as_unread New value of is_marked_as_unread //@description A chat was marked as unread or was read @chat_id Chat identifier @is_marked_as_unread New value of is_marked_as_unread

View File

@ -9988,10 +9988,11 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
d->server_unread_count = server_unread_count; d->server_unread_count = server_unread_count;
d->local_unread_count = local_unread_count; d->local_unread_count = local_unread_count;
if (need_unread_counter(d->order)) {
for (auto &list : get_dialog_lists(d)) { for (auto &list : get_dialog_lists(d)) {
int32 new_unread_count = d->server_unread_count + d->local_unread_count; int32 new_unread_count = d->server_unread_count + d->local_unread_count;
int32 delta = new_unread_count - old_unread_count; int32 delta = new_unread_count - old_unread_count;
if (delta != 0 && need_unread_counter(d->order) && list.is_message_unread_count_inited_) { if (delta != 0 && list.is_message_unread_count_inited_) {
list.unread_message_total_count_ += delta; list.unread_message_total_count_ += delta;
if (is_dialog_muted(d)) { if (is_dialog_muted(d)) {
list.unread_message_muted_count_ += delta; list.unread_message_muted_count_ += delta;
@ -9999,7 +10000,7 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
send_update_unread_message_count(list.folder_id, d->dialog_id, force_update, source); send_update_unread_message_count(list.folder_id, d->dialog_id, force_update, source);
} }
delta = static_cast<int32>(new_unread_count != 0) - static_cast<int32>(old_unread_count != 0); delta = static_cast<int32>(new_unread_count != 0) - static_cast<int32>(old_unread_count != 0);
if (delta != 0 && need_unread_counter(d->order) && list.is_dialog_unread_count_inited_) { if (delta != 0 && list.is_dialog_unread_count_inited_) {
if (d->is_marked_as_unread) { if (d->is_marked_as_unread) {
list.unread_dialog_marked_count_ -= delta; list.unread_dialog_marked_count_ -= delta;
} else { } else {
@ -10015,6 +10016,7 @@ void MessagesManager::set_dialog_last_read_inbox_message_id(Dialog *d, MessageId
send_update_unread_chat_count(list.folder_id, d->dialog_id, force_update, source); send_update_unread_chat_count(list.folder_id, d->dialog_id, force_update, source);
} }
} }
}
if (message_id != MessageId::min() && d->last_read_inbox_message_id.is_valid() && if (message_id != MessageId::min() && d->last_read_inbox_message_id.is_valid() &&
(d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) { (d->order != DEFAULT_ORDER || is_dialog_sponsored(d))) {
@ -10669,6 +10671,11 @@ void MessagesManager::init() {
} }
G()->td_db()->get_binlog_pmc()->erase("nsfac"); G()->td_db()->get_binlog_pmc()->erase("nsfac");
if (!td_->auth_manager_->is_bot()) { // ensure that Main and Archive dialog lists are created
get_dialog_list(FolderId::main());
get_dialog_list(FolderId::archive());
}
auto auth_notification_ids_string = G()->td_db()->get_binlog_pmc()->get("auth_notification_ids"); auto auth_notification_ids_string = G()->td_db()->get_binlog_pmc()->get("auth_notification_ids");
if (!auth_notification_ids_string.empty()) { if (!auth_notification_ids_string.empty()) {
VLOG(notifications) << "Load auth_notification_ids = " << auth_notification_ids_string; VLOG(notifications) << "Load auth_notification_ids = " << auth_notification_ids_string;
@ -11999,17 +12006,19 @@ void MessagesManager::set_dialog_is_pinned(DialogId dialog_id, bool is_pinned) {
set_dialog_is_pinned(d->folder_id, d, is_pinned); set_dialog_is_pinned(d->folder_id, d, is_pinned);
} }
bool MessagesManager::set_dialog_is_pinned(FolderId folder_id, Dialog *d, bool is_pinned) { bool MessagesManager::set_dialog_is_pinned(FolderId folder_id, Dialog *d, bool is_pinned,
bool need_update_dialog_lists) {
if (td_->auth_manager_->is_bot()) { if (td_->auth_manager_->is_bot()) {
return false; return false;
} }
CHECK(d != nullptr); CHECK(d != nullptr);
if (is_removed_from_dialog_list(d) && is_pinned) { if ((is_removed_from_dialog_list(d) || d->order == DEFAULT_ORDER) && is_pinned) {
// the chat can't be pinned // the chat can't be pinned
return false; return false;
} }
auto orders = get_dialog_orders(d);
auto &list = get_dialog_list(folder_id); auto &list = get_dialog_list(folder_id);
bool was_pinned = false; bool was_pinned = false;
for (size_t pos = 0; pos < list.pinned_dialogs_.size(); pos++) { for (size_t pos = 0; pos < list.pinned_dialogs_.size(); pos++) {
@ -12045,9 +12054,9 @@ bool MessagesManager::set_dialog_is_pinned(FolderId folder_id, Dialog *d, bool i
LOG(INFO) << "Set " << d->dialog_id << " is pinned in " << folder_id << " to " << is_pinned; LOG(INFO) << "Set " << d->dialog_id << " is pinned in " << folder_id << " to " << is_pinned;
on_pinned_dialogs_updated(folder_id); on_pinned_dialogs_updated(folder_id);
LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in set_dialog_is_pinned"; if (need_update_dialog_lists) {
update_dialog_pos(d, "set_dialog_is_pinned", false); update_dialog_lists(d, std::move(orders), true, false, "set_dialog_is_pinned");
send_update_chat_position(folder_id, d); }
return true; return true;
} }
@ -12514,9 +12523,6 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<te
set_channel_pts(d, channel_pts, "get channel"); set_channel_pts(d, channel_pts, "get channel");
} }
} }
if (set_dialog_is_pinned(d->folder_id, d, (dialog->flags_ & DIALOG_FLAG_IS_PINNED) != 0)) {
need_update_dialog_pos = false;
}
bool is_marked_as_unread = (dialog->flags_ & telegram_api::dialog::UNREAD_MARK_MASK) != 0; bool is_marked_as_unread = (dialog->flags_ & telegram_api::dialog::UNREAD_MARK_MASK) != 0;
if (is_marked_as_unread != d->is_marked_as_unread) { if (is_marked_as_unread != d->is_marked_as_unread) {
set_dialog_is_marked_as_unread(d, is_marked_as_unread); set_dialog_is_marked_as_unread(d, is_marked_as_unread);
@ -12526,6 +12532,9 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<te
update_dialog_pos(d, "on_get_dialogs"); update_dialog_pos(d, "on_get_dialogs");
} }
// set is_pinned only after updating dialog pos to ensure that order is initialized
set_dialog_is_pinned(d->folder_id, d, (dialog->flags_ & DIALOG_FLAG_IS_PINNED) != 0);
if (!G()->parameters().use_message_db || is_new || !d->is_last_read_inbox_message_id_inited || if (!G()->parameters().use_message_db || is_new || !d->is_last_read_inbox_message_id_inited ||
d->need_repair_server_unread_count) { d->need_repair_server_unread_count) {
if (d->last_read_inbox_message_id.is_valid() && !d->last_read_inbox_message_id.is_server() && if (d->last_read_inbox_message_id.is_valid() && !d->last_read_inbox_message_id.is_server() &&
@ -14799,6 +14808,9 @@ Status MessagesManager::set_pinned_dialogs(FolderId folder_id, vector<DialogId>
if (!have_input_peer(dialog_id, AccessRights::Read)) { if (!have_input_peer(dialog_id, AccessRights::Read)) {
return Status::Error(6, "Can't access the chat"); return Status::Error(6, "Can't access the chat");
} }
if (is_removed_from_dialog_list(d) || d->order == DEFAULT_ORDER) {
return Status::Error(6, "The chat can't be pinned");
}
if (dialog_id.get_type() == DialogType::SecretChat) { if (dialog_id.get_type() == DialogType::SecretChat) {
secret_dialog_count++; secret_dialog_count++;
} else { } else {
@ -23273,9 +23285,12 @@ void MessagesManager::send_update_chat_position(FolderId folder_id, const Dialog
CHECK(d != nullptr); CHECK(d != nullptr);
LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_position"; LOG_CHECK(d->is_update_new_chat_sent) << "Wrong " << d->dialog_id << " in send_update_chat_position";
LOG(INFO) << "Update chat position for " << d->dialog_id; auto position = get_chat_position_object(folder_id, d);
if (position == nullptr) {
position = td_api::make_object<td_api::chatPosition>(get_chat_list_object(folder_id), 0, false, nullptr);
}
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateChatPosition>(d->dialog_id.get(), get_chat_position_object(folder_id, d))); make_tl_object<td_api::updateChatPosition>(d->dialog_id.get(), std::move(position)));
} }
void MessagesManager::send_update_chat_online_member_count(DialogId dialog_id, int32 online_member_count) const { void MessagesManager::send_update_chat_online_member_count(DialogId dialog_id, int32 online_member_count) const {
@ -24280,17 +24295,12 @@ void MessagesManager::set_dialog_folder_id(Dialog *d, FolderId folder_id) {
LOG(INFO) << "Change " << d->dialog_id << " folder from " << d->folder_id << " to " << folder_id; LOG(INFO) << "Change " << d->dialog_id << " folder from " << d->folder_id << " to " << folder_id;
// first remove the dialog from the old chat list auto dialog_orders = get_dialog_orders(d);
// this will send updateChatChatList if needed
set_dialog_order(d, DEFAULT_ORDER, true, false, "set_dialog_folder_id old");
// change the folder
d->folder_id = folder_id; d->folder_id = folder_id;
d->is_folder_id_inited = true; d->is_folder_id_inited = true;
// update dialog position in the new folder update_dialog_lists(d, std::move(dialog_orders), true, false, "set_dialog_folder_id");
// this will send updateChatChatList if needed
update_dialog_pos(d, "set_dialog_folder_id new");
on_dialog_updated(d->dialog_id, "set_dialog_folder_id"); on_dialog_updated(d->dialog_id, "set_dialog_folder_id");
} }
@ -28603,28 +28613,17 @@ int64 MessagesManager::get_dialog_private_order(const DialogList *list, const Di
if (is_dialog_sponsored(d) && list->folder_id == FolderId::main()) { if (is_dialog_sponsored(d) && list->folder_id == FolderId::main()) {
return SPONSORED_DIALOG_ORDER; return SPONSORED_DIALOG_ORDER;
} }
if (d->order == DEFAULT_ORDER) {
return 0;
}
auto pinned_order = get_dialog_pinned_order(list, d->dialog_id); auto pinned_order = get_dialog_pinned_order(list, d->dialog_id);
if (pinned_order != DEFAULT_ORDER) { if (pinned_order != DEFAULT_ORDER) {
return pinned_order; return pinned_order;
} }
return d->order; if (list->folder_id != d->folder_id) {
}
int64 MessagesManager::get_dialog_public_order(FolderId folder_id, const Dialog *d) const {
if (td_->auth_manager_->is_bot()) {
return 0; // to not call get_dialog_list
}
return get_dialog_public_order(get_dialog_list(folder_id), d);
}
int64 MessagesManager::get_dialog_public_order(const DialogList *list, const Dialog *d) const {
if (list == nullptr || td_->auth_manager_->is_bot()) {
return 0; return 0;
} }
return d->order;
auto order = get_dialog_private_order(list, d);
DialogDate dialog_date(order, d->dialog_id);
return dialog_date <= list->last_dialog_date_ ? order : 0;
} }
td_api::object_ptr<td_api::chatPosition> MessagesManager::get_chat_position_object(FolderId folder_id, td_api::object_ptr<td_api::chatPosition> MessagesManager::get_chat_position_object(FolderId folder_id,
@ -28638,15 +28637,14 @@ td_api::object_ptr<td_api::chatPosition> MessagesManager::get_chat_position_obje
return nullptr; return nullptr;
} }
auto order = get_dialog_private_order(list, d); auto order = get_dialog_order_in_list(list, d);
DialogDate dialog_date(order, d->dialog_id); if (order.public_order == 0) {
if (list->last_dialog_date_ < dialog_date || order == 0) {
return nullptr; return nullptr;
} }
bool is_pinned = get_dialog_pinned_order(list, d->dialog_id) != DEFAULT_ORDER; auto chat_source = order.is_sponsored ? sponsored_dialog_source_.get_chat_source_object() : nullptr;
return td_api::make_object<td_api::chatPosition>(get_chat_list_object(folder_id), order, is_pinned, return td_api::make_object<td_api::chatPosition>(get_chat_list_object(folder_id), order.public_order, order.is_pinned,
sponsored_dialog_source_.get_chat_source_object()); std::move(chat_source));
} }
vector<td_api::object_ptr<td_api::chatPosition>> MessagesManager::get_chat_positions_object(const Dialog *d) const { vector<td_api::object_ptr<td_api::chatPosition>> MessagesManager::get_chat_positions_object(const Dialog *d) const {
@ -28683,7 +28681,7 @@ bool MessagesManager::is_removed_from_dialog_list(const Dialog *d) const {
return false; return false;
} }
void MessagesManager::update_dialog_pos(Dialog *d, const char *source, bool need_send_update_chat_order, void MessagesManager::update_dialog_pos(Dialog *d, const char *source, bool need_send_update,
bool is_loaded_from_database) { bool is_loaded_from_database) {
if (td_->auth_manager_->is_bot()) { if (td_->auth_manager_->is_bot()) {
return; return;
@ -28757,13 +28755,13 @@ void MessagesManager::update_dialog_pos(Dialog *d, const char *source, bool need
} }
} }
if (set_dialog_order(d, new_order, need_send_update_chat_order, is_loaded_from_database, source)) { if (set_dialog_order(d, new_order, need_send_update, is_loaded_from_database, source)) {
on_dialog_updated(d->dialog_id, "update_dialog_pos"); on_dialog_updated(d->dialog_id, "update_dialog_pos");
} }
} }
bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_send_update_chat_order, bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_send_update, bool is_loaded_from_database,
bool is_loaded_from_database, const char *source) { const char *source) {
if (td_->auth_manager_->is_bot()) { if (td_->auth_manager_->is_bot()) {
return false; return false;
} }
@ -28775,16 +28773,19 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
auto &list = get_dialog_list(d->folder_id); auto &list = get_dialog_list(d->folder_id);
if (old_date == new_date) { if (old_date == new_date) {
LOG(INFO) << "Order of " << d->dialog_id << " is still " << new_order << " from " << source;
if (new_order == DEFAULT_ORDER) { if (new_order == DEFAULT_ORDER) {
// first addition of a new left dialog // first addition of a new left dialog
list.ordered_dialogs_.insert(new_date); list.ordered_dialogs_.insert(new_date);
} }
LOG(INFO) << "Chat order is not changed: " << new_order << " from " << source;
return false; return false;
} }
LOG(INFO) << "Update order of " << dialog_id << " from " << d->order << " to " << new_order << " from " << source; LOG(INFO) << "Update order of " << dialog_id << " from " << d->order << " to " << new_order << " from " << source;
auto old_public_order = get_dialog_public_order(&list, d); auto dialog_orders = get_dialog_orders(d);
if (list.ordered_dialogs_.erase(old_date) == 0) { if (list.ordered_dialogs_.erase(old_date) == 0) {
LOG_IF(ERROR, d->order != DEFAULT_ORDER) << dialog_id << " not found in the chat list from " << source; LOG_IF(ERROR, d->order != DEFAULT_ORDER) << dialog_id << " not found in the chat list from " << source;
} }
@ -28792,15 +28793,63 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
list.ordered_dialogs_.insert(new_date); list.ordered_dialogs_.insert(new_date);
bool add_to_hints = (d->order == DEFAULT_ORDER); bool add_to_hints = (d->order == DEFAULT_ORDER);
bool was_sponsored = is_dialog_sponsored(d);
bool had_unread_counter = need_unread_counter(d->order);
bool has_unread_counter = need_unread_counter(new_order);
bool is_removed_from_folder = new_order == DEFAULT_ORDER;
bool is_added_to_folder = d->order == DEFAULT_ORDER;
auto old_dialog_total_count = get_dialog_total_count(list); d->order = new_order;
if (is_removed_from_folder || is_added_to_folder) {
int32 delta = is_removed_from_folder ? -1 : 1; if (add_to_hints) {
update_dialogs_hints(d);
}
update_dialogs_hints_rating(d);
update_dialog_lists(d, std::move(dialog_orders), need_send_update, is_loaded_from_database, source);
return true;
}
void MessagesManager::update_dialog_lists(Dialog *d,
std::unordered_map<FolderId, DialogOrderInList, FolderIdHash> &&old_orders,
bool need_send_update, bool is_loaded_from_database, const char *source) {
if (td_->auth_manager_->is_bot()) {
return;
}
CHECK(d != nullptr);
auto dialog_id = d->dialog_id;
LOG(INFO) << "Update lists of " << dialog_id << " from " << source;
if (d->order == DEFAULT_ORDER) {
if (d->folder_id != FolderId::main()) {
d->folder_id = FolderId::main();
d->is_folder_id_inited = true;
on_dialog_updated(dialog_id, "update_dialog_lists");
}
for (auto &old_order : old_orders) {
if (old_order.second.is_pinned) {
set_dialog_is_pinned(old_order.first, d, false, false);
}
}
}
for (auto &dialog_list : dialog_lists_) {
auto dialog_list_id = dialog_list.first;
auto &list = dialog_list.second;
const DialogOrderInList &old_order = old_orders[dialog_list_id];
const DialogOrderInList new_order = get_dialog_order_in_list(&list, d);
bool was_in_list = old_order.order != DEFAULT_ORDER && old_order.private_order != 0;
bool is_in_list = new_order.order != DEFAULT_ORDER && new_order.private_order != 0;
CHECK(was_in_list == td::contains(d->dialog_list_ids, dialog_list_id));
if (need_send_update &&
(old_order.public_order != new_order.public_order || old_order.is_pinned != new_order.is_pinned ||
old_order.is_sponsored != new_order.is_sponsored)) {
send_update_chat_position(dialog_list_id, d);
}
if (was_in_list != is_in_list) {
const int32 delta = was_in_list ? -1 : 1;
list.in_memory_dialog_total_count_ += delta; list.in_memory_dialog_total_count_ += delta;
if (!is_loaded_from_database) { if (!is_loaded_from_database) {
int32 &total_count = dialog_id.get_type() == DialogType::SecretChat ? list.secret_chat_total_count_ int32 &total_count = dialog_id.get_type() == DialogType::SecretChat ? list.secret_chat_total_count_
@ -28813,48 +28862,20 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
} }
} }
} }
}
d->order = new_order; if (!is_loaded_from_database) {
if (new_order == DEFAULT_ORDER && get_dialog_pinned_order(&list, dialog_id) != DEFAULT_ORDER) {
for (size_t pos = 0; pos < list.pinned_dialogs_.size(); pos++) {
if (list.pinned_dialogs_[pos].get_dialog_id() == d->dialog_id) {
list.pinned_dialogs_.erase(list.pinned_dialogs_.begin() + pos);
break;
}
}
list.pinned_dialog_id_orders_.erase(d->dialog_id);
on_pinned_dialogs_updated(d->folder_id);
}
bool need_update_unread_chat_count = old_dialog_total_count != get_dialog_total_count(list);
CHECK(static_cast<size_t>(list.in_memory_dialog_total_count_) <= list.ordered_dialogs_.size());
if (!is_loaded_from_database && had_unread_counter != has_unread_counter) {
auto unread_count = d->server_unread_count + d->local_unread_count; auto unread_count = d->server_unread_count + d->local_unread_count;
const char *change_source = had_unread_counter ? "on_dialog_leave" : "on_dialog_join"; const char *change_source = was_in_list ? "on_dialog_leave" : "on_dialog_join";
if (unread_count != 0 && list.is_message_unread_count_inited_) { if (unread_count != 0 && list.is_message_unread_count_inited_) {
if (had_unread_counter) { unread_count *= delta;
unread_count = -unread_count;
} else {
CHECK(has_unread_counter);
}
list.unread_message_total_count_ += unread_count; list.unread_message_total_count_ += unread_count;
if (is_dialog_muted(d)) { if (is_dialog_muted(d)) {
list.unread_message_muted_count_ += unread_count; list.unread_message_muted_count_ += unread_count;
} }
send_update_unread_message_count(d->folder_id, dialog_id, true, change_source); send_update_unread_message_count(dialog_list_id, dialog_id, true, change_source);
} }
if ((unread_count != 0 || d->is_marked_as_unread) && list.is_dialog_unread_count_inited_) { if ((unread_count != 0 || d->is_marked_as_unread) && list.is_dialog_unread_count_inited_) {
int delta = 1;
if (had_unread_counter) {
delta = -1;
} else {
CHECK(has_unread_counter);
}
list.unread_dialog_total_count_ += delta; list.unread_dialog_total_count_ += delta;
if (unread_count == 0 && d->is_marked_as_unread) { if (unread_count == 0 && d->is_marked_as_unread) {
list.unread_dialog_marked_count_ += delta; list.unread_dialog_marked_count_ += delta;
@ -28865,63 +28886,40 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
list.unread_dialog_muted_marked_count_ += delta; list.unread_dialog_muted_marked_count_ += delta;
} }
} }
need_update_unread_chat_count = false;
send_update_unread_chat_count(d->folder_id, dialog_id, true, change_source);
} }
// always send update unread chat count, because total dialog count could change
send_update_unread_chat_count(dialog_list_id, dialog_id, true, change_source);
}
if (!is_loaded_from_database && dialog_list_id == d->folder_id) {
auto dialog_type = dialog_id.get_type(); auto dialog_type = dialog_id.get_type();
if (dialog_type == DialogType::Channel && has_unread_counter && being_added_dialog_id_ != dialog_id) { if (dialog_type == DialogType::Channel && is_in_list && being_added_dialog_id_ != dialog_id) {
repair_channel_server_unread_count(d); repair_channel_server_unread_count(d);
LOG(INFO) << "Schedule getDifference in " << dialog_id.get_channel_id(); LOG(INFO) << "Schedule getDifference in " << dialog_id.get_channel_id();
channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), 0.001); channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), 0.001);
} }
if (dialog_type == DialogType::Channel && !has_unread_counter) { if (dialog_type == DialogType::Channel && was_in_list) {
remove_all_dialog_notifications(d, false, "set_dialog_order 1"); remove_all_dialog_notifications(d, false, "update_dialog_lists 1");
remove_all_dialog_notifications(d, true, "set_dialog_order 2"); remove_all_dialog_notifications(d, true, "update_dialog_lists 2");
clear_active_dialog_actions(dialog_id); clear_active_dialog_actions(dialog_id);
} }
} }
if (list.is_dialog_unread_count_inited_ && need_update_unread_chat_count) {
send_update_unread_chat_count(d->folder_id, dialog_id, true, "changed total_count");
}
if (add_to_hints) { if (was_in_list) {
update_dialogs_hints(d); bool is_removed = td::remove(d->dialog_list_ids, dialog_list_id);
} CHECK(is_removed);
update_dialogs_hints_rating(d); } else {
d->dialog_list_ids.push_back(dialog_list_id);
auto new_public_order = get_dialog_public_order(&list, d);
if (is_removed_from_folder && d->folder_id != FolderId::main()) {
if (new_public_order != old_public_order) {
send_update_chat_position(d->folder_id, d);
old_public_order = new_public_order;
}
d->folder_id = FolderId::main();
d->is_folder_id_inited = true;
on_dialog_updated(d->dialog_id, "set_dialog_order 5");
if (is_dialog_sponsored(d)) {
auto &main_list = get_dialog_list(d->folder_id);
if (main_list.is_dialog_unread_count_inited_) {
send_update_unread_chat_count(d->folder_id, DialogId(), true, "set_dialog_order 6");
}
} }
} }
if (was_sponsored != is_dialog_sponsored(d)) { if (!is_loaded_from_database && !old_order.is_sponsored && new_order.is_sponsored) {
send_update_chat_position(FolderId::main(), d); // a chat is sponsored only if user isn't a chat member
if (!is_loaded_from_database && !was_sponsored) { remove_all_dialog_notifications(d, false, "update_dialog_lists 3");
// channel is sponsored only if user isn't a channel member remove_all_dialog_notifications(d, true, "update_dialog_lists 4");
remove_all_dialog_notifications(d, false, "set_dialog_order 3");
remove_all_dialog_notifications(d, true, "set_dialog_order 4");
} }
old_public_order = new_public_order;
} }
if (old_public_order != new_public_order && need_send_update_chat_order) {
send_update_chat_position(d->folder_id, d);
}
return true;
} }
void MessagesManager::update_last_dialog_date(FolderId folder_id) { void MessagesManager::update_last_dialog_date(FolderId folder_id) {
@ -29097,10 +29095,35 @@ MessagesManager::Dialog *MessagesManager::on_load_dialog_from_database(DialogId
return add_new_dialog(parse_dialog(dialog_id, value), true); return add_new_dialog(parse_dialog(dialog_id, value), true);
} }
MessagesManager::DialogOrderInList MessagesManager::get_dialog_order_in_list(const DialogList *list,
const Dialog *d) const {
CHECK(!td_->auth_manager_->is_bot());
CHECK(list != nullptr);
CHECK(d != nullptr);
DialogOrderInList order;
order.order = d->order;
order.private_order = get_dialog_private_order(list, d);
order.public_order =
DialogDate(order.private_order, d->dialog_id) <= list->last_dialog_date_ ? order.private_order : 0;
order.is_pinned = get_dialog_pinned_order(list, d->dialog_id) != DEFAULT_ORDER;
order.is_sponsored = order.private_order != 0 && is_dialog_sponsored(d);
return order;
}
std::unordered_map<FolderId, MessagesManager::DialogOrderInList, FolderIdHash> MessagesManager::get_dialog_orders(
const Dialog *d) const {
CHECK(d != nullptr);
std::unordered_map<FolderId, MessagesManager::DialogOrderInList, FolderIdHash> orders;
if (!td_->auth_manager_->is_bot()) {
for (auto &dialog_list_id : d->dialog_list_ids) {
orders.emplace(dialog_list_id, get_dialog_order_in_list(get_dialog_list(dialog_list_id), d));
}
}
return orders;
}
vector<FolderId> MessagesManager::get_dialog_list_ids(const Dialog *d) { vector<FolderId> MessagesManager::get_dialog_list_ids(const Dialog *d) {
vector<FolderId> dialog_list_ids; return d->dialog_list_ids;
dialog_list_ids.push_back(d->folder_id);
return dialog_list_ids;
} }
MessagesManager::DialogListView MessagesManager::get_dialog_lists(const Dialog *d) { MessagesManager::DialogListView MessagesManager::get_dialog_lists(const Dialog *d) {
@ -29603,9 +29626,8 @@ void MessagesManager::on_get_channel_difference(
set_dialog_folder_id(d, FolderId((dialog->flags_ & DIALOG_FLAG_HAS_FOLDER_ID) != 0 ? dialog->folder_id_ : 0)); set_dialog_folder_id(d, FolderId((dialog->flags_ & DIALOG_FLAG_HAS_FOLDER_ID) != 0 ? dialog->folder_id_ : 0));
on_update_dialog_notify_settings(dialog_id, std::move(dialog->notify_settings_), "on_get_dialogs"); on_update_dialog_notify_settings(dialog_id, std::move(dialog->notify_settings_),
"updates.channelDifferenceTooLong");
set_dialog_is_pinned(d->folder_id, d, (dialog->flags_ & DIALOG_FLAG_IS_PINNED) != 0);
bool is_marked_as_unread = (dialog->flags_ & telegram_api::dialog::UNREAD_MARK_MASK) != 0; bool is_marked_as_unread = (dialog->flags_ & telegram_api::dialog::UNREAD_MARK_MASK) != 0;
if (is_marked_as_unread != d->is_marked_as_unread) { if (is_marked_as_unread != d->is_marked_as_unread) {
@ -29619,7 +29641,10 @@ void MessagesManager::on_get_channel_difference(
MessageId(ServerMessageId(dialog->read_inbox_max_id_)), dialog->unread_count_, MessageId(ServerMessageId(dialog->read_inbox_max_id_)), dialog->unread_count_,
dialog->unread_mentions_count_, MessageId(ServerMessageId(dialog->read_outbox_max_id_)), dialog->unread_mentions_count_, MessageId(ServerMessageId(dialog->read_outbox_max_id_)),
std::move(difference->messages_)); std::move(difference->messages_));
need_update_dialog_pos = true; update_dialog_pos(d, "updates.channelDifferenceTooLong");
// set is_pinned only after updating dialog pos to ensure that order is initialized
set_dialog_is_pinned(d->folder_id, d, (dialog->flags_ & DIALOG_FLAG_IS_PINNED) != 0);
set_channel_pts(d, new_pts, "channel difference too long"); set_channel_pts(d, new_pts, "channel difference too long");
break; break;

View File

@ -1055,7 +1055,9 @@ class MessagesManager : public Actor {
uint64 read_history_logevent_id_generation = 0; uint64 read_history_logevent_id_generation = 0;
uint64 set_folder_id_logevent_id = 0; uint64 set_folder_id_logevent_id = 0;
uint64 set_folder_id_logevent_id_generation = 0; uint64 set_folder_id_logevent_id_generation = 0;
FolderId folder_id; FolderId folder_id;
vector<FolderId> dialog_list_ids; // TODO replace with mask
MessageId MessageId
last_read_all_mentions_message_id; // all mentions with a message identifier not greater than it are implicitly read last_read_all_mentions_message_id; // all mentions with a message identifier not greater than it are implicitly read
@ -1288,6 +1290,14 @@ class MessagesManager : public Actor {
} }
}; };
struct DialogOrderInList {
int64 order = DEFAULT_ORDER;
int64 private_order = 0;
int64 public_order = 0;
bool is_pinned = false;
bool is_sponsored = false;
};
class MessagesIteratorBase { class MessagesIteratorBase {
vector<const Message *> stack_; vector<const Message *> stack_;
@ -2046,7 +2056,7 @@ class MessagesManager : public Actor {
static vector<DialogId> remove_secret_chat_dialog_ids(vector<DialogId> dialog_ids); static vector<DialogId> remove_secret_chat_dialog_ids(vector<DialogId> dialog_ids);
bool set_dialog_is_pinned(FolderId folder_id, Dialog *d, bool is_pinned); bool set_dialog_is_pinned(FolderId folder_id, Dialog *d, bool is_pinned, bool need_update_dialog_lists = true);
void set_dialog_is_marked_as_unread(Dialog *d, bool is_marked_as_unread); void set_dialog_is_marked_as_unread(Dialog *d, bool is_marked_as_unread);
@ -2164,6 +2174,10 @@ class MessagesManager : public Actor {
void update_dialogs_hints(const Dialog *d); void update_dialogs_hints(const Dialog *d);
void update_dialogs_hints_rating(const Dialog *d); void update_dialogs_hints_rating(const Dialog *d);
DialogOrderInList get_dialog_order_in_list(const DialogList *list, const Dialog *d) const;
std::unordered_map<FolderId, DialogOrderInList, FolderIdHash> get_dialog_orders(const Dialog *d) const;
vector<FolderId> get_dialog_list_ids(const Dialog *d); vector<FolderId> get_dialog_list_ids(const Dialog *d);
DialogListView get_dialog_lists(const Dialog *d); DialogListView get_dialog_lists(const Dialog *d);
@ -2323,10 +2337,6 @@ class MessagesManager : public Actor {
int64 get_dialog_private_order(const DialogList *list, const Dialog *d) const; int64 get_dialog_private_order(const DialogList *list, const Dialog *d) const;
int64 get_dialog_public_order(FolderId folder_id, const Dialog *d) const;
int64 get_dialog_public_order(const DialogList *list, const Dialog *d) const;
td_api::object_ptr<td_api::chatPosition> get_chat_position_object(FolderId folder_id, const Dialog *d) const; td_api::object_ptr<td_api::chatPosition> get_chat_position_object(FolderId folder_id, const Dialog *d) const;
vector<td_api::object_ptr<td_api::chatPosition>> get_chat_positions_object(const Dialog *d) const; vector<td_api::object_ptr<td_api::chatPosition>> get_chat_positions_object(const Dialog *d) const;
@ -2359,12 +2369,15 @@ class MessagesManager : public Actor {
bool is_removed_from_dialog_list(const Dialog *d) const; bool is_removed_from_dialog_list(const Dialog *d) const;
void update_dialog_pos(Dialog *d, const char *source, bool need_send_update_chat_order = true, void update_dialog_pos(Dialog *d, const char *source, bool need_send_update = true,
bool is_loaded_from_database = false); bool is_loaded_from_database = false);
bool set_dialog_order(Dialog *d, int64 new_order, bool need_send_update_chat_order, bool is_loaded_from_database, bool set_dialog_order(Dialog *d, int64 new_order, bool need_send_update, bool is_loaded_from_database,
const char *source); const char *source);
void update_dialog_lists(Dialog *d, std::unordered_map<FolderId, DialogOrderInList, FolderIdHash> &&old_orders,
bool need_send_update, bool is_loaded_from_database, const char *source);
void update_last_dialog_date(FolderId folder_id); void update_last_dialog_date(FolderId folder_id);
void load_notification_settings(); void load_notification_settings();

View File

@ -4430,6 +4430,7 @@ void Td::send_get_nearest_dc_query(Promise<string> promise) {
} }
void Td::send_update(tl_object_ptr<td_api::Update> &&object) { void Td::send_update(tl_object_ptr<td_api::Update> &&object) {
CHECK(object != nullptr);
auto object_id = object->get_id(); auto object_id = object->get_id();
if (close_flag_ >= 5 && object_id != td_api::updateAuthorizationState::ID) { if (close_flag_ >= 5 && object_id != td_api::updateAuthorizationState::ID) {
// just in case // just in case