This commit is contained in:
Mikhail Kilin
2026-01-31 03:48:50 +03:00
parent 1bf9b3d703
commit 644e36597d
37 changed files with 1070 additions and 600 deletions

View File

@@ -292,27 +292,27 @@ impl TdClient {
self.message_manager.current_pinned_message = msg;
}
pub fn typing_status(&self) -> Option<&(i64, String, std::time::Instant)> {
pub fn typing_status(&self) -> Option<&(crate::types::UserId, String, std::time::Instant)> {
self.chat_manager.typing_status.as_ref()
}
pub fn set_typing_status(&mut self, status: Option<(i64, String, std::time::Instant)>) {
pub fn set_typing_status(&mut self, status: Option<(crate::types::UserId, String, std::time::Instant)>) {
self.chat_manager.typing_status = status;
}
pub fn pending_view_messages(&self) -> &[(i64, Vec<i64>)] {
pub fn pending_view_messages(&self) -> &[(crate::types::ChatId, Vec<crate::types::MessageId>)] {
&self.message_manager.pending_view_messages
}
pub fn pending_view_messages_mut(&mut self) -> &mut Vec<(i64, Vec<i64>)> {
pub fn pending_view_messages_mut(&mut self) -> &mut Vec<(crate::types::ChatId, Vec<crate::types::MessageId>)> {
&mut self.message_manager.pending_view_messages
}
pub fn pending_user_ids(&self) -> &[i64] {
pub fn pending_user_ids(&self) -> &[crate::types::UserId] {
&self.user_cache.pending_user_ids
}
pub fn pending_user_ids_mut(&mut self) -> &mut Vec<i64> {
pub fn pending_user_ids_mut(&mut self) -> &mut Vec<crate::types::UserId> {
&mut self.user_cache.pending_user_ids
}
@@ -470,8 +470,8 @@ impl TdClient {
let chat_id = ChatId::new(new_msg.message.chat_id);
if Some(chat_id) == self.current_chat_id() {
let msg_info = self.convert_message(&new_msg.message, chat_id);
let msg_id = msg_info.id;
let is_incoming = !msg_info.is_outgoing;
let msg_id = msg_info.id();
let is_incoming = !msg_info.is_outgoing();
// Проверяем, есть ли уже сообщение с таким id
let existing_idx = self
@@ -488,12 +488,12 @@ impl TdClient {
// Для исходящих: обновляем can_be_edited и другие поля,
// но сохраняем reply_to (добавленный при отправке)
let existing = &mut self.current_chat_messages_mut()[idx];
existing.can_be_edited = msg_info.can_be_edited;
existing.can_be_deleted_only_for_self =
msg_info.can_be_deleted_only_for_self;
existing.can_be_deleted_for_all_users =
msg_info.can_be_deleted_for_all_users;
existing.is_read = msg_info.is_read;
existing.state.can_be_edited = msg_info.state.can_be_edited;
existing.state.can_be_deleted_only_for_self =
msg_info.state.can_be_deleted_only_for_self;
existing.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;
}
}
None => {
@@ -518,7 +518,7 @@ impl TdClient {
// Clone chat_user_ids to avoid borrow conflict
let chat_user_ids = self.user_cache.chat_user_ids.clone();
self.chats_mut()
.retain(|c| chat_user_ids.get(&c.id) != Some(&user_id));
.retain(|c| chat_user_ids.get(&c.id) != Some(&UserId::new(user_id)));
return;
}
@@ -528,15 +528,15 @@ impl TdClient {
} else {
format!("{} {}", user.first_name, user.last_name)
};
self.user_cache.user_names.insert(user.id, display_name);
self.user_cache.user_names.insert(UserId::new(user.id), display_name);
// Сохраняем username если есть
if let Some(usernames) = user.usernames {
if let Some(username) = usernames.active_usernames.first() {
self.user_cache.user_usernames.insert(user.id, username.clone());
self.user_cache.user_usernames.insert(UserId::new(user.id), username.clone());
// Обновляем username в чатах, связанных с этим пользователем
for (&chat_id, &user_id) in &self.user_cache.chat_user_ids.clone() {
if user_id == user.id {
if user_id == UserId::new(user.id) {
if let Some(chat) = self.chats_mut().iter_mut().find(|c| c.id == chat_id)
{
chat.username = Some(format!("@{}", username));
@@ -991,20 +991,20 @@ impl TdClient {
match origin {
MessageOrigin::User(u) => self
.user_cache.user_names
.peek(&u.sender_user_id)
.peek(&UserId::new(u.sender_user_id))
.cloned()
.unwrap_or_else(|| format!("User_{}", u.sender_user_id)),
MessageOrigin::Chat(c) => self
.chats()
.iter()
.find(|chat| chat.id == c.sender_chat_id)
.find(|chat| chat.id == ChatId::new(c.sender_chat_id))
.map(|chat| chat.title.clone())
.unwrap_or_else(|| "Чат".to_string()),
MessageOrigin::HiddenUser(h) => h.sender_name.clone(),
MessageOrigin::Channel(c) => self
.chats()
.iter()
.find(|chat| chat.id == c.chat_id)
.find(|chat| chat.id == ChatId::new(c.chat_id))
.map(|chat| chat.title.clone())
.unwrap_or_else(|| "Канал".to_string()),
}
@@ -1017,15 +1017,15 @@ impl TdClient {
let msg_data: std::collections::HashMap<i64, (String, String)> = self
.current_chat_messages()
.iter()
.map(|m| (m.id(), (m.sender_name().to_string(), m.text().to_string())))
.map(|m| (m.id().as_i64(), (m.sender_name().to_string(), m.text().to_string())))
.collect();
// Обновляем reply_to для сообщений с неполными данными
for msg in self.current_chat_messages_mut().iter_mut() {
if let Some(ref mut reply) = msg.reply_to {
if let Some(ref mut reply) = msg.interactions.reply_to {
// Если sender_name = "..." или text пустой — пробуем заполнить
if reply.sender_name == "..." || reply.text.is_empty() {
if let Some((sender, content)) = msg_data.get(&reply.message_id) {
if let Some((sender, content)) = msg_data.get(&reply.message_id.as_i64()) {
if reply.sender_name == "..." {
reply.sender_name = sender.clone();
}

View File

@@ -4,7 +4,7 @@ use tdlib_rs::enums::{ChatAction, InputMessageContent, InputMessageReplyTo, Mess
use tdlib_rs::functions;
use tdlib_rs::types::{Chat as TdChat, FormattedText, InputMessageReplyToMessage, InputMessageText, Message as TdMessage, TextEntity, TextParseModeMarkdown};
use super::types::{ForwardInfo, MessageInfo, ReactionInfo, ReplyInfo};
use super::types::{ForwardInfo, MessageBuilder, MessageInfo, ReactionInfo, ReplyInfo};
/// Менеджер сообщений
pub struct MessageManager {
@@ -375,7 +375,8 @@ impl MessageManager {
let batch = std::mem::take(&mut self.pending_view_messages);
for (chat_id, message_ids) in batch {
let _ = functions::view_messages(chat_id, message_ids, None, true, self.client_id).await;
let ids: Vec<i64> = message_ids.iter().map(|id| id.as_i64()).collect();
let _ = functions::view_messages(chat_id.as_i64(), ids, None, true, self.client_id).await;
}
}
@@ -454,7 +455,7 @@ impl MessageManager {
if let tdlib_rs::enums::MessageReplyTo::Message(reply_msg) = reply_to {
// Здесь можно загрузить информацию об оригинальном сообщении
Some(ReplyInfo {
message_id: reply_msg.message_id,
message_id: MessageId::new(reply_msg.message_id),
sender_name: "Unknown".to_string(),
text: "...".to_string(),
})
@@ -488,22 +489,48 @@ impl MessageManager {
})
.unwrap_or_default();
Some(MessageInfo {
id: msg.id,
sender_name,
is_outgoing: msg.is_outgoing,
content: content_text,
entities,
date: msg.date,
edit_date: msg.edit_date,
is_read: !msg.contains_unread_mention,
can_be_edited: msg.can_be_edited,
can_be_deleted_only_for_self: msg.can_be_deleted_only_for_self,
can_be_deleted_for_all_users: msg.can_be_deleted_for_all_users,
reply_to,
forward_from,
reactions,
})
let mut builder = MessageBuilder::new(MessageId::new(msg.id))
.sender_name(sender_name)
.text(content_text)
.entities(entities)
.date(msg.date)
.edit_date(msg.edit_date);
if msg.is_outgoing {
builder = builder.outgoing();
} else {
builder = builder.incoming();
}
if !msg.contains_unread_mention {
builder = builder.read();
} else {
builder = builder.unread();
}
if msg.can_be_edited {
builder = builder.editable();
}
if msg.can_be_deleted_only_for_self {
builder = builder.deletable_for_self();
}
if msg.can_be_deleted_for_all_users {
builder = builder.deletable_for_all();
}
if let Some(reply) = reply_to {
builder = builder.reply_to(reply);
}
if let Some(forward) = forward_from {
builder = builder.forward_from(forward);
}
builder = builder.reactions(reactions);
Some(builder.build())
}
/// Получить недостающую reply информацию для сообщений
@@ -511,7 +538,7 @@ impl MessageManager {
// Collect message IDs that need to be fetched
let mut to_fetch = Vec::new();
for msg in &self.current_chat_messages {
if let Some(ref reply) = msg.reply_to {
if let Some(ref reply) = msg.interactions.reply_to {
if reply.sender_name == "Unknown" {
to_fetch.push(reply.message_id);
}
@@ -522,17 +549,18 @@ impl MessageManager {
if let Some(chat_id) = self.current_chat_id {
for message_id in to_fetch {
if let Ok(original_msg_enum) =
functions::get_message(chat_id, message_id, self.client_id).await
functions::get_message(chat_id.as_i64(), message_id.as_i64(), self.client_id).await
{
if let tdlib_rs::enums::Message::Message(original_msg) = original_msg_enum {
if let Some(orig_info) = self.convert_message(&original_msg).await {
// Update the reply info
for msg in &mut self.current_chat_messages {
if let Some(ref mut reply) = msg.reply_to {
if let Some(ref mut reply) = msg.interactions.reply_to {
if reply.message_id == message_id {
reply.sender_name = orig_info.sender_name.clone();
reply.sender_name = orig_info.metadata.sender_name.clone();
reply.text = orig_info
.content
.text
.chars()
.take(50)
.collect::<String>();

View File

@@ -68,7 +68,7 @@ pub struct MessageMetadata {
}
/// Контент сообщения (текст и форматирование)
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub struct MessageContent {
pub text: String,
/// Сущности форматирования (bold, italic, code и т.д.)

View File

@@ -61,7 +61,7 @@ impl<V: Clone> LruCache<V> {
}
/// Проверить наличие ключа
pub fn contains_key(&self, key: &i64) -> bool {
pub fn contains_key(&self, key: &UserId) -> bool {
self.map.contains_key(key)
}
@@ -181,7 +181,7 @@ impl UserCache {
}
// Берём первые N user_ids для загрузки
let batch: Vec<i64> = self
let batch: Vec<UserId> = self
.pending_user_ids
.drain(..self.pending_user_ids.len().min(LAZY_LOAD_USERS_PER_TICK))
.collect();
@@ -191,7 +191,7 @@ impl UserCache {
continue; // Уже в кэше
}
match functions::get_user(user_id, self.client_id).await {
match functions::get_user(user_id.as_i64(), self.client_id).await {
Ok(user_enum) => {
self.handle_user_update(&user_enum);
}