1use crate::i18n::Locale;
9use orbok_models::SearchCapability;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum ViewId {
14 Search,
15 Sources,
16 Indexing,
17 Storage,
18 Models,
19 Settings,
20}
21
22impl ViewId {
23 pub const ALL: &'static [ViewId] = &[
24 ViewId::Search,
25 ViewId::Sources,
26 ViewId::Indexing,
27 ViewId::Storage,
28 ViewId::Models,
29 ViewId::Settings,
30 ];
31}
32
33#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
35pub struct IndexHealth {
36 pub indexed: u64,
37 pub stale: u64,
38 pub failed: u64,
39 pub queued: u64,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct SourceCard {
45 pub display_name: String,
46 pub display_path: String,
47 pub indexed: u64,
48 pub stale: u64,
49 pub failed: u64,
50 pub active: bool,
51}
52
53#[derive(Debug, Clone, PartialEq)]
56pub struct SearchResultDisplay {
57 pub display_path: String,
58 pub title: Option<String>,
59 pub heading_path: Option<String>,
60 pub snippet: Option<String>,
61 pub keyword_rank: u32,
62 pub badges: Vec<String>,
63}
64
65#[derive(Debug, Clone)]
67pub struct AppState {
68 pub active_view: ViewId,
69 pub locale: Locale,
70 pub query: String,
71 pub last_query: Option<String>,
72 pub search_results: Vec<SearchResultDisplay>,
73 pub search_running: bool,
74 pub health: IndexHealth,
75 pub sources: Vec<SourceCard>,
76 pub capability: SearchCapability,
77 pub storage_total_bytes: u64,
78}
79
80impl Default for AppState {
81 fn default() -> Self {
82 Self {
83 active_view: ViewId::Search,
84 locale: Locale::default(),
85 query: String::new(),
86 last_query: None,
87 search_results: Vec::new(),
88 search_running: false,
89 health: IndexHealth::default(),
90 sources: Vec::new(),
91 capability: SearchCapability::KeywordOnly,
92 storage_total_bytes: 0,
93 }
94 }
95}
96
97#[derive(Debug, Clone)]
99pub enum Message {
100 Switch(ViewId),
101 QueryChanged(String),
102 SubmitSearch,
103 SearchResultsReady(Vec<SearchResultDisplay>),
104 SearchError(String),
105 SetLocale(Locale),
106}
107
108impl AppState {
109 pub fn update(&mut self, message: &Message) {
110 match message {
111 Message::Switch(view) => self.active_view = *view,
112 Message::QueryChanged(query) => self.query = query.clone(),
113 Message::SubmitSearch => {
114 let trimmed = self.query.trim();
115 if !trimmed.is_empty() {
116 self.last_query = Some(trimmed.to_string());
117 self.search_running = true;
118 self.search_results.clear();
119 }
120 }
121 Message::SearchResultsReady(results) => {
122 self.search_results = results.clone();
123 self.search_running = false;
124 }
125 Message::SearchError(_) => {
126 self.search_running = false;
127 }
128 Message::SetLocale(locale) => self.locale = *locale,
129 }
130 }
131}