style: auto-format entire codebase with cargo fmt (stable rustfmt.toml)
Some checks failed
ci/woodpecker/pr/check Pipeline failed
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
Some checks failed
ci/woodpecker/pr/check Pipeline failed
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
This commit is contained in:
@@ -6,22 +6,22 @@
|
||||
//! - Editing and sending messages
|
||||
//! - Loading older messages
|
||||
|
||||
use super::chat_list::open_chat_and_load_data;
|
||||
use crate::app::methods::{
|
||||
compose::ComposeMethods, messages::MessageMethods, modal::ModalMethods,
|
||||
navigation::NavigationMethods,
|
||||
};
|
||||
use crate::app::App;
|
||||
use crate::app::InputMode;
|
||||
use crate::app::methods::{
|
||||
compose::ComposeMethods, messages::MessageMethods,
|
||||
modal::ModalMethods, navigation::NavigationMethods,
|
||||
};
|
||||
use crate::tdlib::{TdClientTrait, ChatAction};
|
||||
use crate::input::handlers::{copy_to_clipboard, format_message_for_clipboard};
|
||||
use crate::tdlib::{ChatAction, TdClientTrait};
|
||||
use crate::types::{ChatId, MessageId};
|
||||
use crate::utils::{is_non_empty, with_timeout, with_timeout_msg};
|
||||
use crate::input::handlers::{copy_to_clipboard, format_message_for_clipboard};
|
||||
use super::chat_list::open_chat_and_load_data;
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
/// Обработка режима выбора сообщения для действий
|
||||
///
|
||||
///
|
||||
/// Обрабатывает:
|
||||
/// - Навигацию по сообщениям (Up/Down)
|
||||
/// - Удаление сообщения (d/в/Delete)
|
||||
@@ -29,7 +29,11 @@ use std::time::{Duration, Instant};
|
||||
/// - Пересылку сообщения (f/а)
|
||||
/// - Копирование сообщения (y/н)
|
||||
/// - Добавление реакции (e/у)
|
||||
pub async fn handle_message_selection<T: TdClientTrait>(app: &mut App<T>, _key: KeyEvent, command: Option<crate::config::Command>) {
|
||||
pub async fn handle_message_selection<T: TdClientTrait>(
|
||||
app: &mut App<T>,
|
||||
_key: KeyEvent,
|
||||
command: Option<crate::config::Command>,
|
||||
) {
|
||||
match command {
|
||||
Some(crate::config::Command::MoveUp) => {
|
||||
app.select_previous_message();
|
||||
@@ -44,9 +48,7 @@ pub async fn handle_message_selection<T: TdClientTrait>(app: &mut App<T>, _key:
|
||||
let can_delete =
|
||||
msg.can_be_deleted_only_for_self() || msg.can_be_deleted_for_all_users();
|
||||
if can_delete {
|
||||
app.chat_state = crate::app::ChatState::DeleteConfirmation {
|
||||
message_id: msg.id(),
|
||||
};
|
||||
app.chat_state = crate::app::ChatState::DeleteConfirmation { message_id: msg.id() };
|
||||
}
|
||||
}
|
||||
Some(crate::config::Command::EnterInsertMode) => {
|
||||
@@ -129,17 +131,22 @@ pub async fn handle_message_selection<T: TdClientTrait>(app: &mut App<T>, _key:
|
||||
}
|
||||
|
||||
/// Редактирование существующего сообщения
|
||||
pub async fn edit_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64, msg_id: MessageId, text: String) {
|
||||
pub async fn edit_message<T: TdClientTrait>(
|
||||
app: &mut App<T>,
|
||||
chat_id: i64,
|
||||
msg_id: MessageId,
|
||||
text: String,
|
||||
) {
|
||||
// Проверяем, что сообщение есть в локальном кэше
|
||||
let msg_exists = app.td_client.current_chat_messages()
|
||||
let msg_exists = app
|
||||
.td_client
|
||||
.current_chat_messages()
|
||||
.iter()
|
||||
.any(|m| m.id() == msg_id);
|
||||
|
||||
if !msg_exists {
|
||||
app.error_message = Some(format!(
|
||||
"Сообщение {} не найдено в кэше чата {}",
|
||||
msg_id.as_i64(), chat_id
|
||||
));
|
||||
app.error_message =
|
||||
Some(format!("Сообщение {} не найдено в кэше чата {}", msg_id.as_i64(), chat_id));
|
||||
app.chat_state = crate::app::ChatState::Normal;
|
||||
app.message_input.clear();
|
||||
app.cursor_position = 0;
|
||||
@@ -148,7 +155,8 @@ pub async fn edit_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64, msg_
|
||||
|
||||
match with_timeout_msg(
|
||||
Duration::from_secs(5),
|
||||
app.td_client.edit_message(ChatId::new(chat_id), msg_id, text),
|
||||
app.td_client
|
||||
.edit_message(ChatId::new(chat_id), msg_id, text),
|
||||
"Таймаут редактирования",
|
||||
)
|
||||
.await
|
||||
@@ -160,8 +168,12 @@ pub async fn edit_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64, msg_
|
||||
let old_reply_to = messages[pos].interactions.reply_to.clone();
|
||||
// Если в старом сообщении был reply и в новом он "Unknown" - сохраняем старый
|
||||
if let Some(old_reply) = old_reply_to {
|
||||
if edited_msg.interactions.reply_to.as_ref()
|
||||
.map_or(true, |r| r.sender_name == "Unknown") {
|
||||
if edited_msg
|
||||
.interactions
|
||||
.reply_to
|
||||
.as_ref()
|
||||
.map_or(true, |r| r.sender_name == "Unknown")
|
||||
{
|
||||
edited_msg.interactions.reply_to = Some(old_reply);
|
||||
}
|
||||
}
|
||||
@@ -189,13 +201,13 @@ pub async fn send_new_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64,
|
||||
};
|
||||
|
||||
// Создаём ReplyInfo ДО отправки, пока сообщение точно доступно
|
||||
let reply_info = app.get_replying_to_message().map(|m| {
|
||||
crate::tdlib::ReplyInfo {
|
||||
let reply_info = app
|
||||
.get_replying_to_message()
|
||||
.map(|m| crate::tdlib::ReplyInfo {
|
||||
message_id: m.id(),
|
||||
sender_name: m.sender_name().to_string(),
|
||||
text: m.text().to_string(),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.message_input.clear();
|
||||
app.cursor_position = 0;
|
||||
@@ -206,11 +218,14 @@ pub async fn send_new_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64,
|
||||
app.last_typing_sent = None;
|
||||
|
||||
// Отменяем typing status
|
||||
app.td_client.send_chat_action(ChatId::new(chat_id), ChatAction::Cancel).await;
|
||||
app.td_client
|
||||
.send_chat_action(ChatId::new(chat_id), ChatAction::Cancel)
|
||||
.await;
|
||||
|
||||
match with_timeout_msg(
|
||||
Duration::from_secs(5),
|
||||
app.td_client.send_message(ChatId::new(chat_id), text, reply_to_id, reply_info),
|
||||
app.td_client
|
||||
.send_message(ChatId::new(chat_id), text, reply_to_id, reply_info),
|
||||
"Таймаут отправки",
|
||||
)
|
||||
.await
|
||||
@@ -228,7 +243,7 @@ pub async fn send_new_message<T: TdClientTrait>(app: &mut App<T>, chat_id: i64,
|
||||
}
|
||||
|
||||
/// Обработка клавиши Enter
|
||||
///
|
||||
///
|
||||
/// Обрабатывает три сценария:
|
||||
/// 1. В режиме выбора сообщения: начать редактирование
|
||||
/// 2. В открытом чате: отправить новое или редактировать существующее сообщение
|
||||
@@ -304,7 +319,8 @@ pub async fn send_reaction<T: TdClientTrait>(app: &mut App<T>) {
|
||||
// Send reaction with timeout
|
||||
let result = with_timeout_msg(
|
||||
Duration::from_secs(5),
|
||||
app.td_client.toggle_reaction(chat_id, message_id, emoji.clone()),
|
||||
app.td_client
|
||||
.toggle_reaction(chat_id, message_id, emoji.clone()),
|
||||
"Таймаут отправки реакции",
|
||||
)
|
||||
.await;
|
||||
@@ -353,7 +369,8 @@ pub async fn load_older_messages_if_needed<T: TdClientTrait>(app: &mut App<T>) {
|
||||
// Load older messages with timeout
|
||||
let Ok(older) = with_timeout(
|
||||
Duration::from_secs(3),
|
||||
app.td_client.load_older_messages(ChatId::new(chat_id), oldest_msg_id),
|
||||
app.td_client
|
||||
.load_older_messages(ChatId::new(chat_id), oldest_msg_id),
|
||||
)
|
||||
.await
|
||||
else {
|
||||
@@ -368,7 +385,7 @@ pub async fn load_older_messages_if_needed<T: TdClientTrait>(app: &mut App<T>) {
|
||||
}
|
||||
|
||||
/// Обработка ввода клавиатуры в открытом чате
|
||||
///
|
||||
///
|
||||
/// Обрабатывает:
|
||||
/// - Backspace/Delete: удаление символов относительно курсора
|
||||
/// - Char: вставка символов в позицию курсора + typing status
|
||||
@@ -408,7 +425,8 @@ pub async fn handle_open_chat_keyboard_input<T: TdClientTrait>(app: &mut App<T>,
|
||||
// Игнорируем символы с Ctrl/Alt модификаторами (кроме Shift)
|
||||
// Это позволяет обрабатывать хоткеи типа Ctrl+U для профиля
|
||||
if key.modifiers.contains(KeyModifiers::CONTROL)
|
||||
|| key.modifiers.contains(KeyModifiers::ALT) {
|
||||
|| key.modifiers.contains(KeyModifiers::ALT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -434,7 +452,9 @@ pub async fn handle_open_chat_keyboard_input<T: TdClientTrait>(app: &mut App<T>,
|
||||
.unwrap_or(true);
|
||||
if should_send_typing {
|
||||
if let Some(chat_id) = app.get_selected_chat_id() {
|
||||
app.td_client.send_chat_action(ChatId::new(chat_id), ChatAction::Typing).await;
|
||||
app.td_client
|
||||
.send_chat_action(ChatId::new(chat_id), ChatAction::Typing)
|
||||
.await;
|
||||
app.last_typing_sent = Some(Instant::now());
|
||||
}
|
||||
}
|
||||
@@ -621,8 +641,7 @@ async fn handle_view_image<T: TdClientTrait>(app: &mut App<T>) {
|
||||
for msg in app.td_client.current_chat_messages_mut() {
|
||||
if let Some(photo) = msg.photo_info_mut() {
|
||||
if photo.file_id == file_id {
|
||||
photo.download_state =
|
||||
PhotoDownloadState::Downloaded(path.clone());
|
||||
photo.download_state = PhotoDownloadState::Downloaded(path.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -640,8 +659,7 @@ async fn handle_view_image<T: TdClientTrait>(app: &mut App<T>) {
|
||||
for msg in app.td_client.current_chat_messages_mut() {
|
||||
if let Some(photo) = msg.photo_info_mut() {
|
||||
if photo.file_id == file_id {
|
||||
photo.download_state =
|
||||
PhotoDownloadState::Error(e.clone());
|
||||
photo.download_state = PhotoDownloadState::Error(e.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -660,8 +678,7 @@ async fn handle_view_image<T: TdClientTrait>(app: &mut App<T>) {
|
||||
for msg in app.td_client.current_chat_messages_mut() {
|
||||
if let Some(photo) = msg.photo_info_mut() {
|
||||
if photo.file_id == file_id {
|
||||
photo.download_state =
|
||||
PhotoDownloadState::Downloaded(path.clone());
|
||||
photo.download_state = PhotoDownloadState::Downloaded(path.clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -748,13 +765,25 @@ async fn handle_play_voice<T: TdClientTrait>(app: &mut App<T>) {
|
||||
if let Ok(entries) = std::fs::read_dir(parent) {
|
||||
for entry in entries.flatten() {
|
||||
let entry_name = entry.file_name();
|
||||
if entry_name.to_string_lossy().starts_with(&stem.to_string_lossy().to_string()) {
|
||||
if entry_name
|
||||
.to_string_lossy()
|
||||
.starts_with(&stem.to_string_lossy().to_string())
|
||||
{
|
||||
let found_path = entry.path().to_string_lossy().to_string();
|
||||
// Кэшируем найденный файл
|
||||
if let Some(ref mut cache) = app.voice_cache {
|
||||
let _ = cache.store(&file_id.to_string(), Path::new(&found_path));
|
||||
let _ = cache.store(
|
||||
&file_id.to_string(),
|
||||
Path::new(&found_path),
|
||||
);
|
||||
}
|
||||
return handle_play_voice_from_path(app, &found_path, &voice, &msg).await;
|
||||
return handle_play_voice_from_path(
|
||||
app,
|
||||
&found_path,
|
||||
&voice,
|
||||
&msg,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -826,4 +855,3 @@ async fn _download_and_expand<T: TdClientTrait>(app: &mut App<T>, msg_id: crate:
|
||||
// Закомментировано - будет реализовано в Этапе 4
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user