refactor: prepare handlers structure for future input refactoring
Preparation for splitting large input file (#2): - Created src/input/handlers/ structure (7 modules) - clipboard.rs (~100 lines) - clipboard operations extracted - global.rs (~90 lines) - global commands (Ctrl+R/S/P/F) extracted - Stubs: profile.rs, search.rs, modal.rs, messages.rs, chat_list.rs - main_input.rs remains monolithic (1139 lines) - Attempted full migration broke navigation - rolled back - Handlers remain as preparation for gradual migration Updated documentation: - REFACTORING_OPPORTUNITIES.md: #2.1 status updated - CONTEXT.md: Added lesson about careful refactoring Lesson learned: Critical input logic requires careful step-by-step refactoring with functionality verification after each step. Tests: 563 passed, 0 failed Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
85
src/input/handlers/global.rs
Normal file
85
src/input/handlers/global.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
//! Global commands that work from any screen
|
||||
//!
|
||||
//! Handles Ctrl+ combinations:
|
||||
//! - Ctrl+R: Refresh chats
|
||||
//! - Ctrl+S: Start search
|
||||
//! - Ctrl+P: View pinned messages
|
||||
//! - Ctrl+F: Search messages in chat
|
||||
|
||||
use crate::app::App;
|
||||
use crate::types::ChatId;
|
||||
use crate::utils::{with_timeout, with_timeout_msg};
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Обрабатывает глобальные команды (Ctrl+ combinations).
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// `true` если команда была обработана, `false` если нет
|
||||
pub async fn handle_global_commands(app: &mut App, key: KeyEvent) -> bool {
|
||||
let has_ctrl = key.modifiers.contains(KeyModifiers::CONTROL);
|
||||
|
||||
match key.code {
|
||||
KeyCode::Char('r') if has_ctrl => {
|
||||
// Ctrl+R - обновить список чатов
|
||||
app.status_message = Some("Обновление чатов...".to_string());
|
||||
let _ = with_timeout(Duration::from_secs(5), app.td_client.load_chats(50)).await;
|
||||
app.status_message = None;
|
||||
true
|
||||
}
|
||||
KeyCode::Char('s') if has_ctrl => {
|
||||
// Ctrl+S - начать поиск (только если чат не открыт)
|
||||
if app.selected_chat_id.is_none() {
|
||||
app.start_search();
|
||||
}
|
||||
true
|
||||
}
|
||||
KeyCode::Char('p') if has_ctrl => {
|
||||
// Ctrl+P - режим просмотра закреплённых сообщений
|
||||
handle_pinned_messages(app).await;
|
||||
true
|
||||
}
|
||||
KeyCode::Char('f') if has_ctrl => {
|
||||
// Ctrl+F - поиск по сообщениям в открытом чате
|
||||
if app.selected_chat_id.is_some()
|
||||
&& !app.is_pinned_mode()
|
||||
&& !app.is_message_search_mode()
|
||||
{
|
||||
app.enter_message_search_mode();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Обрабатывает загрузку и отображение закреплённых сообщений
|
||||
async fn handle_pinned_messages(app: &mut App) {
|
||||
if app.selected_chat_id.is_some() && !app.is_pinned_mode() {
|
||||
if let Some(chat_id) = app.get_selected_chat_id() {
|
||||
app.status_message = Some("Загрузка закреплённых...".to_string());
|
||||
match with_timeout_msg(
|
||||
Duration::from_secs(5),
|
||||
app.td_client.get_pinned_messages(ChatId::new(chat_id)),
|
||||
"Таймаут загрузки",
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(messages) => {
|
||||
let messages: Vec<crate::tdlib::MessageInfo> = messages;
|
||||
if messages.is_empty() {
|
||||
app.status_message = Some("Нет закреплённых сообщений".to_string());
|
||||
} else {
|
||||
app.enter_pinned_mode(messages);
|
||||
app.status_message = None;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
app.error_message = Some(e);
|
||||
app.status_message = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user