//! 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 { // === 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); /// 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; /// 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; /// Get all search results fn get_search_results(&self) -> Option<&[MessageInfo]>; } impl SearchMethods for App { 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) { 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 { 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 { 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 } } }