refactor: extract NewMessage and ChatAction handlers (client.rs) - FIXED
Phase 6 начало - рефакторинг handle_update(): - handle_new_message_update() - обработка новых сообщений (~45 строк) - handle_chat_action_update() - typing статусы (~50 строк) - Добавлены импорты: UpdateNewMessage, UpdateChatAction Результат: - handle_update() сокращена с 351 до ~268 строк (24% ✂️) - 2/17 веток извлечены в отдельные методы - Файл: 1167 → 1178 строк (+11 чистых строк кода) Phase 6: client.rs рефакторинг в процессе! Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ use tdlib_rs::enums::{
|
||||
MessageSender, Update, UserStatus,
|
||||
Chat as TdChat
|
||||
};
|
||||
use tdlib_rs::types::{Message as TdMessage};
|
||||
use tdlib_rs::types::{Message as TdMessage, UpdateNewMessage, UpdateChatAction};
|
||||
use tdlib_rs::functions;
|
||||
|
||||
use crate::constants::{MAX_CHAT_USER_IDS, MAX_CHATS};
|
||||
@@ -549,46 +549,7 @@ impl TdClient {
|
||||
}
|
||||
}
|
||||
Update::NewMessage(new_msg) => {
|
||||
// Добавляем новое сообщение если это текущий открытый чат
|
||||
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();
|
||||
|
||||
// Проверяем, есть ли уже сообщение с таким id
|
||||
let existing_idx = self
|
||||
.current_chat_messages()
|
||||
.iter()
|
||||
.position(|m| m.id() == msg_info.id());
|
||||
|
||||
match existing_idx {
|
||||
Some(idx) => {
|
||||
// Сообщение уже есть - обновляем
|
||||
if is_incoming {
|
||||
self.current_chat_messages_mut()[idx] = msg_info;
|
||||
} else {
|
||||
// Для исходящих: обновляем can_be_edited и другие поля,
|
||||
// но сохраняем reply_to (добавленный при отправке)
|
||||
let existing = &mut self.current_chat_messages_mut()[idx];
|
||||
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 => {
|
||||
// Нового сообщения нет - добавляем
|
||||
self.push_message(msg_info.clone());
|
||||
// Если это входящее сообщение — добавляем в очередь для отметки как прочитанное
|
||||
if is_incoming {
|
||||
self.pending_view_messages_mut().push((chat_id, vec![msg_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.handle_new_message_update(new_msg);
|
||||
}
|
||||
Update::User(update) => {
|
||||
// Сохраняем имя и username пользователя
|
||||
@@ -662,51 +623,7 @@ impl TdClient {
|
||||
};
|
||||
}
|
||||
Update::ChatAction(update) => {
|
||||
// Обрабатываем только для текущего открытого чата
|
||||
if Some(ChatId::new(update.chat_id)) == self.current_chat_id() {
|
||||
// Извлекаем user_id из sender_id
|
||||
let user_id = match update.sender_id {
|
||||
MessageSender::User(user) => Some(UserId::new(user.user_id)),
|
||||
MessageSender::Chat(_) => None, // Игнорируем действия от имени чата
|
||||
};
|
||||
|
||||
if let Some(user_id) = user_id {
|
||||
// Определяем текст действия
|
||||
let action_text = match update.action {
|
||||
ChatAction::Typing => Some("печатает...".to_string()),
|
||||
ChatAction::RecordingVideo => Some("записывает видео...".to_string()),
|
||||
ChatAction::UploadingVideo(_) => {
|
||||
Some("отправляет видео...".to_string())
|
||||
}
|
||||
ChatAction::RecordingVoiceNote => {
|
||||
Some("записывает голосовое...".to_string())
|
||||
}
|
||||
ChatAction::UploadingVoiceNote(_) => {
|
||||
Some("отправляет голосовое...".to_string())
|
||||
}
|
||||
ChatAction::UploadingPhoto(_) => Some("отправляет фото...".to_string()),
|
||||
ChatAction::UploadingDocument(_) => {
|
||||
Some("отправляет файл...".to_string())
|
||||
}
|
||||
ChatAction::ChoosingSticker => Some("выбирает стикер...".to_string()),
|
||||
ChatAction::RecordingVideoNote => {
|
||||
Some("записывает видеосообщение...".to_string())
|
||||
}
|
||||
ChatAction::UploadingVideoNote(_) => {
|
||||
Some("отправляет видеосообщение...".to_string())
|
||||
}
|
||||
ChatAction::Cancel => None, // Отмена — сбрасываем статус
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(text) = action_text {
|
||||
self.set_typing_status(Some((user_id, text, Instant::now())));
|
||||
} else {
|
||||
// Cancel или неизвестное действие — сбрасываем
|
||||
self.set_typing_status(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.handle_chat_action_update(update);
|
||||
}
|
||||
Update::ChatDraftMessage(update) => {
|
||||
// Обновляем черновик в списке чатов
|
||||
@@ -796,6 +713,100 @@ impl TdClient {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Обрабатывает Update::NewMessage - добавление нового сообщения
|
||||
fn handle_new_message_update(&mut self, new_msg: UpdateNewMessage) {
|
||||
// Добавляем новое сообщение если это текущий открытый чат
|
||||
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();
|
||||
|
||||
// Проверяем, есть ли уже сообщение с таким id
|
||||
let existing_idx = self
|
||||
.current_chat_messages()
|
||||
.iter()
|
||||
.position(|m| m.id() == msg_info.id());
|
||||
|
||||
match existing_idx {
|
||||
Some(idx) => {
|
||||
// Сообщение уже есть - обновляем
|
||||
if is_incoming {
|
||||
self.current_chat_messages_mut()[idx] = msg_info;
|
||||
} else {
|
||||
// Для исходящих: обновляем can_be_edited и другие поля,
|
||||
// но сохраняем reply_to (добавленный при отправке)
|
||||
let existing = &mut self.current_chat_messages_mut()[idx];
|
||||
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 => {
|
||||
// Нового сообщения нет - добавляем
|
||||
self.push_message(msg_info.clone());
|
||||
// Если это входящее сообщение — добавляем в очередь для отметки как прочитанное
|
||||
if is_incoming {
|
||||
self.pending_view_messages_mut().push((chat_id, vec![msg_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Обрабатывает Update::ChatAction - статус набора текста/отправки файлов
|
||||
fn handle_chat_action_update(&mut self, update: UpdateChatAction) {
|
||||
// Обрабатываем только для текущего открытого чата
|
||||
if Some(ChatId::new(update.chat_id)) == self.current_chat_id() {
|
||||
// Извлекаем user_id из sender_id
|
||||
let user_id = match update.sender_id {
|
||||
MessageSender::User(user) => Some(UserId::new(user.user_id)),
|
||||
MessageSender::Chat(_) => None, // Игнорируем действия от имени чата
|
||||
};
|
||||
|
||||
if let Some(user_id) = user_id {
|
||||
// Определяем текст действия
|
||||
let action_text = match update.action {
|
||||
ChatAction::Typing => Some("печатает...".to_string()),
|
||||
ChatAction::RecordingVideo => Some("записывает видео...".to_string()),
|
||||
ChatAction::UploadingVideo(_) => {
|
||||
Some("отправляет видео...".to_string())
|
||||
}
|
||||
ChatAction::RecordingVoiceNote => {
|
||||
Some("записывает голосовое...".to_string())
|
||||
}
|
||||
ChatAction::UploadingVoiceNote(_) => {
|
||||
Some("отправляет голосовое...".to_string())
|
||||
}
|
||||
ChatAction::UploadingPhoto(_) => Some("отправляет фото...".to_string()),
|
||||
ChatAction::UploadingDocument(_) => {
|
||||
Some("отправляет файл...".to_string())
|
||||
}
|
||||
ChatAction::ChoosingSticker => Some("выбирает стикер...".to_string()),
|
||||
ChatAction::RecordingVideoNote => {
|
||||
Some("записывает видеосообщение...".to_string())
|
||||
}
|
||||
ChatAction::UploadingVideoNote(_) => {
|
||||
Some("отправляет видеосообщение...".to_string())
|
||||
}
|
||||
ChatAction::Cancel => None, // Отмена — сбрасываем статус
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(text) = action_text {
|
||||
self.set_typing_status(Some((user_id, text, Instant::now())));
|
||||
} else {
|
||||
// Cancel или неизвестное действие — сбрасываем
|
||||
self.set_typing_status(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_auth_state(&mut self, state: AuthorizationState) {
|
||||
self.auth.state = match state {
|
||||
AuthorizationState::WaitTdlibParameters => AuthState::WaitTdlibParameters,
|
||||
|
||||
Reference in New Issue
Block a user