Encapsulate TDLib state mutations
This commit is contained in:
@@ -104,11 +104,11 @@ rg -n "current_chat_messages_mut|chats_mut|folders_mut|pending_user_ids_mut|user
|
|||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
|
|
||||||
- [ ] Add focused methods on `TdClient` for common mutations: update chat, update message by id, queue pending user, update user cache, update folders.
|
- [x] Add focused methods on `TdClient` for common mutations: update chat, update message by id, queue pending user, update user cache, update folders.
|
||||||
- [ ] Replace raw `*_mut()` usage in helper/update modules with those methods.
|
- [x] Replace raw `*_mut()` usage in helper/update modules with those methods.
|
||||||
- [ ] Keep raw mutable access private to `TdClient` implementation where it is still needed.
|
- [x] Keep raw mutable access private to `TdClient` implementation where it is still needed.
|
||||||
- [ ] Add or update tests around message updates, user-cache updates, and chat-list updates.
|
- [x] Add or update tests around message updates, user-cache updates, and chat-list updates.
|
||||||
- [ ] Run `cargo test --all-features`.
|
- [x] Run `cargo test --all-features`.
|
||||||
|
|
||||||
Acceptance criteria:
|
Acceptance criteria:
|
||||||
|
|
||||||
|
|||||||
@@ -10,19 +10,12 @@ use tdlib_rs::enums::{Chat as TdChat, ChatList, ChatType};
|
|||||||
use super::client::TdClient;
|
use super::client::TdClient;
|
||||||
use super::types::ChatInfo;
|
use super::types::ChatInfo;
|
||||||
|
|
||||||
/// Находит мутабельную ссылку на чат по ID.
|
|
||||||
pub fn find_chat_mut(client: &mut TdClient, chat_id: ChatId) -> Option<&mut ChatInfo> {
|
|
||||||
client.chats_mut().iter_mut().find(|c| c.id == chat_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Обновляет поле чата, если чат найден.
|
/// Обновляет поле чата, если чат найден.
|
||||||
pub fn update_chat<F>(client: &mut TdClient, chat_id: ChatId, updater: F)
|
pub fn update_chat<F>(client: &mut TdClient, chat_id: ChatId, updater: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ChatInfo),
|
F: FnOnce(&mut ChatInfo),
|
||||||
{
|
{
|
||||||
if let Some(chat) = find_chat_mut(client, chat_id) {
|
client.update_chat(chat_id, updater);
|
||||||
updater(chat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Добавляет новый чат или обновляет существующий
|
/// Добавляет новый чат или обновляет существующий
|
||||||
@@ -33,9 +26,7 @@ pub fn add_or_update_chat(client: &mut TdClient, td_chat_enum: &TdChat) {
|
|||||||
// Пропускаем удалённые аккаунты
|
// Пропускаем удалённые аккаунты
|
||||||
if td_chat.title == "Deleted Account" || td_chat.title.is_empty() {
|
if td_chat.title == "Deleted Account" || td_chat.title.is_empty() {
|
||||||
// Удаляем из списка если уже был добавлен
|
// Удаляем из списка если уже был добавлен
|
||||||
client
|
client.remove_chat(ChatId::new(td_chat.id));
|
||||||
.chats_mut()
|
|
||||||
.retain(|c| c.id != ChatId::new(td_chat.id));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,22 +52,23 @@ pub fn add_or_update_chat(client: &mut TdClient, td_chat_enum: &TdChat) {
|
|||||||
ChatType::Private(private) => {
|
ChatType::Private(private) => {
|
||||||
// Ограничиваем размер chat_user_ids
|
// Ограничиваем размер chat_user_ids
|
||||||
let chat_id = ChatId::new(td_chat.id);
|
let chat_id = ChatId::new(td_chat.id);
|
||||||
if client.user_cache.chat_user_ids.len() >= MAX_CHAT_USER_IDS
|
let user_id = UserId::new(private.user_id);
|
||||||
&& !client.user_cache.chat_user_ids.contains_key(&chat_id)
|
client.update_user_cache(|cache| {
|
||||||
|
if cache.chat_user_ids.len() >= MAX_CHAT_USER_IDS
|
||||||
|
&& !cache.chat_user_ids.contains_key(&chat_id)
|
||||||
{
|
{
|
||||||
// Удаляем случайную запись (первую найденную)
|
// Удаляем случайную запись (первую найденную)
|
||||||
if let Some(&key) = client.user_cache.chat_user_ids.keys().next() {
|
if let Some(&key) = cache.chat_user_ids.keys().next() {
|
||||||
client.user_cache.chat_user_ids.remove(&key);
|
cache.chat_user_ids.remove(&key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let user_id = UserId::new(private.user_id);
|
cache.chat_user_ids.insert(chat_id, user_id);
|
||||||
client.user_cache.chat_user_ids.insert(chat_id, user_id);
|
|
||||||
// Проверяем, есть ли уже username в кэше (peek не обновляет LRU)
|
// Проверяем, есть ли уже username в кэше (peek не обновляет LRU)
|
||||||
client
|
cache
|
||||||
.user_cache
|
|
||||||
.user_usernames
|
.user_usernames
|
||||||
.peek(&user_id)
|
.peek(&user_id)
|
||||||
.map(|u| format!("@{}", u))
|
.map(|u| format!("@{}", u))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
@@ -110,44 +102,35 @@ pub fn add_or_update_chat(client: &mut TdClient, td_chat_enum: &TdChat) {
|
|||||||
draft_text: None,
|
draft_text: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(existing) = find_chat_mut(client, ChatId::new(td_chat.id)) {
|
let chat_info_for_update = chat_info.clone();
|
||||||
existing.title = chat_info.title;
|
let updated_existing = client.update_chat(ChatId::new(td_chat.id), |existing| {
|
||||||
existing.last_message = chat_info.last_message;
|
existing.title = chat_info_for_update.title;
|
||||||
existing.last_message_date = chat_info.last_message_date;
|
existing.last_message = chat_info_for_update.last_message;
|
||||||
existing.unread_count = chat_info.unread_count;
|
existing.last_message_date = chat_info_for_update.last_message_date;
|
||||||
existing.unread_mention_count = chat_info.unread_mention_count;
|
existing.unread_count = chat_info_for_update.unread_count;
|
||||||
existing.last_read_outbox_message_id = chat_info.last_read_outbox_message_id;
|
existing.unread_mention_count = chat_info_for_update.unread_mention_count;
|
||||||
existing.folder_ids = chat_info.folder_ids;
|
existing.last_read_outbox_message_id = chat_info_for_update.last_read_outbox_message_id;
|
||||||
existing.is_muted = chat_info.is_muted;
|
existing.folder_ids = chat_info_for_update.folder_ids;
|
||||||
|
existing.is_muted = chat_info_for_update.is_muted;
|
||||||
|
|
||||||
// Обновляем username если он появился
|
// Обновляем username если он появился
|
||||||
if let Some(username) = chat_info.username {
|
if let Some(username) = chat_info_for_update.username {
|
||||||
existing.username = Some(username);
|
existing.username = Some(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем позицию только если она пришла
|
// Обновляем позицию только если она пришла
|
||||||
if main_position.is_some() {
|
if main_position.is_some() {
|
||||||
existing.is_pinned = chat_info.is_pinned;
|
existing.is_pinned = chat_info_for_update.is_pinned;
|
||||||
existing.order = chat_info.order;
|
existing.order = chat_info_for_update.order;
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
client.chats_mut().push(chat_info);
|
|
||||||
|
if !updated_existing {
|
||||||
|
client.push_chat(chat_info);
|
||||||
// Ограничиваем количество чатов
|
// Ограничиваем количество чатов
|
||||||
if client.chats_mut().len() > MAX_CHATS {
|
client.trim_chats_to_max_by_order(MAX_CHATS);
|
||||||
// Удаляем чат с наименьшим order (наименее активный)
|
|
||||||
let Some(min_idx) = client
|
|
||||||
.chats()
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.min_by_key(|(_, c)| c.order)
|
|
||||||
.map(|(i, _)| i)
|
|
||||||
else {
|
|
||||||
return; // Нет чатов для удаления (не должно произойти)
|
|
||||||
};
|
|
||||||
client.chats_mut().remove(min_idx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сортируем чаты по order (TDLib order учитывает pinned и время)
|
// Сортируем чаты по order (TDLib order учитывает pinned и время)
|
||||||
client.chats_mut().sort_by(|a, b| b.order.cmp(&a.order));
|
client.sort_chats_by_order();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,8 @@ impl TdClient {
|
|||||||
self.notification_manager.set_enabled(config.enabled);
|
self.notification_manager.set_enabled(config.enabled);
|
||||||
self.notification_manager
|
self.notification_manager
|
||||||
.set_only_mentions(config.only_mentions);
|
.set_only_mentions(config.only_mentions);
|
||||||
self.notification_manager.set_show_preview(config.show_preview);
|
self.notification_manager
|
||||||
|
.set_show_preview(config.show_preview);
|
||||||
self.notification_manager.set_timeout(config.timeout_ms);
|
self.notification_manager.set_timeout(config.timeout_ms);
|
||||||
self.notification_manager
|
self.notification_manager
|
||||||
.set_urgency(config.urgency.clone());
|
.set_urgency(config.urgency.clone());
|
||||||
@@ -433,24 +434,117 @@ impl TdClient {
|
|||||||
&self.chat_manager.chats
|
&self.chat_manager.chats
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chats_mut(&mut self) -> &mut Vec<ChatInfo> {
|
pub fn update_chats<F, R>(&mut self, updater: F) -> R
|
||||||
&mut self.chat_manager.chats
|
where
|
||||||
|
F: FnOnce(&mut Vec<ChatInfo>) -> R,
|
||||||
|
{
|
||||||
|
updater(&mut self.chat_manager.chats)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_chat<F>(&mut self, chat_id: ChatId, updater: F) -> bool
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut ChatInfo),
|
||||||
|
{
|
||||||
|
let Some(chat) = self.chat_manager.chats.iter_mut().find(|c| c.id == chat_id) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
updater(chat);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_chat(&mut self, chat_id: ChatId) {
|
||||||
|
self.chat_manager.chats.retain(|c| c.id != chat_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_chat(&mut self, chat: ChatInfo) {
|
||||||
|
self.chat_manager.chats.push(chat);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trim_chats_to_max_by_order(&mut self, max_chats: usize) {
|
||||||
|
if self.chat_manager.chats.len() <= max_chats {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(min_idx) = self
|
||||||
|
.chat_manager
|
||||||
|
.chats
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.min_by_key(|(_, chat)| chat.order)
|
||||||
|
.map(|(idx, _)| idx)
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.chat_manager.chats.remove(min_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sort_chats_by_order(&mut self) {
|
||||||
|
self.chat_manager
|
||||||
|
.chats
|
||||||
|
.sort_by(|a, b| b.order.cmp(&a.order));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn folders(&self) -> &[FolderInfo] {
|
pub fn folders(&self) -> &[FolderInfo] {
|
||||||
&self.chat_manager.folders
|
&self.chat_manager.folders
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn folders_mut(&mut self) -> &mut Vec<FolderInfo> {
|
pub fn update_folders<F, R>(&mut self, updater: F) -> R
|
||||||
&mut self.chat_manager.folders
|
where
|
||||||
|
F: FnOnce(&mut Vec<FolderInfo>) -> R,
|
||||||
|
{
|
||||||
|
updater(&mut self.chat_manager.folders)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_folders(&mut self, folders: Vec<FolderInfo>) {
|
||||||
|
self.chat_manager.folders = folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_chat_messages(&self) -> &[MessageInfo] {
|
pub fn current_chat_messages(&self) -> &[MessageInfo] {
|
||||||
&self.message_manager.current_chat_messages
|
&self.message_manager.current_chat_messages
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_chat_messages_mut(&mut self) -> &mut Vec<MessageInfo> {
|
pub fn clear_current_chat_messages(&mut self) {
|
||||||
&mut self.message_manager.current_chat_messages
|
self.message_manager.current_chat_messages.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_current_chat_messages(&mut self, messages: Vec<MessageInfo>) {
|
||||||
|
self.message_manager.current_chat_messages = messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_current_chat_messages<F, R>(&mut self, updater: F) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Vec<MessageInfo>) -> R,
|
||||||
|
{
|
||||||
|
updater(&mut self.message_manager.current_chat_messages)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_current_chat_message<F>(&mut self, message_id: MessageId, updater: F) -> bool
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut MessageInfo),
|
||||||
|
{
|
||||||
|
let Some(message) = self
|
||||||
|
.message_manager
|
||||||
|
.current_chat_messages
|
||||||
|
.iter_mut()
|
||||||
|
.find(|message| message.id() == message_id)
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
updater(message);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace_current_chat_message(
|
||||||
|
&mut self,
|
||||||
|
message_id: MessageId,
|
||||||
|
new_message: MessageInfo,
|
||||||
|
) -> bool {
|
||||||
|
self.update_current_chat_message(message_id, |message| {
|
||||||
|
*message = new_message;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_chat_id(&self) -> Option<ChatId> {
|
pub fn current_chat_id(&self) -> Option<ChatId> {
|
||||||
@@ -498,8 +592,10 @@ impl TdClient {
|
|||||||
&self.user_cache.pending_user_ids
|
&self.user_cache.pending_user_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pending_user_ids_mut(&mut self) -> &mut Vec<crate::types::UserId> {
|
pub fn queue_pending_user_id(&mut self, user_id: crate::types::UserId) {
|
||||||
&mut self.user_cache.pending_user_ids
|
if !self.user_cache.pending_user_ids.contains(&user_id) {
|
||||||
|
self.user_cache.pending_user_ids.push(user_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_chat_list_position(&self) -> i32 {
|
pub fn main_chat_list_position(&self) -> i32 {
|
||||||
@@ -515,8 +611,11 @@ impl TdClient {
|
|||||||
&self.user_cache
|
&self.user_cache
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_cache_mut(&mut self) -> &mut UserCache {
|
pub fn update_user_cache<F, R>(&mut self, updater: F) -> R
|
||||||
&mut self.user_cache
|
where
|
||||||
|
F: FnOnce(&mut UserCache) -> R,
|
||||||
|
{
|
||||||
|
updater(&mut self.user_cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Helper методы для упрощения обработки updates ====================
|
// ==================== Helper методы для упрощения обработки updates ====================
|
||||||
@@ -558,7 +657,7 @@ impl TdClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Пересортируем по order
|
// Пересортируем по order
|
||||||
self.chats_mut().sort_by(|a, b| b.order.cmp(&a.order));
|
self.sort_chats_by_order();
|
||||||
}
|
}
|
||||||
Update::ChatReadInbox(update) => {
|
Update::ChatReadInbox(update) => {
|
||||||
crate::tdlib::chat_helpers::update_chat(
|
crate::tdlib::chat_helpers::update_chat(
|
||||||
@@ -600,11 +699,13 @@ impl TdClient {
|
|||||||
);
|
);
|
||||||
// Если это текущий открытый чат — обновляем is_read у сообщений
|
// Если это текущий открытый чат — обновляем is_read у сообщений
|
||||||
if Some(ChatId::new(update.chat_id)) == self.current_chat_id() {
|
if Some(ChatId::new(update.chat_id)) == self.current_chat_id() {
|
||||||
for msg in self.current_chat_messages_mut().iter_mut() {
|
self.update_current_chat_messages(|messages| {
|
||||||
|
for msg in messages {
|
||||||
if msg.is_outgoing() && msg.id() <= last_read_msg_id {
|
if msg.is_outgoing() && msg.id() <= last_read_msg_id {
|
||||||
msg.state.is_read = true;
|
msg.state.is_read = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Update::ChatPosition(update) => {
|
Update::ChatPosition(update) => {
|
||||||
@@ -618,11 +719,13 @@ impl TdClient {
|
|||||||
}
|
}
|
||||||
Update::ChatFolders(update) => {
|
Update::ChatFolders(update) => {
|
||||||
// Обновляем список папок
|
// Обновляем список папок
|
||||||
*self.folders_mut() = update
|
self.set_folders(
|
||||||
|
update
|
||||||
.chat_folders
|
.chat_folders
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| FolderInfo { id: f.id, name: f.title })
|
.map(|f| FolderInfo { id: f.id, name: f.title })
|
||||||
.collect();
|
.collect(),
|
||||||
|
);
|
||||||
self.set_main_chat_list_position(update.main_chat_list_position);
|
self.set_main_chat_list_position(update.main_chat_list_position);
|
||||||
}
|
}
|
||||||
Update::UserStatus(update) => {
|
Update::UserStatus(update) => {
|
||||||
@@ -635,9 +738,11 @@ impl TdClient {
|
|||||||
UserStatus::LastMonth(_) => UserOnlineStatus::LastMonth,
|
UserStatus::LastMonth(_) => UserOnlineStatus::LastMonth,
|
||||||
UserStatus::Empty => UserOnlineStatus::LongTimeAgo,
|
UserStatus::Empty => UserOnlineStatus::LongTimeAgo,
|
||||||
};
|
};
|
||||||
self.user_cache
|
self.update_user_cache(|cache| {
|
||||||
|
cache
|
||||||
.user_statuses
|
.user_statuses
|
||||||
.insert(UserId::new(update.user_id), status);
|
.insert(UserId::new(update.user_id), status);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Update::ConnectionState(update) => {
|
Update::ConnectionState(update) => {
|
||||||
// Обновляем состояние сетевого соединения
|
// Обновляем состояние сетевого соединения
|
||||||
|
|||||||
@@ -70,14 +70,14 @@ impl ChatClient for TdClient {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&mut Vec<ChatInfo>),
|
F: FnOnce(&mut Vec<ChatInfo>),
|
||||||
{
|
{
|
||||||
updater(self.chats_mut());
|
TdClient::update_chats(self, updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_folders<F>(&mut self, updater: F)
|
fn update_folders<F>(&mut self, updater: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Vec<FolderInfo>),
|
F: FnOnce(&mut Vec<FolderInfo>),
|
||||||
{
|
{
|
||||||
updater(self.folders_mut());
|
TdClient::update_folders(self, updater);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,18 +204,18 @@ impl MessageClient for TdClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn clear_current_chat_messages(&mut self) {
|
fn clear_current_chat_messages(&mut self) {
|
||||||
self.current_chat_messages_mut().clear()
|
TdClient::clear_current_chat_messages(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_current_chat_messages(&mut self, messages: Vec<MessageInfo>) {
|
fn set_current_chat_messages(&mut self, messages: Vec<MessageInfo>) {
|
||||||
*self.current_chat_messages_mut() = messages;
|
TdClient::set_current_chat_messages(self, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_current_chat_messages<F>(&mut self, updater: F)
|
fn update_current_chat_messages<F>(&mut self, updater: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut Vec<MessageInfo>),
|
F: FnOnce(&mut Vec<MessageInfo>),
|
||||||
{
|
{
|
||||||
updater(self.current_chat_messages_mut());
|
TdClient::update_current_chat_messages(self, updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_current_chat_id(&mut self, chat_id: Option<ChatId>) {
|
fn set_current_chat_id(&mut self, chat_id: Option<ChatId>) {
|
||||||
@@ -253,7 +253,7 @@ impl UserClient for TdClient {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&mut UserCache),
|
F: FnOnce(&mut UserCache),
|
||||||
{
|
{
|
||||||
updater(self.user_cache_mut());
|
TdClient::update_user_cache(self, updater);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_pending_user_ids(&mut self) {
|
async fn process_pending_user_ids(&mut self) {
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ pub fn convert_message(client: &mut TdClient, message: &TdMessage, chat_id: Chat
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
// Добавляем в очередь для загрузки
|
// Добавляем в очередь для загрузки
|
||||||
if !client.pending_user_ids().contains(&user_id) {
|
client.queue_pending_user_id(user_id);
|
||||||
client.pending_user_ids_mut().push(user_id);
|
|
||||||
}
|
|
||||||
format!("User_{}", user_id.as_i64())
|
format!("User_{}", user_id.as_i64())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -210,7 +208,8 @@ pub fn update_reply_info_from_loaded_messages(client: &mut TdClient) {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Обновляем reply_to для сообщений с неполными данными
|
// Обновляем reply_to для сообщений с неполными данными
|
||||||
for msg in client.current_chat_messages_mut().iter_mut() {
|
client.update_current_chat_messages(|messages| {
|
||||||
|
for msg in messages {
|
||||||
let Some(ref mut reply) = msg.interactions.reply_to else {
|
let Some(ref mut reply) = msg.interactions.reply_to else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@@ -231,4 +230,5 @@ pub fn update_reply_info_from_loaded_messages(client: &mut TdClient) {
|
|||||||
reply.text = content.clone();
|
reply.text = content.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,17 +54,19 @@ pub fn handle_new_message_update(client: &mut TdClient, new_msg: UpdateNewMessag
|
|||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
// Сообщение уже есть - обновляем
|
// Сообщение уже есть - обновляем
|
||||||
if is_incoming {
|
if is_incoming {
|
||||||
client.current_chat_messages_mut()[idx] = msg_info;
|
client.replace_current_chat_message(msg_id, msg_info);
|
||||||
} else {
|
} else {
|
||||||
// Для исходящих: обновляем can_be_edited и другие поля,
|
// Для исходящих: обновляем can_be_edited и другие поля,
|
||||||
// но сохраняем reply_to (добавленный при отправке)
|
// но сохраняем reply_to (добавленный при отправке)
|
||||||
let existing = &mut client.current_chat_messages_mut()[idx];
|
client.update_current_chat_messages(|messages| {
|
||||||
|
let existing = &mut messages[idx];
|
||||||
existing.state.can_be_edited = msg_info.state.can_be_edited;
|
existing.state.can_be_edited = msg_info.state.can_be_edited;
|
||||||
existing.state.can_be_deleted_only_for_self =
|
existing.state.can_be_deleted_only_for_self =
|
||||||
msg_info.state.can_be_deleted_only_for_self;
|
msg_info.state.can_be_deleted_only_for_self;
|
||||||
existing.state.can_be_deleted_for_all_users =
|
existing.state.can_be_deleted_for_all_users =
|
||||||
msg_info.state.can_be_deleted_for_all_users;
|
msg_info.state.can_be_deleted_for_all_users;
|
||||||
existing.state.is_read = msg_info.state.is_read;
|
existing.state.is_read = msg_info.state.is_read;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -122,7 +124,7 @@ pub fn handle_chat_position_update(client: &mut TdClient, update: UpdateChatPosi
|
|||||||
ChatList::Main => {
|
ChatList::Main => {
|
||||||
if update.position.order == 0 {
|
if update.position.order == 0 {
|
||||||
// Чат больше не в Main (перемещён в архив и т.д.)
|
// Чат больше не в Main (перемещён в архив и т.д.)
|
||||||
client.chats_mut().retain(|c| c.id != chat_id);
|
client.remove_chat(chat_id);
|
||||||
} else {
|
} else {
|
||||||
// Обновляем позицию существующего чата
|
// Обновляем позицию существующего чата
|
||||||
crate::tdlib::chat_helpers::update_chat(client, chat_id, |chat| {
|
crate::tdlib::chat_helpers::update_chat(client, chat_id, |chat| {
|
||||||
@@ -131,7 +133,7 @@ pub fn handle_chat_position_update(client: &mut TdClient, update: UpdateChatPosi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Пересортируем по order
|
// Пересортируем по order
|
||||||
client.chats_mut().sort_by(|a, b| b.order.cmp(&a.order));
|
client.sort_chats_by_order();
|
||||||
}
|
}
|
||||||
ChatList::Folder(folder) => {
|
ChatList::Folder(folder) => {
|
||||||
// Обновляем folder_ids для чата
|
// Обновляем folder_ids для чата
|
||||||
@@ -166,10 +168,10 @@ pub fn handle_user_update(client: &mut TdClient, update: UpdateUser) {
|
|||||||
// Удаляем чаты с этим пользователем из списка
|
// Удаляем чаты с этим пользователем из списка
|
||||||
let user_id = user.id;
|
let user_id = user.id;
|
||||||
// Clone chat_user_ids to avoid borrow conflict
|
// Clone chat_user_ids to avoid borrow conflict
|
||||||
let chat_user_ids = client.user_cache.chat_user_ids.clone();
|
let chat_user_ids = client.user_cache().chat_user_ids.clone();
|
||||||
client
|
client.update_chats(|chats| {
|
||||||
.chats_mut()
|
chats.retain(|c| chat_user_ids.get(&c.id) != Some(&UserId::new(user_id)));
|
||||||
.retain(|c| chat_user_ids.get(&c.id) != Some(&UserId::new(user_id)));
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,10 +181,9 @@ pub fn handle_user_update(client: &mut TdClient, update: UpdateUser) {
|
|||||||
} else {
|
} else {
|
||||||
format!("{} {}", user.first_name, user.last_name)
|
format!("{} {}", user.first_name, user.last_name)
|
||||||
};
|
};
|
||||||
client
|
client.update_user_cache(|cache| {
|
||||||
.user_cache
|
cache.user_names.insert(UserId::new(user.id), display_name);
|
||||||
.user_names
|
});
|
||||||
.insert(UserId::new(user.id), display_name);
|
|
||||||
|
|
||||||
// Сохраняем username если есть (с упрощённым извлечением через and_then)
|
// Сохраняем username если есть (с упрощённым извлечением через and_then)
|
||||||
if let Some(username) = user
|
if let Some(username) = user
|
||||||
@@ -190,19 +191,25 @@ pub fn handle_user_update(client: &mut TdClient, update: UpdateUser) {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|u| u.active_usernames.first())
|
.and_then(|u| u.active_usernames.first())
|
||||||
{
|
{
|
||||||
client
|
let affected_chat_ids = client.update_user_cache(|cache| {
|
||||||
.user_cache
|
cache
|
||||||
.user_usernames
|
.user_usernames
|
||||||
.insert(UserId::new(user.id), username.to_string());
|
.insert(UserId::new(user.id), username.to_string());
|
||||||
|
cache
|
||||||
|
.chat_user_ids
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(&chat_id, &user_id)| {
|
||||||
|
(user_id == UserId::new(user.id)).then_some(chat_id)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
// Обновляем username в чатах, связанных с этим пользователем
|
// Обновляем username в чатах, связанных с этим пользователем
|
||||||
for (&chat_id, &user_id) in &client.user_cache.chat_user_ids.clone() {
|
for chat_id in affected_chat_ids {
|
||||||
if user_id == UserId::new(user.id) {
|
|
||||||
crate::tdlib::chat_helpers::update_chat(client, chat_id, |chat| {
|
crate::tdlib::chat_helpers::update_chat(client, chat_id, |chat| {
|
||||||
chat.username = Some(format!("@{}", username));
|
chat.username = Some(format!("@{}", username));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// LRU-кэш автоматически удаляет старые записи при вставке
|
// LRU-кэш автоматически удаляет старые записи при вставке
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,16 +225,8 @@ pub fn handle_message_interaction_info_update(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(msg) = client
|
|
||||||
.current_chat_messages_mut()
|
|
||||||
.iter_mut()
|
|
||||||
.find(|m| m.id() == MessageId::new(update.message_id))
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Извлекаем реакции из interaction_info
|
// Извлекаем реакции из interaction_info
|
||||||
msg.interactions.reactions = update
|
let reactions = update
|
||||||
.interaction_info
|
.interaction_info
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|info| info.reactions.as_ref())
|
.and_then(|info| info.reactions.as_ref())
|
||||||
@@ -250,6 +249,9 @@ pub fn handle_message_interaction_info_update(
|
|||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
client.update_current_chat_message(MessageId::new(update.message_id), |msg| {
|
||||||
|
msg.interactions.reactions = reactions;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Обрабатывает Update::MessageSendSucceeded - успешная отправка сообщения.
|
/// Обрабатывает Update::MessageSendSucceeded - успешная отправка сообщения.
|
||||||
@@ -291,7 +293,7 @@ pub fn handle_message_send_succeeded_update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Заменяем старое сообщение на новое
|
// Заменяем старое сообщение на новое
|
||||||
client.current_chat_messages_mut()[idx] = new_msg;
|
client.replace_current_chat_message(old_id, new_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Обрабатывает Update::ChatDraftMessage - обновление черновика сообщения в чате.
|
/// Обрабатывает Update::ChatDraftMessage - обновление черновика сообщения в чате.
|
||||||
|
|||||||
Reference in New Issue
Block a user