fix: исправлены баги с сообщениями, редактированием и reply

- Изменён порядок хранения сообщений (теперь от старых к новым)
- Исправлена логика выбора сообщений для редактирования
- Исправлена отправка reply (структура условий)
- Добавлено сохранение reply_info при отправке
- Удалены отладочные логи

Fixes: сообщения теперь отображаются корректно в UI
Fixes: редактирование работает без ошибки 'Message not found'
Fixes: reply показывает превью исходного сообщения
This commit is contained in:
Mikhail Kilin
2026-01-31 18:29:02 +03:00
parent 644e36597d
commit 07c401e0f9
4 changed files with 129 additions and 82 deletions

View File

@@ -498,7 +498,7 @@ impl TdClient {
}
None => {
// Нового сообщения нет - добавляем
self.push_message(msg_info);
self.push_message(msg_info.clone());
// Если это входящее сообщение — добавляем в очередь для отметки как прочитанное
if is_incoming {
self.pending_view_messages_mut().push((chat_id, vec![msg_id]));

View File

@@ -29,11 +29,11 @@ impl MessageManager {
/// Добавить сообщение в список текущего чата
pub fn push_message(&mut self, msg: MessageInfo) {
self.current_chat_messages.insert(0, msg);
self.current_chat_messages.push(msg); // Добавляем в конец
// Ограничиваем размер списка
// Ограничиваем размер списка (удаляем старые с начала)
if self.current_chat_messages.len() > MAX_MESSAGES_IN_CHAT {
self.current_chat_messages.truncate(MAX_MESSAGES_IN_CHAT);
self.current_chat_messages.drain(0..(self.current_chat_messages.len() - MAX_MESSAGES_IN_CHAT));
}
}
@@ -43,34 +43,63 @@ impl MessageManager {
chat_id: ChatId,
limit: i32,
) -> Result<Vec<MessageInfo>, String> {
// Устанавливаем текущий чат для получения новых сообщений
self.current_chat_id = Some(chat_id);
use tokio::time::{sleep, Duration};
let result = functions::get_chat_history(
chat_id.as_i64(),
0, // from_message_id
0, // offset
limit,
false,
self.client_id,
)
.await;
// ВАЖНО: Сначала открываем чат в TDLib
// Это сообщает TDLib что пользователь открыл чат и нужно загрузить историю
let _ = functions::open_chat(chat_id.as_i64(), self.client_id).await;
match result {
Ok(tdlib_rs::enums::Messages::Messages(messages_obj)) => {
let mut messages = Vec::new();
for msg_opt in messages_obj.messages.iter().rev() {
if let Some(msg) = msg_opt {
if let Some(info) = self.convert_message(msg).await {
messages.push(info);
// Даём TDLib время на синхронизацию (загрузку истории с сервера)
sleep(Duration::from_millis(100)).await;
// НЕ устанавливаем current_chat_id здесь!
// Он будет установлен снаружи ПОСЛЕ сохранения истории
// Это предотвращает race condition с Update::NewMessage
// Пробуем загрузить несколько раз, TDLib может подгружать с сервера
let mut all_messages = Vec::new();
let max_attempts = 3;
for attempt in 1..=max_attempts {
let result = functions::get_chat_history(
chat_id.as_i64(),
0, // from_message_id (0 = from latest)
0, // offset
limit,
false, // only_local - false means can fetch from server
self.client_id,
)
.await;
match result {
Ok(tdlib_rs::enums::Messages::Messages(messages_obj)) => {
if !messages_obj.messages.is_empty() {
all_messages.clear(); // Очищаем предыдущие результаты
for msg_opt in messages_obj.messages.iter().rev() {
if let Some(msg) = msg_opt {
if let Some(info) = self.convert_message(msg).await {
all_messages.push(info);
}
}
}
// Если получили достаточно сообщений, прекращаем попытки
if all_messages.len() >= 2 || attempt == max_attempts {
break;
}
}
// Если сообщений мало, ждём перед следующей попыткой
if attempt < max_attempts {
sleep(Duration::from_millis(200)).await;
}
}
Ok(messages)
Ok(_) => return Err("Неожиданный тип сообщений".to_string()),
Err(e) => return Err(format!("Ошибка загрузки истории: {:?}", e)),
}
Ok(_) => Err("Неожиданный тип сообщений".to_string()),
Err(e) => Err(format!("Ошибка загрузки истории: {:?}", e)),
}
Ok(all_messages)
}
/// Загрузить более старые сообщения
@@ -194,7 +223,7 @@ impl MessageManager {
chat_id: ChatId,
text: String,
reply_to_message_id: Option<MessageId>,
_reply_info: Option<ReplyInfo>,
reply_info: Option<ReplyInfo>,
) -> Result<MessageInfo, String> {
// Парсим markdown в тексте
let formatted_text = match functions::parse_text_entities(
@@ -241,10 +270,19 @@ impl MessageManager {
.await;
match result {
Ok(tdlib_rs::enums::Message::Message(msg)) => self
.convert_message(&msg)
.await
.ok_or_else(|| "Не удалось конвертировать сообщение".to_string()),
Ok(tdlib_rs::enums::Message::Message(msg)) => {
let mut msg_info = self
.convert_message(&msg)
.await
.ok_or_else(|| "Не удалось конвертировать сообщение".to_string())?;
// Добавляем reply_info если был передан
if let Some(reply) = reply_info {
msg_info.interactions.reply_to = Some(reply);
}
Ok(msg_info)
}
Ok(_) => Err("Неожиданный тип сообщения".to_string()),
Err(e) => Err(format!("Ошибка отправки сообщения: {:?}", e)),
}