Krolyxon
Commit c047f63

rmptuisrchandler.rs

381 lines · 13.7 KB · Rust

1use crate::browser::FileExtension;
2use std::{path::Path, time::Duration};
3
4use crate::{
5 app::{App, AppResult, SelectedTab},
6 ui::InputMode,
7};
8use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
9use rust_fuzzy_search::{self, fuzzy_search_sorted};
10
11pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
12 if app.inputmode == InputMode::Editing {
13 // Live search update
14 match app.selected_tab {
15 SelectedTab::DirectoryBrowser => {
16 let list: Vec<&str> = app
17 .browser
18 .filetree
19 .iter()
20 .map(|(_, f)| f.as_str())
21 .collect::<Vec<&str>>();
22
23 let res: Vec<(&str, f32)> = fuzzy_search_sorted(&app.search_input, &list);
24 let res = res.iter().map(|(x, _)| *x).collect::<Vec<&str>>();
25
26 for (i, (_, item)) in app.browser.filetree.iter().enumerate() {
27 if item.contains(res.get(0).unwrap()) {
28 app.browser.selected = i;
29 }
30 }
31 }
32
33 SelectedTab::Queue => {
34 let list: Vec<&str> = app
35 .queue_list
36 .list
37 .iter()
38 .map(|f| f.as_str())
39 .collect::<Vec<&str>>();
40 let res: Vec<(&str, f32)> = fuzzy_search_sorted(&app.search_input, &list);
41 let res = res.iter().map(|(x, _)| *x).collect::<Vec<&str>>();
42
43 for (i, item) in app.queue_list.list.iter().enumerate() {
44 if item.contains(res.get(0).unwrap()) {
45 app.queue_list.index = i;
46 }
47 }
48 }
49
50 SelectedTab::Playlists => {
51 let list: Vec<&str> = app
52 .pl_list
53 .list
54 .iter()
55 .map(|f| f.as_str())
56 .collect::<Vec<&str>>();
57 let res: Vec<(&str, f32)> = fuzzy_search_sorted(&app.search_input, &list);
58 let res = res.iter().map(|(x, _)| *x).collect::<Vec<&str>>();
59
60 for (i, item) in app.pl_list.list.iter().enumerate() {
61 if item.contains(res.get(0).unwrap()) {
62 app.pl_list.index = i;
63 }
64 }
65 }
66 }
67
68 match key_event.code {
69 KeyCode::Esc => {
70 app.inputmode = InputMode::Normal;
71 }
72 KeyCode::Char(to_insert) => {
73 app.enter_char(to_insert);
74 }
75 KeyCode::Enter => {
76 let list: Vec<&str> = app
77 .browser
78 .filetree
79 .iter()
80 .map(|(_, f)| f.as_str())
81 .collect::<Vec<&str>>();
82
83 let res: Vec<(&str, f32)> = fuzzy_search_sorted(&app.search_input, &list);
84 let (res, _) = res.get(0).unwrap();
85
86 for (i, (_, item)) in app.browser.filetree.iter().enumerate() {
87 if item.contains(res) {
88 app.browser.selected = i;
89 }
90 }
91
92 app.search_input.clear();
93 app.inputmode = InputMode::Normal;
94 app.reset_cursor();
95 }
96
97 KeyCode::Backspace => {
98 app.delete_char();
99 }
100
101 KeyCode::Left => {
102 app.move_cursor_left();
103 }
104
105 KeyCode::Right => {
106 app.move_cursor_right();
107 }
108
109 _ => {}
110 }
111 } else if app.playlist_popup {
112 match key_event.code {
113 KeyCode::Char('q') | KeyCode::Esc => {
114 app.playlist_popup = false;
115 }
116
117 KeyCode::Char('j') | KeyCode::Down => app.append_list.next(),
118 KeyCode::Char('k') | KeyCode::Up => app.append_list.prev(),
119
120 KeyCode::Enter => {
121 let pl_index = app.append_list.index;
122 let pl_name = &app.append_list.list.get(pl_index).unwrap();
123
124 let s_index: usize;
125 match app.selected_tab {
126 SelectedTab::Queue => {
127 s_index = app.queue_list.index;
128 let short_path = app.queue_list.list.get(s_index).unwrap().to_string();
129
130 if let Some(full_path) = app.conn.get_full_path(&short_path) {
131 let song = app.conn.get_song_with_only_filename(&full_path);
132
133 if pl_name.to_string() == "Current Playlist" {
134 app.conn.conn.push(&song)?;
135 app.update_queue();
136 } else {
137 app.conn.add_to_playlist(pl_name, &song)?;
138 }
139 }
140 }
141
142 SelectedTab::DirectoryBrowser => {
143 let (t, f) = app.browser.filetree.get(app.browser.selected).unwrap();
144 if t == "file" {
145 let short_path = f;
146 if let Some(full_path) = app.conn.get_full_path(short_path) {
147 let song = app.conn.get_song_with_only_filename(&full_path);
148
149 if pl_name.to_string() == "Current Playlist" {
150 app.conn.conn.push(&song)?;
151 app.update_queue();
152 } else {
153 app.conn.add_to_playlist(pl_name, &song)?;
154 }
155 }
156 } else if t == "directory" {
157 for (t, f) in app.conn.conn.listfiles(f)?.iter() {
158 // dir_vec.push((t, f));
159 if t == "file"
160 && Path::new(&f).has_extension(&[
161 "mp3", "ogg", "flac", "m4a", "wav", "aac", "opus", "ape",
162 "wma", "mpc", "aiff", "dff", "mp2", "mka",
163 ])
164 {
165 let full_path = app.conn.get_full_path(&f).unwrap_or_default();
166 let song = app.conn.get_song_with_only_filename(&full_path);
167 if pl_name.to_string() == "Current Playlist" {
168 app.conn.conn.push(&song)?;
169 } else {
170 app.conn.add_to_playlist(pl_name, &song)?;
171 }
172 }
173 }
174 }
175 }
176 _ => {}
177 }
178
179 // hide the playlist popup
180 app.playlist_popup = false;
181 app.append_list.index = 0;
182 }
183 _ => {}
184 }
185 } else {
186 match key_event.code {
187 // Quit
188 KeyCode::Char('q') => app.quit(),
189 KeyCode::Char('c') | KeyCode::Char('C') => {
190 if key_event.modifiers == KeyModifiers::CONTROL {
191 app.quit();
192 } else {
193 app.conn.conn.clear()?;
194 app.conn.update_status();
195 app.queue_list.list.clear();
196 app.queue_list.reset_index();
197 }
198 }
199
200 // Go Up
201 KeyCode::Char('j') | KeyCode::Down => match app.selected_tab {
202 SelectedTab::DirectoryBrowser => app.browser.next(),
203 SelectedTab::Queue => app.queue_list.next(),
204 SelectedTab::Playlists => app.pl_list.next(),
205 },
206
207 // Go down
208 KeyCode::Char('k') | KeyCode::Up => match app.selected_tab {
209 SelectedTab::DirectoryBrowser => app.browser.prev(),
210 SelectedTab::Queue => app.queue_list.prev(),
211 SelectedTab::Playlists => app.pl_list.prev(),
212 },
213
214 // Next directory
215 KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => {
216 // app.update_queue();
217
218 match app.selected_tab {
219 SelectedTab::DirectoryBrowser => {
220 app.handle_enter()?;
221 }
222
223 SelectedTab::Queue => {
224 app.conn.conn.switch(app.queue_list.index as u32)?;
225 }
226
227 SelectedTab::Playlists => {
228 app.conn
229 .load_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
230 }
231 }
232 app.conn.update_status();
233 }
234
235 // head back to previous directory
236 KeyCode::Char('h') | KeyCode::Left => match app.selected_tab {
237 SelectedTab::DirectoryBrowser => {
238 app.browser.handle_go_back(&mut app.conn)?;
239 }
240 SelectedTab::Queue => {}
241 SelectedTab::Playlists => {}
242 },
243
244 // Playback controls
245 // Toggle Pause
246 KeyCode::Char('p') => app.conn.toggle_pause(),
247
248 // Pause
249 KeyCode::Char('s') => app.conn.pause(),
250
251 // Toggle rpeat
252 KeyCode::Char('r') => {
253 app.conn.toggle_repeat();
254 app.conn.update_status();
255 }
256
257 // Toggle random
258 KeyCode::Char('z') => {
259 app.conn.toggle_random();
260 app.conn.update_status();
261 }
262
263 // Dmenu prompt
264 KeyCode::Char('D') => app.conn.play_dmenu()?,
265
266 // add to queue
267 KeyCode::Char('a') => app.playlist_popup = true,
268
269 // Fast forward
270 KeyCode::Char('f') => {
271 let place = app.conn.conn.status().unwrap().song.unwrap().pos;
272 let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
273 let pos = Duration::from_secs(pos.as_secs().wrapping_add(2));
274 app.conn.conn.seek(place, pos)?;
275 }
276
277 // backward
278 KeyCode::Char('b') => {
279 let place = app.conn.conn.status().unwrap().song.unwrap().pos;
280 let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
281 let pos = Duration::from_secs(pos.as_secs().wrapping_add(2));
282 app.conn.conn.seek(place, pos)?;
283 }
284
285 // Cycle through tabs
286 KeyCode::Tab => {
287 app.cycle_tabls();
288 }
289
290 // Directory browser tab
291 KeyCode::Char('1') => {
292 app.selected_tab = SelectedTab::Queue;
293 }
294
295 // Playing queue tab
296 KeyCode::Char('2') => {
297 app.selected_tab = SelectedTab::DirectoryBrowser;
298 }
299
300 // Playlists tab
301 KeyCode::Char('3') => {
302 app.selected_tab = SelectedTab::Playlists;
303 }
304
305 // Play next song
306 KeyCode::Char('>') => {
307 if !app.queue_list.list.is_empty() {
308 app.conn.conn.next()?;
309 app.update_queue();
310 }
311 }
312
313 // Play previous song
314 KeyCode::Char('<') => {
315 if !app.queue_list.list.is_empty() {
316 app.conn.conn.prev()?;
317 app.update_queue();
318 }
319 }
320
321 // Volume controls
322 KeyCode::Char('=') => {
323 app.conn.inc_volume(2);
324 app.conn.update_status();
325 }
326
327 KeyCode::Char('-') => {
328 app.conn.dec_volume(2);
329 app.conn.update_status();
330 }
331
332 // Delete highlighted song from the queue
333 KeyCode::Char('d') => {
334 if app.queue_list.index >= app.queue_list.list.len() - 1 {
335 if app.queue_list.index != 0 {
336 app.queue_list.index -= 1;
337 }
338 }
339
340 app.conn.conn.delete(app.queue_list.index as u32)?;
341 app.update_queue();
342 }
343
344 // Update MPD database
345 KeyCode::Char('U') => {
346 app.conn.conn.update()?;
347 }
348
349 // Search for songs
350 KeyCode::Char('/') => {
351 app.inputmode = InputMode::toggle_editing_states(&app.inputmode);
352 }
353
354 // Remove from Current Playlsit
355 KeyCode::Char(' ') | KeyCode::Backspace => {
356 app.handle_add_or_remove_from_current_playlist()?;
357 }
358
359 // Change playlist name
360 KeyCode::Char('e') => if app.selected_tab == SelectedTab::Playlists {},
361
362 // go to top of list
363 KeyCode::Char('g') => match app.selected_tab {
364 SelectedTab::Queue => app.queue_list.index = 0,
365 SelectedTab::DirectoryBrowser => app.browser.selected = 0,
366 SelectedTab::Playlists => app.pl_list.index = 0,
367 },
368
369 // go to bottom of list
370 KeyCode::Char('G') => match app.selected_tab {
371 SelectedTab::Queue => app.queue_list.index = app.queue_list.list.len() - 1,
372 SelectedTab::DirectoryBrowser => {
373 app.browser.selected = app.browser.filetree.len() - 1
374 }
375 SelectedTab::Playlists => app.pl_list.index = app.pl_list.list.len() - 1,
376 },
377 _ => {}
378 }
379 }
380 Ok(())
381}