refactor: split main_input.rs into modular handlers (1199→164 lines)
Split monolithic input handler into 5 specialized modules: - handlers/chat.rs (452 lines) - chat keyboard input - handlers/modal.rs (316 lines) - modal dialogs - handlers/chat_list.rs (142 lines) - chat list navigation - handlers/search.rs (140 lines) - search functionality - handlers/compose.rs (80 lines) - forward/reply/edit modes Changes: - main_input.rs: 1199→164 lines (removed 1035 lines, -86%) - Preserved existing handlers: clipboard, global, profile - Created clean router pattern in main_input.rs - Fixed keybinding conflict: Ctrl+I→Ctrl+U for profile - Fixed modifier handling in chat input (ignore Ctrl/Alt chars) - Updated CONTEXT.md with refactoring metrics - Updated ROADMAP.md: Phase 13 Etap 1 marked as DONE Phase 13 Etap 1: COMPLETED (100%) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
141
src/input/handlers/search.rs
Normal file
141
src/input/handlers/search.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
//! Search input handlers
|
||||
//!
|
||||
//! Handles keyboard input for search functionality, including:
|
||||
//! - Chat list search mode
|
||||
//! - Message search mode
|
||||
//! - Search query input
|
||||
|
||||
use crate::app::App;
|
||||
use crate::tdlib::TdClientTrait;
|
||||
use crate::types::{ChatId, MessageId};
|
||||
use crate::utils::with_timeout;
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use std::time::Duration;
|
||||
|
||||
// Import from chat_list module
|
||||
use super::chat_list::open_chat_and_load_data;
|
||||
|
||||
/// Обработка режима поиска по чатам
|
||||
///
|
||||
/// Обрабатывает:
|
||||
/// - Редактирование поискового запроса (Backspace, Char)
|
||||
/// - Навигацию по отфильтрованному списку (Up/Down)
|
||||
/// - Открытие выбранного чата (Enter)
|
||||
/// - Отмену поиска (Esc)
|
||||
pub async fn handle_chat_search_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent, command: Option<crate::config::Command>) {
|
||||
match command {
|
||||
Some(crate::config::Command::Cancel) => {
|
||||
app.cancel_search();
|
||||
}
|
||||
Some(crate::config::Command::SubmitMessage) => {
|
||||
app.select_filtered_chat();
|
||||
if let Some(chat_id) = app.get_selected_chat_id() {
|
||||
open_chat_and_load_data(app, chat_id).await;
|
||||
}
|
||||
}
|
||||
Some(crate::config::Command::MoveDown) => {
|
||||
app.next_filtered_chat();
|
||||
}
|
||||
Some(crate::config::Command::MoveUp) => {
|
||||
app.previous_filtered_chat();
|
||||
}
|
||||
_ => {
|
||||
match key.code {
|
||||
KeyCode::Backspace => {
|
||||
app.search_query.pop();
|
||||
app.chat_list_state.select(Some(0));
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
app.search_query.push(c);
|
||||
app.chat_list_state.select(Some(0));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Обработка режима поиска по сообщениям в открытом чате
|
||||
///
|
||||
/// Обрабатывает:
|
||||
/// - Навигацию по результатам поиска (Up/Down/N/n)
|
||||
/// - Переход к выбранному сообщению (Enter)
|
||||
/// - Редактирование поискового запроса (Backspace, Char)
|
||||
/// - Выход из режима поиска (Esc)
|
||||
pub async fn handle_message_search_mode<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent, command: Option<crate::config::Command>) {
|
||||
match command {
|
||||
Some(crate::config::Command::Cancel) => {
|
||||
app.exit_message_search_mode();
|
||||
}
|
||||
Some(crate::config::Command::MoveUp) => {
|
||||
app.select_previous_search_result();
|
||||
}
|
||||
Some(crate::config::Command::MoveDown) => {
|
||||
app.select_next_search_result();
|
||||
}
|
||||
Some(crate::config::Command::SubmitMessage) => {
|
||||
if let Some(msg_id) = app.get_selected_search_result_id() {
|
||||
let msg_id = MessageId::new(msg_id);
|
||||
let msg_index = app
|
||||
.td_client
|
||||
.current_chat_messages()
|
||||
.iter()
|
||||
.position(|m| m.id() == msg_id);
|
||||
|
||||
if let Some(idx) = msg_index {
|
||||
let total = app.td_client.current_chat_messages().len();
|
||||
app.message_scroll_offset = total.saturating_sub(idx + 5);
|
||||
}
|
||||
app.exit_message_search_mode();
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
match key.code {
|
||||
KeyCode::Char('N') => {
|
||||
app.select_previous_search_result();
|
||||
}
|
||||
KeyCode::Char('n') => {
|
||||
app.select_next_search_result();
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
let Some(mut query) = app.get_search_query().map(|s| s.to_string()) else {
|
||||
return;
|
||||
};
|
||||
query.pop();
|
||||
app.update_search_query(query.clone());
|
||||
perform_message_search(app, &query).await;
|
||||
}
|
||||
KeyCode::Char(c) => {
|
||||
let Some(mut query) = app.get_search_query().map(|s| s.to_string()) else {
|
||||
return;
|
||||
};
|
||||
query.push(c);
|
||||
app.update_search_query(query.clone());
|
||||
perform_message_search(app, &query).await;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Выполняет поиск по сообщениям с обновлением результатов
|
||||
pub async fn perform_message_search<T: TdClientTrait>(app: &mut App<T>, query: &str) {
|
||||
let Some(chat_id) = app.get_selected_chat_id() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if query.is_empty() {
|
||||
app.set_search_results(Vec::new());
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(results) = with_timeout(
|
||||
Duration::from_secs(3),
|
||||
app.td_client.search_messages(ChatId::new(chat_id), query),
|
||||
)
|
||||
.await
|
||||
{
|
||||
app.set_search_results(results);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user