Files
telegram-tui/src/app/methods/search.rs
Mikhail Kilin 931954d829 refactor: split app/mod.rs into trait-based architecture (1015→371 lines)
Split monolithic App impl into 5 specialized trait modules:
- methods/navigation.rs (NavigationMethods) - 7 methods for chat navigation
- methods/messages.rs (MessageMethods) - 8 methods for message operations
- methods/compose.rs (ComposeMethods) - 10 methods for reply/forward/draft
- methods/search.rs (SearchMethods) - 15 methods for search functionality
- methods/modal.rs (ModalMethods) - 27 methods for modal dialogs

Changes:
- app/mod.rs: 1015→371 lines (removed 644 lines, -63%)
- Created app/methods/ with 5 trait impl blocks
- Left in app/mod.rs: constructors, get_command, get_selected_chat_id/chat, getters/setters
- 116 functions → 5 trait impl blocks (67 in traits + 48 in core)
- Single Responsibility Principle achieved
- Updated CONTEXT.md with refactoring metrics
- Updated ROADMAP.md: Phase 13 Etap 2 marked as DONE

Phase 13 Etap 2: COMPLETED (100%)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 00:59:14 +03:00

175 lines
4.9 KiB
Rust

//! Search methods for App
//!
//! Handles chat list search and message search within chat
use crate::app::{App, ChatFilter, ChatFilterCriteria, ChatState};
use crate::tdlib::{ChatInfo, MessageInfo, TdClientTrait};
/// Search methods for chats and messages
pub trait SearchMethods<T: TdClientTrait> {
// === Chat Search ===
/// Start search mode in chat list
fn start_search(&mut self);
/// Cancel search mode and reset query
fn cancel_search(&mut self);
/// Get filtered chats based on search query and selected folder
fn get_filtered_chats(&self) -> Vec<&ChatInfo>;
// === Message Search ===
/// Check if message search mode is active
fn is_message_search_mode(&self) -> bool;
/// Enter message search mode within chat
fn enter_message_search_mode(&mut self);
/// Exit message search mode
fn exit_message_search_mode(&mut self);
/// Set search results
fn set_search_results(&mut self, results: Vec<MessageInfo>);
/// Select previous search result (up)
fn select_previous_search_result(&mut self);
/// Select next search result (down)
fn select_next_search_result(&mut self);
/// Get currently selected search result
fn get_selected_search_result(&self) -> Option<&MessageInfo>;
/// Get ID of selected search result for navigation
fn get_selected_search_result_id(&self) -> Option<i64>;
/// Get current search query
fn get_search_query(&self) -> Option<&str>;
/// Update search query
fn update_search_query(&mut self, new_query: String);
/// Get index of selected search result
fn get_search_selected_index(&self) -> Option<usize>;
/// Get all search results
fn get_search_results(&self) -> Option<&[MessageInfo]>;
}
impl<T: TdClientTrait> SearchMethods<T> for App<T> {
fn start_search(&mut self) {
self.is_searching = true;
self.search_query.clear();
}
fn cancel_search(&mut self) {
self.is_searching = false;
self.search_query.clear();
self.chat_list_state.select(Some(0));
}
fn get_filtered_chats(&self) -> Vec<&ChatInfo> {
// Используем ChatFilter для централизованной фильтрации
let mut criteria = ChatFilterCriteria::new()
.with_folder(self.selected_folder_id);
if !self.search_query.is_empty() {
criteria = criteria.with_search(self.search_query.clone());
}
ChatFilter::filter(&self.chats, &criteria)
}
fn is_message_search_mode(&self) -> bool {
self.chat_state.is_search_in_chat()
}
fn enter_message_search_mode(&mut self) {
self.chat_state = ChatState::SearchInChat {
query: String::new(),
results: Vec::new(),
selected_index: 0,
};
}
fn exit_message_search_mode(&mut self) {
self.chat_state = ChatState::Normal;
}
fn set_search_results(&mut self, results: Vec<MessageInfo>) {
if let ChatState::SearchInChat { results: r, selected_index, .. } = &mut self.chat_state {
*r = results;
*selected_index = 0;
}
}
fn select_previous_search_result(&mut self) {
if let ChatState::SearchInChat { selected_index, .. } = &mut self.chat_state {
if *selected_index > 0 {
*selected_index -= 1;
}
}
}
fn select_next_search_result(&mut self) {
if let ChatState::SearchInChat {
selected_index,
results,
..
} = &mut self.chat_state
{
if *selected_index + 1 < results.len() {
*selected_index += 1;
}
}
}
fn get_selected_search_result(&self) -> Option<&MessageInfo> {
if let ChatState::SearchInChat {
results,
selected_index,
..
} = &self.chat_state
{
results.get(*selected_index)
} else {
None
}
}
fn get_selected_search_result_id(&self) -> Option<i64> {
self.get_selected_search_result().map(|m| m.id().as_i64())
}
fn get_search_query(&self) -> Option<&str> {
if let ChatState::SearchInChat { query, .. } = &self.chat_state {
Some(query.as_str())
} else {
None
}
}
fn update_search_query(&mut self, new_query: String) {
if let ChatState::SearchInChat { query, .. } = &mut self.chat_state {
*query = new_query;
}
}
fn get_search_selected_index(&self) -> Option<usize> {
if let ChatState::SearchInChat { selected_index, .. } = &self.chat_state {
Some(*selected_index)
} else {
None
}
}
fn get_search_results(&self) -> Option<&[MessageInfo]> {
if let ChatState::SearchInChat { results, .. } = &self.chat_state {
Some(results.as_slice())
} else {
None
}
}
}