Krolyxon
Commit 32a3c60

rmptuisrchandler.rs

426 lines · 15.1 KB · Rust

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