diff --git a/src/app/handle.rs b/src/app/handle.rs index ca232aa..b7d1911 100644 --- a/src/app/handle.rs +++ b/src/app/handle.rs @@ -1,4 +1,4 @@ -use crossterm::event::{KeyCode, KeyEvent}; +use crossterm::event::{Event, KeyCode, KeyEvent}; use jocalsend::ReceiveDialog; use log::{debug, error, warn}; use tui_input::backend::crossterm::EventHandler; @@ -12,14 +12,12 @@ impl App { event: crossterm::event::Event, ) { let code = key_event.code; - let mode = self.screen.last_mut().unwrap(); + let mode = self.screen(); match mode { CurrentScreen::Main | CurrentScreen::Help | CurrentScreen::Logging - | CurrentScreen::Receiving - | CurrentScreen::Sending(SendingScreen::Files(FileMode::Picking)) - | CurrentScreen::Sending(SendingScreen::Peers) => match code { + | CurrentScreen::Receiving => match code { KeyCode::Char('q') => self.exit().await, KeyCode::Char('s') => self.send(), KeyCode::Char('r') => self.recv(), @@ -42,89 +40,98 @@ impl App { KeyCode::Char('d') => self.deny(), _ => {} }, - CurrentScreen::Sending(sending_screen) => match sending_screen { - // we can only be in picking mode - SendingScreen::Files(fmode) => match code { - KeyCode::Char('t') => *sending_screen = SendingScreen::Text, - KeyCode::Tab => *sending_screen = SendingScreen::Peers, - KeyCode::Enter => self.chdir_or_send_file().await, - KeyCode::Char('/') => { - *fmode = FileMode::Fuzzy; - } - _ => self.file_finder.handle(&event).unwrap_or_default(), - }, - SendingScreen::Peers => match code { - KeyCode::Tab => { - *sending_screen = SendingScreen::Files(FileMode::Picking) - } - KeyCode::Char('t') => *sending_screen = SendingScreen::Text, - KeyCode::Enter => self.send_content().await, - KeyCode::Up => self.peer_state.select_previous(), - KeyCode::Down => self.peer_state.select_next(), - _ => {} - }, - SendingScreen::Text => unreachable!(), - }, - CurrentScreen::Stopping => unreachable!(), + CurrentScreen::Stopping | CurrentScreen::Sending(_) => unreachable!(), }, }, - // we only need to deal with sending text now or doing fuzzy matching - CurrentScreen::Sending(sending_screen) => match sending_screen { - SendingScreen::Text => match code { - KeyCode::Tab => *sending_screen = SendingScreen::Peers, - KeyCode::Enter => self.send_text().await, - KeyCode::Esc => { - self.text = None; - self.input.reset(); - *sending_screen = SendingScreen::Files(FileMode::Picking); + CurrentScreen::Sending(_) => self.sending_screen(key_event, event).await, + CurrentScreen::Stopping => {} + } + } + + async fn sending_screen(&mut self, key_event: KeyEvent, event: Event) { + let mode = self.screen(); + let CurrentScreen::Sending(mode) = mode else { + return; + }; + let code = key_event.code; + match mode { + SendingScreen::Peers => match code { + KeyCode::Char('q') => self.exit().await, + KeyCode::Char('s') => self.send(), + KeyCode::Char('r') => self.recv(), + KeyCode::Char('l') => self.logs(), + KeyCode::Char('m') => self.main(), + KeyCode::Char('h') | KeyCode::Char('?') => self.help(), + KeyCode::Char('c') => self.service.clear_peers().await, + KeyCode::Char('t') => self.sending_text(), + KeyCode::Tab => self.sending_files(), + KeyCode::Enter => self.send_content().await, + KeyCode::Esc => self.pop(), + _ => {} + }, + SendingScreen::Files(FileMode::Picking) => match code { + KeyCode::Char('q') => self.exit().await, + KeyCode::Char('s') => self.send(), + KeyCode::Char('r') => self.recv(), + KeyCode::Char('l') => self.logs(), + KeyCode::Char('m') => self.main(), + KeyCode::Char('h') | KeyCode::Char('?') => self.help(), + KeyCode::Char('c') => self.service.clear_peers().await, + KeyCode::Char('t') => self.sending_text(), + KeyCode::Tab => self.sending_peers(), + KeyCode::Enter => self.chdir_or_send_file().await, + KeyCode::Esc => self.pop(), + KeyCode::Char('/') => self.sending_fuzzy(), + _ => self.file_finder.handle(&event).unwrap_or_default(), + }, + SendingScreen::Files(FileMode::Fuzzy) => match code { + KeyCode::Tab => self.sending_peers(), + KeyCode::Enter => self.chdir_or_send_file().await, + KeyCode::Esc => { + self.file_finder.reset_fuzzy(); + self.sending_files(); + } + KeyCode::Up | KeyCode::Down => { + if let Err(e) = self.file_finder.handle(&event) { + log::error!("error selecting file: {e:?}"); } - _ => { - if let Some(changed) = self.input.handle_event(&event) - && changed.value - { - if self.input.value().is_empty() { - self.text = None; - } else { - self.text = Some(self.input.to_string()); - } - } + } + _ => { + self.file_finder.index(); + if let Some(changed) = self.file_finder.input.handle_event(&event) + && changed.value + { + let id = self + .file_finder + .fuzzy + .search(self.file_finder.input.value()) + .first() + .copied() + .unwrap_or(0); + self.file_finder.explorer.set_selected_idx(id); } - }, - SendingScreen::Files(fmode) => { - if *fmode == FileMode::Fuzzy { - match code { - KeyCode::Tab => *sending_screen = SendingScreen::Peers, - KeyCode::Enter => self.chdir_or_send_file().await, - KeyCode::Esc => { - self.file_finder.reset_fuzzy(); - *fmode = FileMode::Picking; - } - KeyCode::Up | KeyCode::Down => { - if let Err(e) = self.file_finder.handle(&event) { - log::error!("error selecting file: {e:?}"); - } - } - _ => { - self.file_finder.index(); - if let Some(changed) = self.file_finder.input.handle_event(&event) - && changed.value - { - let id = self - .file_finder - .fuzzy - .search(self.file_finder.input.value()) - .first() - .copied() - .unwrap_or(0); - self.file_finder.explorer.set_selected_idx(id); - } - } + } + }, + SendingScreen::Text => match code { + KeyCode::Tab => self.sending_peers(), + KeyCode::Enter => self.send_text().await, + KeyCode::Esc => { + self.text = None; + self.input.reset(); + self.sending_files(); + } + _ => { + if let Some(changed) = self.input.handle_event(&event) + && changed.value + { + if self.input.value().is_empty() { + self.text = None; + } else { + self.text = Some(self.input.to_string()); } } } - SendingScreen::Peers => unreachable!(), }, - CurrentScreen::Stopping => {} } } @@ -184,6 +191,41 @@ impl App { } } + fn sending_peers(&mut self) { + if let CurrentScreen::Sending(mode) = self.screen_mut() { + *mode = SendingScreen::Peers; + } + } + + fn sending_text(&mut self) { + if let CurrentScreen::Sending(mode) = self.screen_mut() { + *mode = SendingScreen::Text; + } + } + + fn sending_fuzzy(&mut self) { + if let CurrentScreen::Sending(mode) = self.screen_mut() { + *mode = SendingScreen::Files(FileMode::Fuzzy); + } + } + + fn sending_files(&mut self) { + let doing_files = self.text.is_none(); + let doing_picking = self.file_finder.input.value().is_empty(); + let screen = self.screen_mut(); + if let CurrentScreen::Sending(mode) = screen { + if doing_files { + if doing_picking { + *mode = SendingScreen::Files(FileMode::Picking); + } else { + *mode = SendingScreen::Files(FileMode::Fuzzy); + } + } else { + *mode = SendingScreen::Text; + } + } + } + // accept a content receive request fn accept(&mut self) { let Some(idx) = self.receiving_state.selected() else { @@ -231,6 +273,7 @@ impl App { error!("could not list directory {file:?}: {e}"); return; } else if file.is_dir() { + self.file_finder.input.reset(); return; } diff --git a/src/app/widgets.rs b/src/app/widgets.rs index cb2564b..a411b95 100644 --- a/src/app/widgets.rs +++ b/src/app/widgets.rs @@ -128,6 +128,9 @@ impl Widget for &mut App { let [header_left, header_right] = header_layout.areas(top); let header_margin = Margin::new(1, 2); + let top_heavy = Layout::vertical([Constraint::Percentage(66), Constraint::Percentage(34)]); + let [heavy_top, _skinny_bottom] = top_heavy.areas(area); + let subscreen_margin = Margin::new(1, 2); // it's safe to call `unwrap()` here because we ensure there's always at least @@ -190,7 +193,9 @@ impl Widget for &mut App { let file_area = header_left.inner(header_margin); match sending_screen { - SendingScreen::Files(FileMode::Picking) => { + SendingScreen::Files(FileMode::Picking) + | SendingScreen::Peers + | SendingScreen::Text => { self.file_finder.widget().render(file_area, buf); } SendingScreen::Files(FileMode::Fuzzy) => { @@ -199,7 +204,6 @@ impl Widget for &mut App { text_popup(self.file_finder.input.value(), "fuzzy search", input, buf); self.file_finder.widget().render(files, buf); } - _ => {} } logger(header_right.inner(header_margin), buf); @@ -212,7 +216,8 @@ impl Widget for &mut App { ); if sending_screen == SendingScreen::Text { - let rect = centered_rect(area, Constraint::Percentage(80), Constraint::Max(10)); + let rect = + centered_rect(heavy_top, Constraint::Percentage(80), Constraint::Max(6)); let text = if let Some(text) = self.text.as_ref() { text } else {