1use {
2 crate::{
3 action::{Action, OpenProxyStep, TuiAction},
4 config::{self, LAST_PROXY_URL},
5 input::KeyCode,
6 logger::*,
7 theme::THEME,
8 },
9 glues_core::EntryEvent,
10 ratatui::{style::Stylize, text::Line, widgets::ListState},
11};
12
13#[cfg(target_arch = "wasm32")]
14use crate::config::LAST_IDB_NAMESPACE;
15
16#[cfg(not(target_arch = "wasm32"))]
17use crate::{
18 action::{OpenGitStep, OpenMongoStep},
19 config::{LAST_FILE_PATH, LAST_GIT_PATH, LAST_MONGO_CONN_STR, LAST_REDB_PATH},
20};
21
22pub const INSTANT: &str = "[i] Instant";
23#[cfg(target_arch = "wasm32")]
24pub const INDEXED_DB: &str = "[d] IndexedDB";
25#[cfg(not(target_arch = "wasm32"))]
26pub const FILE: &str = "[l] Local";
27#[cfg(not(target_arch = "wasm32"))]
28pub const REDB: &str = "[r] redb";
29#[cfg(not(target_arch = "wasm32"))]
30pub const GIT: &str = "[g] Git";
31#[cfg(not(target_arch = "wasm32"))]
32pub const MONGO: &str = "[m] MongoDB";
33#[cfg(target_arch = "wasm32")]
34pub const PROXY: &str = "[p] Proxy";
35#[cfg(not(target_arch = "wasm32"))]
36pub const PROXY: &str = "[p] Proxy";
37pub const HELP: &str = "[h] Help";
38pub const THEME_MENU: &str = "[t] Theme";
39pub const QUIT: &str = "[q] Quit";
40
41#[cfg(not(target_arch = "wasm32"))]
42pub const MENU_ITEMS: [&str; 9] = [
43 INSTANT, FILE, REDB, GIT, MONGO, PROXY, HELP, THEME_MENU, QUIT,
44];
45#[cfg(target_arch = "wasm32")]
46pub const MENU_ITEMS: [&str; 5] = [INSTANT, INDEXED_DB, PROXY, HELP, THEME_MENU];
47
48pub struct EntryContext {
49 pub list_state: ListState,
50}
51
52impl Default for EntryContext {
53 fn default() -> Self {
54 Self {
55 list_state: ListState::default().with_selected(Some(0)),
56 }
57 }
58}
59
60impl EntryContext {
61 pub async fn consume(&mut self, code: KeyCode) -> Action {
62 #[cfg(not(target_arch = "wasm32"))]
63 let open = |key, action: TuiAction| async move {
64 TuiAction::Prompt {
65 message: vec![
66 Line::raw("Enter the path:"),
67 Line::from("If the path does not exist, it will be created.".fg(THEME.hint)),
68 ],
69 action: Box::new(action.into()),
70 default: config::get(key).await,
71 }
72 .into()
73 };
74
75 #[cfg(not(target_arch = "wasm32"))]
76 let open_redb = || async move {
77 TuiAction::Prompt {
78 message: vec![
79 Line::raw("Provide the redb database path:"),
80 Line::from(
81 "Glues will create or reuse the single-file redb database.".fg(THEME.hint),
82 ),
83 ],
84 action: Box::new(TuiAction::OpenRedb.into()),
85 default: config::get(LAST_REDB_PATH).await,
86 }
87 .into()
88 };
89
90 #[cfg(target_arch = "wasm32")]
91 let open_indexed_db = || async move {
92 TuiAction::Prompt {
93 message: vec![
94 Line::raw("Enter the IndexedDB namespace:"),
95 Line::from("Leave empty to use the default namespace (glues).".fg(THEME.hint)),
96 ],
97 action: Box::new(TuiAction::OpenIndexedDb.into()),
98 default: config::get(LAST_IDB_NAMESPACE).await,
99 }
100 .into()
101 };
102
103 #[cfg(not(target_arch = "wasm32"))]
104 let open_git = || async move {
105 TuiAction::Prompt {
106 message: vec![
107 Line::raw("Enter the git repository path:"),
108 Line::from("The path must contain an existing .git repository.".fg(THEME.hint)),
109 Line::from("otherwise, an error will occur.".fg(THEME.hint)),
110 ],
111 action: Box::new(TuiAction::OpenGit(OpenGitStep::Path).into()),
112 default: config::get(LAST_GIT_PATH).await,
113 }
114 .into()
115 };
116
117 #[cfg(not(target_arch = "wasm32"))]
118 let open_mongo = || async move {
119 TuiAction::Prompt {
120 message: vec![
121 Line::raw("Enter the MongoDB connection string:"),
122 Line::from("e.g. mongodb://localhost:27017".fg(THEME.hint)),
123 ],
124 action: Box::new(TuiAction::OpenMongo(OpenMongoStep::ConnStr).into()),
125 default: config::get(LAST_MONGO_CONN_STR).await,
126 }
127 .into()
128 };
129
130 let open_proxy = || async move {
131 TuiAction::Prompt {
132 message: vec![
133 Line::raw("Enter the proxy server URL:"),
134 Line::from("e.g. http://127.0.0.1:4000".fg(THEME.hint)),
135 ],
136 action: Box::new(TuiAction::OpenProxy(OpenProxyStep::Url).into()),
137 default: config::get(LAST_PROXY_URL).await,
138 }
139 .into()
140 };
141
142 match code {
143 #[cfg(not(target_arch = "wasm32"))]
144 KeyCode::Char('q') => TuiAction::Quit.into(),
145 KeyCode::Char('j') | KeyCode::Down => {
146 self.list_state.select_next();
147 Action::None
148 }
149 KeyCode::Char('k') | KeyCode::Up => {
150 self.list_state.select_previous();
151 Action::None
152 }
153 KeyCode::Char('i') => EntryEvent::OpenMemory.into(),
154 #[cfg(target_arch = "wasm32")]
155 KeyCode::Char('d') => open_indexed_db().await,
156 #[cfg(not(target_arch = "wasm32"))]
157 KeyCode::Char('l') => open(LAST_FILE_PATH, TuiAction::OpenFile).await,
158 #[cfg(not(target_arch = "wasm32"))]
159 KeyCode::Char('r') => open_redb().await,
160 #[cfg(not(target_arch = "wasm32"))]
161 KeyCode::Char('g') => open_git().await,
162 #[cfg(not(target_arch = "wasm32"))]
163 KeyCode::Char('m') => open_mongo().await,
164 KeyCode::Char('p') => open_proxy().await,
165 KeyCode::Char('h') => TuiAction::Help.into(),
166 KeyCode::Char('t') => TuiAction::OpenThemeMenu.into(),
167
168 KeyCode::Enter => {
169 let i = self
170 .list_state
171 .selected()
172 .log_expect("EntryContext::consume: selected is None. This should not happen.");
173 match MENU_ITEMS[i] {
174 INSTANT => EntryEvent::OpenMemory.into(),
175 #[cfg(target_arch = "wasm32")]
176 INDEXED_DB => open_indexed_db().await,
177 #[cfg(not(target_arch = "wasm32"))]
178 FILE => open(LAST_FILE_PATH, TuiAction::OpenFile).await,
179 #[cfg(not(target_arch = "wasm32"))]
180 REDB => open_redb().await,
181 #[cfg(not(target_arch = "wasm32"))]
182 GIT => open_git().await,
183 #[cfg(not(target_arch = "wasm32"))]
184 MONGO => open_mongo().await,
185 PROXY => open_proxy().await,
186 HELP => TuiAction::Help.into(),
187 THEME_MENU => TuiAction::OpenThemeMenu.into(),
188 #[cfg(not(target_arch = "wasm32"))]
189 QUIT => TuiAction::Quit.into(),
190 _ => Action::None,
191 }
192 }
193 _ => Action::PassThrough,
194 }
195 }
196}