carch_core/ui/
state.rs

1use std::collections::HashMap;
2use std::path::PathBuf;
3
4use fuzzy_matcher::skim::SkimMatcherV2;
5use ratatui::layout::Rect;
6use ratatui::text::Text;
7
8use super::popups::run_script::RunScriptPopup;
9use super::theme::Theme;
10
11#[derive(PartialEq, Debug, Clone, Copy)]
12pub enum AppMode {
13    Normal,
14    Search,
15    Confirm,
16    Help,
17    Preview,
18    RunScript,
19    Description,
20    RootWarning,
21}
22
23#[derive(PartialEq, Debug, Clone, Copy)]
24pub enum FocusedPanel {
25    Categories,
26    Scripts,
27}
28
29pub struct StatefulList<T> {
30    pub state: ratatui::widgets::ListState,
31    pub items: Vec<T>,
32}
33
34impl<T> Default for StatefulList<T> {
35    fn default() -> Self {
36        Self::new()
37    }
38}
39
40impl<T> StatefulList<T> {
41    pub fn new() -> StatefulList<T> {
42        StatefulList { state: ratatui::widgets::ListState::default(), items: Vec::new() }
43    }
44
45    pub fn with_items(items: Vec<T>) -> StatefulList<T> {
46        let mut list = StatefulList::new();
47        list.items = items;
48        if !list.items.is_empty() {
49            list.state.select(Some(0));
50        }
51        list
52    }
53
54    pub fn next(&mut self) {
55        let i = match self.state.selected() {
56            Some(i) => {
57                if i >= self.items.len() - 1 {
58                    0
59                } else {
60                    i + 1
61                }
62            }
63            None => 0,
64        };
65        self.state.select(Some(i));
66    }
67
68    pub fn previous(&mut self) {
69        let i = match self.state.selected() {
70            Some(i) => {
71                if i == 0 {
72                    self.items.len() - 1
73                } else {
74                    i - 1
75                }
76            }
77            None => 0,
78        };
79        self.state.select(Some(i));
80    }
81}
82
83#[derive(Clone, Debug)]
84pub struct ScriptItem {
85    pub category: String,
86    pub name:     String,
87    pub path:     PathBuf,
88}
89
90#[derive(Default, Clone)]
91pub struct UiOptions {
92    pub log_mode:     bool,
93    pub theme:        String,
94    pub theme_locked: bool,
95    pub is_root:      bool,
96}
97
98#[derive(Default)]
99pub struct PreviewState<'a> {
100    pub content:    String,
101    pub scroll:     u16,
102    pub max_scroll: u16,
103    pub cache:      HashMap<PathBuf, Text<'a>>,
104}
105
106#[derive(Clone, Debug)]
107pub struct SearchResult {
108    pub item:    ScriptItem,
109    pub score:   i64,
110    pub indices: Vec<usize>,
111}
112
113#[derive(Default)]
114pub struct SearchState {
115    pub input:           String,
116    pub results:         Vec<SearchResult>,
117    pub cursor_position: usize,
118    pub selected_idx:    usize,
119    pub autocomplete:    Option<String>,
120    pub matcher:         SkimMatcherV2,
121}
122
123#[derive(Default)]
124pub struct MultiSelectState {
125    pub enabled: bool,
126    pub scripts: Vec<PathBuf>,
127}
128
129#[derive(Default)]
130pub struct HelpState {
131    pub scroll:     u16,
132    pub max_scroll: u16,
133}
134
135#[derive(Default)]
136pub struct DescriptionState {
137    pub content:    Option<String>,
138    pub scroll:     u16,
139    pub max_scroll: u16,
140}
141
142pub struct App<'a> {
143    pub mode:          AppMode,
144    pub quit:          bool,
145    pub focused_panel: FocusedPanel,
146    pub log_mode:      bool,
147    pub modules_dir:   PathBuf,
148    pub theme:         Theme,
149    pub theme_locked:  bool,
150
151    pub scripts:     StatefulList<ScriptItem>,
152    pub categories:  StatefulList<String>,
153    pub all_scripts: HashMap<String, Vec<ScriptItem>>,
154
155    pub script_panel_area:      Rect,
156    pub preview:                PreviewState<'a>,
157    pub search:                 SearchState,
158    pub multi_select:           MultiSelectState,
159    pub help:                   HelpState,
160    pub description:            DescriptionState,
161    pub run_script_popup:       Option<RunScriptPopup>,
162    pub script_execution_queue: Vec<PathBuf>,
163}