diff --git a/src/app/mod.rs b/src/app/mod.rs index 2f33a80..4310fad 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -125,7 +125,7 @@ impl App { KeyCode::Esc => self.pop(), KeyCode::Char('q') => self.exit(), KeyCode::Tab => *s = SendingScreen::Peers, - KeyCode::Enter => self.send_content().await, + KeyCode::Enter => self.chdir_or_send_file().await, _ => self.file_picker.handle(&event).unwrap_or_default(), }, SendingScreen::Peers => match key_event.code { @@ -137,7 +137,15 @@ impl App { KeyCode::Down => self.peer_state.select_next(), _ => {} }, - SendingScreen::Text => {} + SendingScreen::Text => match key_event.code { + KeyCode::Esc => { + self.text = None; + *s = SendingScreen::Files; + } + KeyCode::Tab => *s = SendingScreen::Peers, + KeyCode::Enter => self.send_text().await, + _ => {} + }, }, _ => match key_event.code { KeyCode::Char('q') => self.exit(), @@ -230,9 +238,14 @@ impl App { self.receive_requests.remove(key); } - // send content to selected peer, or change directories in the file explorer - async fn send_content(&mut self) { - debug!("sending content"); + async fn chdir_or_send_file(&mut self) { + let file = self.file_picker.current().path().clone(); + if file.is_dir() + && let Err(e) = self.file_picker.set_cwd(&file) + { + error!("could not list directory {file:?}: {e}"); + return; + } let Some(peer_idx) = self.peer_state.selected() else { warn!("no peer selected to send to"); @@ -243,29 +256,42 @@ impl App { return; }; - if let Some(ref text) = self.text { - if let Err(e) = self.service.send_text(&peer.fingerprint, text).await { - error!("got error sending \"{text}\" to {}: {e:?}", peer.alias); - } - } else { - let file = self.file_picker.current().path().clone(); - if file.is_dir() - && let Err(e) = self.file_picker.set_cwd(&file) - { - error!("could not list directory {file:?}: {e}"); - return; + if file.is_file() { + debug!("sending {file:?}"); + if let Err(e) = self.service.send_file(&peer.fingerprint, file).await { + error!("got error sending content: {e:?}"); } + } + } - if file.is_file() { - debug!("sending {file:?}"); - if let Err(e) = self - .service - .send_file(&peer.fingerprint, file.clone()) - .await - { - error!("got error sending content: {e:?}"); - } - } + // send content to selected peer, or change directories in the file explorer + async fn send_text(&mut self) { + debug!("sending text"); + + let Some(peer_idx) = self.peer_state.selected() else { + debug!("no peer selected to send to"); + return; + }; + let Some(peer) = self.peers.get(peer_idx) else { + warn!("invalid peer index {peer_idx}"); + return; + }; + + let Some(text) = &self.text else { + debug!("no text to send"); + return; + }; + + if let Err(e) = self.service.send_text(&peer.fingerprint, text).await { + error!("got error sending \"{text}\" to {}: {e:?}", peer.alias); + } + } + + async fn send_content(&mut self) { + if self.text.is_some() { + self.send_text().await; + } else { + self.chdir_or_send_file().await; } } } diff --git a/src/app/widgets.rs b/src/app/widgets.rs index ba758bf..f14692c 100644 --- a/src/app/widgets.rs +++ b/src/app/widgets.rs @@ -128,12 +128,11 @@ impl Widget for &mut App { let rx_reqs: Vec<_> = self.receive_requests.values().collect(); outer_frame(*current_screen, &MAIN_MENU, area, buf); logger(header_right.inner(header_margin), buf); - let peers = PeersWidget { peers: &self.peers }; - ratatui::widgets::StatefulWidget::render( - peers, + peers( + &self.peers, + &mut self.peer_state, footer_right.inner(footer_margin), buf, - &mut self.peer_state, ); NetworkInfoWidget.render(footer_left.inner(footer_margin), buf); receive_requests( @@ -169,18 +168,16 @@ impl Widget for &mut App { SendingScreen::Text => {} } - let peers = PeersWidget { peers: &self.peers }; - self.file_picker .widget() .render(header_left.inner(header_margin), buf); logger(header_right.inner(header_margin), buf); - ratatui::widgets::StatefulWidget::render( - peers, + peers( + &self.peers, + &mut self.peer_state, bottom.inner(subscreen_margin), buf, - &mut self.peer_state, ); } _ => { @@ -272,47 +269,35 @@ fn receive_requests( ratatui::widgets::StatefulWidget::render(table, area, buf, state); } -#[derive(Debug, Clone)] -pub struct PeersWidget<'p> { - pub peers: &'p [Peer], -} - -impl<'p> ratatui::widgets::StatefulWidget for PeersWidget<'p> { - type State = ListState; - - fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) - where - Self: Sized, - { - if self.peers.is_empty() { - state.select(None); - } - if state.selected().is_none() { - state.select(Some(0)); - } - - let mut items = Vec::with_capacity(self.peers.len()); - for Peer { - addr, - alias, - fingerprint, - } in self.peers.iter() - { - let item = format!("{:?}: {} ({})", addr, alias, fingerprint); - let s = Line::from(item.yellow()); - let item = ListItem::new(s); - items.push(item); - } - let title = Line::from(" Peers ".bold()).centered(); - let block = Block::default() - .title(title) - .borders(Borders::all()) - .padding(Padding::uniform(1)); - let list = List::new(items) - .block(block) - .highlight_style(Style::new().bg(Color::Rgb(99, 99, 99))); - ratatui::widgets::StatefulWidget::render(list, area, buf, state); +fn peers(peers: &[Peer], state: &mut ListState, area: Rect, buf: &mut Buffer) { + if peers.is_empty() { + state.select(None); } + if state.selected().is_none() { + state.select(Some(0)); + } + + let mut items = Vec::with_capacity(peers.len()); + for Peer { + addr, + alias, + fingerprint, + } in peers + { + let item = format!("{:?}: {} ({})", addr, alias, fingerprint); + let s = Line::from(item.yellow()); + let item = ListItem::new(s); + items.push(item); + } + let title = Line::from(" Peers ".bold()).centered(); + let block = Block::default() + .title(title) + .borders(Borders::all()) + .padding(Padding::uniform(1)); + let list = List::new(items) + .block(block) + .highlight_style(Style::new().bg(Color::Rgb(99, 99, 99))); + ratatui::widgets::StatefulWidget::render(list, area, buf, state); } #[derive(Debug, Clone)] @@ -364,7 +349,7 @@ impl Widget for NetworkInfoWidget { } // helpers -fn centered_rect(area: Rect, width_pct: u16, height_pct: u16) -> Rect { +fn _centered_rect(area: Rect, width_pct: u16, height_pct: u16) -> Rect { let horizontal = Layout::horizontal([Constraint::Percentage(width_pct)]).flex(Flex::Center); let vertical = Layout::vertical([Constraint::Percentage(height_pct)]).flex(Flex::Center); let [area] = vertical.areas(area);