Krolyxon
Tag v0.1.5

rmptuisrceventhandler.rs

332 lines · 11.7 KB · Rust

1use crate::{
2 app::{App, AppResult, SelectedTab},
3 connection::VolumeStatus,
4 ui::InputMode,
5};
6use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind};
7use std::time::Duration;
8
9use super::{pl_append_keys, pl_rename_keys, search_keys};
10
11pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
12 // searching, playlist renaming, playlist appending
13 if app.inputmode == InputMode::Editing {
14 search_keys::handle_search_keys(key_event, app)?;
15 } else if app.inputmode == InputMode::PlaylistRename {
16 pl_rename_keys::handle_pl_rename_keys(key_event, app)?;
17 } else if app.playlist_popup {
18 pl_append_keys::hande_pl_append_keys(key_event, app)?;
19 } else {
20 // General KeyMaps
21 match key_event.code {
22 // Quit
23 KeyCode::Char('q') => app.quit(),
24 KeyCode::Char('c') | KeyCode::Char('C') => {
25 if key_event.modifiers == KeyModifiers::CONTROL {
26 app.quit();
27 } else {
28 app.conn.conn.clear()?;
29 app.conn.update_status();
30 app.queue_list.list.clear();
31 app.queue_list.reset_index();
32 }
33 }
34
35 // Playback controls
36 // Toggle Pause
37 KeyCode::Char('p') => {
38 app.conn.toggle_pause();
39 app.conn.update_status();
40 }
41
42 // Pause
43 KeyCode::Char('s') => {
44 app.conn.pause();
45 app.conn.update_status();
46 }
47
48 // Toggle rpeat
49 KeyCode::Char('r') => {
50 app.conn.toggle_repeat();
51 app.conn.update_status();
52 }
53
54 // Toggle random
55 KeyCode::Char('z') => {
56 app.conn.toggle_random();
57 app.conn.update_status();
58 }
59
60 // Dmenu prompt
61 KeyCode::Char('D') => {
62 app.conn.play_dmenu()?;
63 app.conn.update_status();
64 }
65
66 // add to queue
67 KeyCode::Char('a') => app.playlist_popup = true,
68
69 // Fast forward
70 KeyCode::Char('f') => {
71 if !app.queue_list.list.is_empty() {
72 let status = app.conn.conn.status().unwrap_or_default();
73 let place = status.song.unwrap_or_default().pos;
74 let (pos, _) = status.time.unwrap_or_default();
75 let pos = Duration::from_secs(pos.as_secs().wrapping_add(2));
76 app.conn.conn.seek(place, pos)?;
77 app.conn.update_status();
78 }
79 }
80
81 // backward
82 KeyCode::Char('b') => {
83 if !app.queue_list.list.is_empty() {
84 let status = app.conn.conn.status().unwrap_or_default();
85 let place = status.song.unwrap_or_default().pos;
86 let (pos, _) = status.time.unwrap_or_default();
87 let pos = Duration::from_secs(pos.as_secs().wrapping_sub(2));
88 app.conn.conn.seek(place, pos)?;
89 app.conn.update_status();
90 }
91 }
92
93 // Cycle through tabs
94 KeyCode::Tab => {
95 app.cycle_tabls();
96 }
97
98 // Directory browser tab
99 KeyCode::Char('1') => {
100 app.selected_tab = SelectedTab::Queue;
101 }
102
103 // Playing queue tab
104 KeyCode::Char('2') => {
105 app.selected_tab = SelectedTab::DirectoryBrowser;
106 }
107
108 // Playlists tab
109 KeyCode::Char('3') => {
110 app.selected_tab = SelectedTab::Playlists;
111 }
112
113 // Play next song
114 KeyCode::Char('>') => {
115 if !app.queue_list.list.is_empty() {
116 app.conn.conn.next()?;
117 app.update_queue();
118 app.conn.update_status();
119 }
120 }
121
122 // Play previous song
123 KeyCode::Char('<') => {
124 if !app.queue_list.list.is_empty() {
125 app.conn.conn.prev()?;
126 app.update_queue();
127 app.conn.update_status();
128 }
129 }
130
131 // Volume controls
132 KeyCode::Char('=') | KeyCode::Char('+') => {
133 app.conn.inc_volume(2);
134 app.conn.update_status();
135 }
136
137 KeyCode::Char('-') => {
138 app.conn.dec_volume(2);
139 app.conn.update_status();
140 }
141
142 // Toggle Mute
143 KeyCode::Char('m') => {
144 match app.conn.volume_status {
145 VolumeStatus::Muted(v) => {
146 app.conn.conn.volume(v)?;
147 app.conn.volume_status = VolumeStatus::Unmuted;
148 }
149 VolumeStatus::Unmuted => {
150 let current_volume = app.conn.status.volume;
151 app.conn.conn.volume(0)?;
152 app.conn.volume_status = VolumeStatus::Muted(current_volume);
153 }
154 }
155 app.conn.update_status();
156 }
157
158 // Update MPD database
159 KeyCode::Char('U') => {
160 app.conn.conn.rescan()?;
161 app.should_update_song_list = true;
162 }
163
164 // Search for songs
165 KeyCode::Char('/') => {
166 if app.inputmode == InputMode::Normal {
167 app.inputmode = InputMode::Editing;
168 } else {
169 app.inputmode = InputMode::Normal;
170 }
171 }
172
173 // Add or Remove from Current Playlist
174 KeyCode::Char(' ') => {
175 app.handle_add_or_remove_from_current_playlist()?;
176 }
177 _ => {}
178 }
179
180 // Tab specific keymaps
181 match app.selected_tab {
182 SelectedTab::Queue => {
183 match key_event.code {
184 // Go Up
185 KeyCode::Char('j') | KeyCode::Down => app.queue_list.next(),
186
187 // Go down
188 KeyCode::Char('k') | KeyCode::Up => app.queue_list.prev(),
189
190 // Next directory
191 KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => {
192 app.conn.conn.switch(app.queue_list.index as u32)?;
193 app.conn.update_status();
194 }
195
196 // Delete highlighted song from the queue
197 KeyCode::Char('d') => {
198 if app.queue_list.index >= app.queue_list.list.len()
199 && app.queue_list.index != 0
200 {
201 app.queue_list.index -= 1;
202 }
203
204 app.conn.conn.delete(app.queue_list.index as u32)?;
205
206 if app.queue_list.index >= app.queue_list.list.len().saturating_sub(1)
207 && app.queue_list.index != 0
208 {
209 app.queue_list.index -= 1;
210 }
211
212 app.conn.update_status();
213 app.update_queue();
214 }
215
216 // Swap highlighted song with next one
217 KeyCode::Char('J') => {
218 let current: u32 = app.queue_list.index as u32;
219 let next: u32 = if (current + 1) as usize == app.queue_list.list.len() {
220 app.queue_list.index as u32
221 } else {
222 app.queue_list.index += 1;
223 current + 1
224 };
225 app.conn.conn.swap(current, next)?;
226 app.update_queue();
227 app.conn.update_status();
228 }
229
230 // Swap highlighted song with previous one
231 KeyCode::Char('K') => {
232 let current: u32 = app.queue_list.index as u32;
233 let prev: u32 = if current == 0 {
234 app.queue_list.index as u32
235 } else {
236 app.queue_list.index -= 1;
237 current - 1
238 };
239 app.conn.conn.swap(current, prev)?;
240 app.update_queue();
241 app.conn.update_status();
242 }
243
244 // go to top of list
245 KeyCode::Char('g') => app.queue_list.index = 0,
246
247 // go to bottom of list
248 KeyCode::Char('G') => app.queue_list.index = app.queue_list.list.len() - 1,
249
250 _ => {}
251 }
252 }
253
254 SelectedTab::DirectoryBrowser => {
255 match key_event.code {
256 // Go Up
257 KeyCode::Char('j') | KeyCode::Down => app.browser.next(),
258
259 // Go down
260 KeyCode::Char('k') | KeyCode::Up => app.browser.prev(),
261
262 // Next directory
263 KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => {
264 // app.update_queue();
265 app.handle_enter()?;
266 app.conn.update_status();
267 }
268
269 // head back to previous directory
270 KeyCode::Char('h') | KeyCode::Left => {
271 app.browser.handle_go_back(&mut app.conn)?
272 }
273
274 // go to top of list
275 KeyCode::Char('g') => app.browser.selected = 0,
276
277 // go to bottom of list
278 KeyCode::Char('G') => app.browser.selected = app.browser.filetree.len() - 1,
279
280 _ => {}
281 }
282 }
283
284 SelectedTab::Playlists => {
285 match key_event.code {
286 // Go Up
287 KeyCode::Char('j') | KeyCode::Down => app.pl_list.next(),
288
289 // Go down
290 KeyCode::Char('k') | KeyCode::Up => app.pl_list.prev(),
291
292 // go to top of list
293 KeyCode::Char('g') => app.pl_list.index = 0,
294
295 // go to bottom of list
296 KeyCode::Char('G') => app.pl_list.index = app.pl_list.list.len() - 1,
297
298 // Change playlist name
299 KeyCode::Char('e') => app.change_playlist_name()?,
300
301 // add to current playlist
302 KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right | KeyCode::Char(' ') => {
303 // app.update_queue();
304 if !app.pl_list.list.is_empty() {
305 app.conn
306 .load_playlist(app.pl_list.list.get(app.pl_list.index).unwrap())?;
307 app.conn.update_status();
308 }
309 }
310 _ => {}
311 }
312 }
313 }
314 }
315 Ok(())
316}
317
318pub fn handle_mouse_events(mouse_event: MouseEvent, app: &mut App) -> AppResult<()> {
319 match mouse_event.kind {
320 MouseEventKind::ScrollUp => app.handle_scroll_up(),
321 MouseEventKind::ScrollDown => app.handle_scroll_down(),
322 MouseEventKind::Down(button) => {
323 let (x, y) = (mouse_event.column, mouse_event.row);
324 match button {
325 crossterm::event::MouseButton::Left => app.handle_mouse_left_click(x, y)?,
326 _ => {}
327 }
328 }
329 _ => {}
330 }
331 Ok(())
332}