state.rs (3426B)
1 use crate::timeline::TimelineTab; 2 use enostr::Pubkey; 3 use notedeck_ui::ProfileSearchResult; 4 5 use super::SearchType; 6 7 #[derive(Debug, Eq, PartialEq)] 8 pub enum SearchState { 9 Typing(TypingType), 10 PerformSearch(SearchType), 11 Searched, 12 Navigating, 13 New, 14 } 15 16 #[derive(Debug, Eq, PartialEq)] 17 pub enum TypingType { 18 Mention(String), 19 } 20 21 #[derive(Debug, Clone)] 22 pub enum RecentSearchItem { 23 Query(String), 24 Profile { pubkey: Pubkey, query: String }, 25 } 26 27 #[derive(Debug, Eq, PartialEq, Clone, Default)] 28 pub enum FocusState { 29 /// Get ready to focus 30 Navigating, 31 32 /// We should request focus when we stop navigating 33 ShouldRequestFocus, 34 35 /// We already focused, we don't need to do that again 36 #[default] 37 RequestedFocus, 38 } 39 40 /// Search query state that exists between frames 41 #[derive(Debug)] 42 pub struct SearchQueryState { 43 /// This holds our search query while we're updating it 44 pub string: String, 45 46 /// Current search state 47 pub state: SearchState, 48 49 /// A bit of context to know if we're navigating to the view. We 50 /// can use this to know when to request focus on the textedit 51 pub focus_state: FocusState, 52 53 /// The search results 54 pub notes: TimelineTab, 55 56 /// Currently selected item index in search results (-1 = none, 0 = "search posts", 1+ = users) 57 pub selected_index: i32, 58 59 /// Cached user search results for the current query 60 pub user_results: Vec<Vec<u8>>, 61 62 /// Recent search history (most recent first, max 10) 63 pub recent_searches: Vec<RecentSearchItem>, 64 65 /// Cached @mention search results 66 pub mention_results: Vec<ProfileSearchResult>, 67 68 /// The query string that produced `mention_results` 69 pub last_mention_query: String, 70 } 71 72 impl Default for SearchQueryState { 73 fn default() -> Self { 74 SearchQueryState::new() 75 } 76 } 77 78 impl SearchQueryState { 79 pub fn new() -> Self { 80 Self { 81 string: "".to_string(), 82 state: SearchState::New, 83 notes: TimelineTab::default(), 84 focus_state: FocusState::Navigating, 85 selected_index: -1, 86 user_results: Vec::new(), 87 recent_searches: Vec::new(), 88 mention_results: Vec::new(), 89 last_mention_query: String::new(), 90 } 91 } 92 93 pub fn add_recent_query(&mut self, query: String) { 94 if query.is_empty() { 95 return; 96 } 97 98 let item = RecentSearchItem::Query(query.clone()); 99 self.recent_searches 100 .retain(|s| !matches!(s, RecentSearchItem::Query(q) if q == &query)); 101 self.recent_searches.insert(0, item); 102 self.recent_searches.truncate(10); 103 } 104 105 pub fn add_recent_profile(&mut self, pubkey: Pubkey, query: String) { 106 if query.is_empty() { 107 return; 108 } 109 110 let item = RecentSearchItem::Profile { 111 pubkey, 112 query: query.clone(), 113 }; 114 self.recent_searches.retain( 115 |s| !matches!(s, RecentSearchItem::Profile { pubkey: pk, .. } if pk == &pubkey), 116 ); 117 self.recent_searches.insert(0, item); 118 self.recent_searches.truncate(10); 119 } 120 121 pub fn remove_recent_search(&mut self, index: usize) { 122 if index < self.recent_searches.len() { 123 self.recent_searches.remove(index); 124 } 125 } 126 127 pub fn clear_recent_searches(&mut self) { 128 self.recent_searches.clear(); 129 } 130 }