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:
@@ -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 для сообщений с неполными данными
|
||||
|
||||
@@ -57,17 +57,28 @@ pub struct ReactionInfo {
|
||||
pub is_chosen: bool,
|
||||
}
|
||||
|
||||
/// Метаданные сообщения (ID, отправитель, время)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MessageInfo {
|
||||
pub struct MessageMetadata {
|
||||
pub id: MessageId,
|
||||
pub sender_name: String,
|
||||
pub is_outgoing: bool,
|
||||
pub content: String,
|
||||
/// Сущности форматирования (bold, italic, code и т.д.)
|
||||
pub entities: Vec<TextEntity>,
|
||||
pub date: i32,
|
||||
/// Дата редактирования (0 если не редактировалось)
|
||||
pub edit_date: i32,
|
||||
}
|
||||
|
||||
/// Контент сообщения (текст и форматирование)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MessageContent {
|
||||
pub text: String,
|
||||
/// Сущности форматирования (bold, italic, code и т.д.)
|
||||
pub entities: Vec<TextEntity>,
|
||||
}
|
||||
|
||||
/// Состояние и права доступа к сообщению
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MessageState {
|
||||
pub is_outgoing: bool,
|
||||
pub is_read: bool,
|
||||
/// Можно ли редактировать сообщение
|
||||
pub can_be_edited: bool,
|
||||
@@ -75,6 +86,11 @@ pub struct MessageInfo {
|
||||
pub can_be_deleted_only_for_self: bool,
|
||||
/// Можно ли удалить для всех
|
||||
pub can_be_deleted_for_all_users: bool,
|
||||
}
|
||||
|
||||
/// Взаимодействия с сообщением (reply, forward, reactions)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MessageInteractions {
|
||||
/// Информация о reply (если это ответ на сообщение)
|
||||
pub reply_to: Option<ReplyInfo>,
|
||||
/// Информация о forward (если сообщение переслано)
|
||||
@@ -83,6 +99,120 @@ pub struct MessageInfo {
|
||||
pub reactions: Vec<ReactionInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MessageInfo {
|
||||
pub metadata: MessageMetadata,
|
||||
pub content: MessageContent,
|
||||
pub state: MessageState,
|
||||
pub interactions: MessageInteractions,
|
||||
}
|
||||
|
||||
impl MessageInfo {
|
||||
/// Создать новое сообщение
|
||||
pub fn new(
|
||||
id: MessageId,
|
||||
sender_name: String,
|
||||
is_outgoing: bool,
|
||||
content: String,
|
||||
entities: Vec<TextEntity>,
|
||||
date: i32,
|
||||
edit_date: i32,
|
||||
is_read: bool,
|
||||
can_be_edited: bool,
|
||||
can_be_deleted_only_for_self: bool,
|
||||
can_be_deleted_for_all_users: bool,
|
||||
reply_to: Option<ReplyInfo>,
|
||||
forward_from: Option<ForwardInfo>,
|
||||
reactions: Vec<ReactionInfo>,
|
||||
) -> Self {
|
||||
Self {
|
||||
metadata: MessageMetadata {
|
||||
id,
|
||||
sender_name,
|
||||
date,
|
||||
edit_date,
|
||||
},
|
||||
content: MessageContent {
|
||||
text: content,
|
||||
entities,
|
||||
},
|
||||
state: MessageState {
|
||||
is_outgoing,
|
||||
is_read,
|
||||
can_be_edited,
|
||||
can_be_deleted_only_for_self,
|
||||
can_be_deleted_for_all_users,
|
||||
},
|
||||
interactions: MessageInteractions {
|
||||
reply_to,
|
||||
forward_from,
|
||||
reactions,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Удобные getter'ы для частых операций
|
||||
pub fn id(&self) -> MessageId {
|
||||
self.metadata.id
|
||||
}
|
||||
|
||||
pub fn sender_name(&self) -> &str {
|
||||
&self.metadata.sender_name
|
||||
}
|
||||
|
||||
pub fn date(&self) -> i32 {
|
||||
self.metadata.date
|
||||
}
|
||||
|
||||
pub fn edit_date(&self) -> i32 {
|
||||
self.metadata.edit_date
|
||||
}
|
||||
|
||||
pub fn is_edited(&self) -> bool {
|
||||
self.metadata.edit_date > 0
|
||||
}
|
||||
|
||||
pub fn text(&self) -> &str {
|
||||
&self.content.text
|
||||
}
|
||||
|
||||
pub fn entities(&self) -> &[TextEntity] {
|
||||
&self.content.entities
|
||||
}
|
||||
|
||||
pub fn is_outgoing(&self) -> bool {
|
||||
self.state.is_outgoing
|
||||
}
|
||||
|
||||
pub fn is_read(&self) -> bool {
|
||||
self.state.is_read
|
||||
}
|
||||
|
||||
pub fn can_be_edited(&self) -> bool {
|
||||
self.state.can_be_edited
|
||||
}
|
||||
|
||||
pub fn can_be_deleted_only_for_self(&self) -> bool {
|
||||
self.state.can_be_deleted_only_for_self
|
||||
}
|
||||
|
||||
pub fn can_be_deleted_for_all_users(&self) -> bool {
|
||||
self.state.can_be_deleted_for_all_users
|
||||
}
|
||||
|
||||
pub fn reply_to(&self) -> Option<&ReplyInfo> {
|
||||
self.interactions.reply_to.as_ref()
|
||||
}
|
||||
|
||||
pub fn forward_from(&self) -> Option<&ForwardInfo> {
|
||||
self.interactions.forward_from.as_ref()
|
||||
}
|
||||
|
||||
pub fn reactions(&self) -> &[ReactionInfo] {
|
||||
&self.interactions.reactions
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FolderInfo {
|
||||
pub id: i32,
|
||||
|
||||
Reference in New Issue
Block a user