refactor: restructure MessageInfo with logical field grouping (P2.6)

Сгруппированы 16 плоских полей MessageInfo в 4 логические структуры
для улучшения организации кода и maintainability.

Новые структуры:
- MessageMetadata: id, sender_name, date, edit_date
- MessageContent: text, entities
- MessageState: is_outgoing, is_read, can_be_edited, can_be_deleted_*
- MessageInteractions: reply_to, forward_from, reactions

Изменения:
- Добавлены 4 новые структуры в tdlib/types.rs
- Обновлена MessageInfo для использования новых структур
- Добавлен конструктор MessageInfo::new() для удобного создания
- Добавлены getter методы (id(), text(), sender_name() и др.) для удобного доступа
- Обновлены все места создания MessageInfo (convert_message)
- Обновлены все места использования (~200+ обращений):
  * ui/messages.rs: рендеринг сообщений
  * app/mod.rs: логика приложения
  * input/main_input.rs: обработка ввода и копирование
  * tdlib/client.rs: обработка updates
  * Все тестовые файлы (14 файлов)

Преимущества:
- Логическая группировка данных
- Проще понимать структуру сообщения
- Легче добавлять новые поля в будущем
- Улучшенная читаемость кода

Статус: Priority 2 теперь 80% (4/5 задач)
-  Error enum
-  Config validation
-  Newtype для ID
-  MessageInfo реструктуризация
-  MessageBuilder pattern

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-01-31 01:45:54 +03:00
parent 7081a886ad
commit 43960332d9
14 changed files with 274 additions and 144 deletions

View File

@@ -422,8 +422,8 @@ impl TdClient {
// Если это текущий открытый чат — обновляем is_read у сообщений
if Some(ChatId::new(update.chat_id)) == self.current_chat_id() {
for msg in self.current_chat_messages_mut().iter_mut() {
if msg.is_outgoing && msg.id <= last_read_msg_id {
msg.is_read = true;
if msg.is_outgoing() && msg.id() <= last_read_msg_id {
msg.state.is_read = true;
}
}
}
@@ -477,7 +477,7 @@ impl TdClient {
let existing_idx = self
.current_chat_messages()
.iter()
.position(|m| m.id == msg_info.id);
.position(|m| m.id() == msg_info.id());
match existing_idx {
Some(idx) => {
@@ -646,10 +646,10 @@ impl TdClient {
if let Some(msg) = self
.current_chat_messages_mut()
.iter_mut()
.find(|m| m.id == MessageId::new(update.message_id))
.find(|m| m.id() == MessageId::new(update.message_id))
{
// Извлекаем реакции из interaction_info
msg.reactions = update
msg.interactions.reactions = update
.interaction_info
.as_ref()
.and_then(|info| info.reactions.as_ref())
@@ -870,22 +870,22 @@ impl TdClient {
// Извлекаем реакции
let reactions = self.extract_reactions(message);
MessageInfo {
id: message_id,
MessageInfo::new(
message_id,
sender_name,
is_outgoing: message.is_outgoing,
message.is_outgoing,
content,
entities,
date: message.date,
edit_date: message.edit_date,
message.date,
message.edit_date,
is_read,
can_be_edited: message.can_be_edited,
can_be_deleted_only_for_self: message.can_be_deleted_only_for_self,
can_be_deleted_for_all_users: message.can_be_deleted_for_all_users,
message.can_be_edited,
message.can_be_deleted_only_for_self,
message.can_be_deleted_for_all_users,
reply_to,
forward_from,
reactions,
}
)
}
/// Извлекает информацию о reply из сообщения
@@ -902,8 +902,8 @@ impl TdClient {
let reply_msg_id = MessageId::new(reply.message_id);
self.current_chat_messages()
.iter()
.find(|m| m.id == reply_msg_id)
.map(|m| m.sender_name.clone())
.find(|m| m.id() == reply_msg_id)
.map(|m| m.sender_name().to_string())
.unwrap_or_else(|| "...".to_string())
};
@@ -917,8 +917,8 @@ impl TdClient {
// Пробуем найти в текущих сообщениях
self.current_chat_messages()
.iter()
.find(|m| m.id == reply_msg_id)
.map(|m| m.content.clone())
.find(|m| m.id() == reply_msg_id)
.map(|m| m.text().to_string())
.unwrap_or_default()
};
@@ -996,7 +996,7 @@ impl TdClient {
let msg_data: std::collections::HashMap<i64, (String, String)> = self
.current_chat_messages()
.iter()
.map(|m| (m.id, (m.sender_name.clone(), m.content.clone())))
.map(|m| (m.id(), (m.sender_name().to_string(), m.text().to_string())))
.collect();
// Обновляем reply_to для сообщений с неполными данными