Krolyxon
Tag v0.1.0

rmptuisrchandler.rs

429 lines · 15.2 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.first().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.file.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.file.contains(res.first().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.first().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.first().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(
125 app.pl_list.list.get(app.pl_list.index).unwrap(),
126 &app.pl_newname_input,
127 )?;
128 app.pl_list.list = App::get_playlist(&mut app.conn.conn)?;
129 app.pl_newname_input.clear();
130 app.reset_cursor();
131 app.inputmode = InputMode::Normal;
132 }
133
134 KeyCode::Backspace => {
135 app.delete_char();
136 }
137
138 KeyCode::Left => {
139 app.move_cursor_left();
140 }
141
142 KeyCode::Right => {
143 app.move_cursor_right();
144 }
145
146 _ => {}
147 }
148 // Playlist popup keybinds
149 //
150 // Keybind for when the "append to playlist" popup is visible
151 } else if app.playlist_popup {
152 match key_event.code {
153 KeyCode::Char('q') | KeyCode::Esc => {
154 app.playlist_popup = false;
155 }
156
157 KeyCode::Char('j') | KeyCode::Down => app.append_list.next(),
158 KeyCode::Char('k') | KeyCode::Up => app.append_list.prev(),
159
160 KeyCode::Enter => {
161 let pl_index = app.append_list.index;
162 let pl_name = &app.append_list.list.get(pl_index).unwrap();
163
164 let s_index: usize;
165 match app.selected_tab {
166 SelectedTab::Queue => {
167 s_index = app.queue_list.index;
168 let short_path = &app.queue_list.list.get(s_index).unwrap().file;
169
170 if let Some(full_path) = app.conn.get_full_path(short_path) {
171 let song = app.conn.get_song_with_only_filename(&full_path);
172
173 if *pl_name == "Current Playlist" {
174 app.conn.conn.push(&song)?;
175 app.update_queue();
176 } else {
177 app.conn.add_to_playlist(pl_name, &song)?;
178 }
179 }
180 }
181
182 SelectedTab::DirectoryBrowser => {
183 let (t, f) = app.browser.filetree.get(app.browser.selected).unwrap();
184 if t == "file" {
185 let short_path = f;
186 if let Some(full_path) = app.conn.get_full_path(short_path) {
187 let song = app.conn.get_song_with_only_filename(&full_path);
188
189 if *pl_name == "Current Playlist" {
190 app.conn.conn.push(&song)?;
191 app.update_queue();
192 } else {
193 app.conn.add_to_playlist(pl_name, &song)?;
194 }
195 }
196 } else if t == "directory" {
197 for (t, f) in app.conn.conn.listfiles(f)?.iter() {
198 // dir_vec.push((t, f));
199 if t == "file"
200 && Path::new(&f).has_extension(&[
201 "mp3", "ogg", "flac", "m4a", "wav", "aac", "opus", "ape",
202 "wma", "mpc", "aiff", "dff", "mp2", "mka",
203 ])
204 {
205 let full_path = app.conn.get_full_path(f).unwrap_or_default();
206 let song = app.conn.get_song_with_only_filename(&full_path);
207 if *pl_name == "Current Playlist" {
208 app.conn.conn.push(&song)?;
209 } else {
210 app.conn.add_to_playlist(pl_name, &song)?;
211 }
212 }
213 }
214 }
215 }
216 _ => {}
217 }
218
219 // hide the playlist popup
220 app.playlist_popup = false;
221 app.append_list.index = 0;
222 }
223 _ => {}
224 }
225 } else {
226 // Global keymaps
227 //
228 // Keymaps related to all the tabs
229 match key_event.code {
230 // Quit
231 KeyCode::Char('q') => app.quit(),
232 KeyCode::Char('c') | KeyCode::Char('C') => {
233 if key_event.modifiers == KeyModifiers::CONTROL {
234 app.quit();
235 } else {
236 app.conn.conn.clear()?;
237 app.conn.update_status();
238 app.queue_list.list.clear();
239 app.queue_list.reset_index();
240 }
241 }
242
243 // Go Up
244 KeyCode::Char('j') | KeyCode::Down => match app.selected_tab {
245 SelectedTab::DirectoryBrowser => app.browser.next(),
246 SelectedTab::Queue => app.queue_list.next(),
247 SelectedTab::Playlists => app.pl_list.next(),
248 },
249
250 // Go down
251 KeyCode::Char('k') | KeyCode::Up => match app.selected_tab {
252 SelectedTab::DirectoryBrowser => app.browser.prev(),
253 SelectedTab::Queue => app.queue_list.prev(),
254 SelectedTab::Playlists => app.pl_list.prev(),
255 },
256
257 // Next directory
258 KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => {
259 // app.update_queue();
260
261 match app.selected_tab {
262 SelectedTab::DirectoryBrowser => {
263 app.handle_enter()?;
264 }
265
266 SelectedTab::Queue => {
267 app.conn.conn.switch(app.queue_list.index as u32)?;
268 }
269
270 SelectedTab::Playlists => {
271 app.conn
272 .load_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
273 }
274 }
275 app.conn.update_status();
276 }
277
278 // head back to previous directory
279 KeyCode::Char('h') | KeyCode::Left => match app.selected_tab {
280 SelectedTab::DirectoryBrowser => {
281 app.browser.handle_go_back(&mut app.conn)?;
282 }
283 SelectedTab::Queue => {}
284 SelectedTab::Playlists => {}
285 },
286
287 // Playback controls
288 // Toggle Pause
289 KeyCode::Char('p') => app.conn.toggle_pause(),
290
291 // Pause
292 KeyCode::Char('s') => app.conn.pause(),
293
294 // Toggle rpeat
295 KeyCode::Char('r') => {
296 app.conn.toggle_repeat();
297 app.conn.update_status();
298 }
299
300 // Toggle random
301 KeyCode::Char('z') => {
302 app.conn.toggle_random();
303 app.conn.update_status();
304 }
305
306 // Dmenu prompt
307 KeyCode::Char('D') => app.conn.play_dmenu()?,
308
309 // add to queue
310 KeyCode::Char('a') => app.playlist_popup = true,
311
312 // Fast forward
313 KeyCode::Char('f') => {
314 let place = app.conn.conn.status().unwrap().song.unwrap().pos;
315 let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
316 let pos = Duration::from_secs(pos.as_secs().wrapping_add(2));
317 app.conn.conn.seek(place, pos)?;
318 }
319
320 // backward
321 KeyCode::Char('b') => {
322 let place = app.conn.conn.status().unwrap().song.unwrap().pos;
323 let (pos, _) = app.conn.conn.status().unwrap().time.unwrap();
324 let pos = Duration::from_secs(pos.as_secs().wrapping_add(2));
325 app.conn.conn.seek(place, pos)?;
326 }
327
328 // Cycle through tabs
329 KeyCode::Tab => {
330 app.cycle_tabls();
331 }
332
333 // Directory browser tab
334 KeyCode::Char('1') => {
335 app.selected_tab = SelectedTab::Queue;
336 }
337
338 // Playing queue tab
339 KeyCode::Char('2') => {
340 app.selected_tab = SelectedTab::DirectoryBrowser;
341 }
342
343 // Playlists tab
344 KeyCode::Char('3') => {
345 app.selected_tab = SelectedTab::Playlists;
346 }
347
348 // Play next song
349 KeyCode::Char('>') => {
350 if !app.queue_list.list.is_empty() {
351 app.conn.conn.next()?;
352 app.update_queue();
353 }
354 }
355
356 // Play previous song
357 KeyCode::Char('<') => {
358 if !app.queue_list.list.is_empty() {
359 app.conn.conn.prev()?;
360 app.update_queue();
361 }
362 }
363
364 // Volume controls
365 KeyCode::Char('=') => {
366 app.conn.inc_volume(2);
367 app.conn.update_status();
368 }
369
370 KeyCode::Char('-') => {
371 app.conn.dec_volume(2);
372 app.conn.update_status();
373 }
374
375 // Delete highlighted song from the queue
376 KeyCode::Char('d') => {
377 if app.queue_list.index >= app.queue_list.list.len() - 1
378 && app.queue_list.index != 0
379 {
380 app.queue_list.index -= 1;
381 }
382
383 app.conn.conn.delete(app.queue_list.index as u32)?;
384 app.update_queue();
385 }
386
387 // Update MPD database
388 KeyCode::Char('U') => {
389 app.conn.conn.rescan()?;
390 app.browser.update_directory(&mut app.conn)?;
391 }
392
393 // Search for songs
394 KeyCode::Char('/') => {
395 if app.inputmode == InputMode::Normal {
396 app.inputmode = InputMode::Editing;
397 } else {
398 app.inputmode = InputMode::Normal;
399 }
400 }
401
402 // Remove from Current Playlsit
403 KeyCode::Char(' ') | KeyCode::Backspace => {
404 app.handle_add_or_remove_from_current_playlist()?;
405 }
406
407 // go to top of list
408 KeyCode::Char('g') => match app.selected_tab {
409 SelectedTab::Queue => app.queue_list.index = 0,
410 SelectedTab::DirectoryBrowser => app.browser.selected = 0,
411 SelectedTab::Playlists => app.pl_list.index = 0,
412 },
413
414 // go to bottom of list
415 KeyCode::Char('G') => match app.selected_tab {
416 SelectedTab::Queue => app.queue_list.index = app.queue_list.list.len() - 1,
417 SelectedTab::DirectoryBrowser => {
418 app.browser.selected = app.browser.filetree.len() - 1
419 }
420 SelectedTab::Playlists => app.pl_list.index = app.pl_list.list.len() - 1,
421 },
422
423 // Change playlist name
424 KeyCode::Char('e') => app.change_playlist_name()?,
425 _ => {}
426 }
427 }
428 Ok(())
429}