Krolyxon
Commit 412e00f

rmptuisrchandler.rs

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