From 9e1e08851e5ddc6f4e428d4673ab4804f2b11ead Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Tue, 8 Jul 2025 15:46:31 -0700 Subject: [PATCH] add informative footers --- src/discovery.rs | 2 -- src/http_server.rs | 3 +- src/main.rs | 11 ++++---- src/ui.rs | 69 ++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/src/discovery.rs b/src/discovery.rs index 62509a3..2d975b9 100644 --- a/src/discovery.rs +++ b/src/discovery.rs @@ -25,8 +25,6 @@ impl JoecalState { pub async fn listen_multicast(&self, config: &Config) -> crate::error::Result<()> { let mut buf = [0; 65536]; - println!("Socket local addr: {:?}", self.socket.local_addr()?); - println!("Listening on multicast addr: {}", config.multicast_addr); let mut timeout = tokio::time::interval(Duration::from_secs(5)); diff --git a/src/http_server.rs b/src/http_server.rs index 591a29b..e1182f6 100644 --- a/src/http_server.rs +++ b/src/http_server.rs @@ -21,10 +21,9 @@ impl JoecalState { config: &Config, ) -> crate::error::Result<()> { let app = self.create_router(config); + // TODO: make addr config let addr = SocketAddr::from(([0, 0, 0, 0], config.port)); - let listener = TcpListener::bind(&addr).await?; - println!("HTTP server listening on {addr}"); axum::serve( listener, diff --git a/src/main.rs b/src/main.rs index 0e628f3..cb26de2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![feature(slice_as_array)] use std::{collections::BTreeMap, io, net::SocketAddr}; use joecalsend::{Config, JoecalState, RunningState, error, models::Device}; @@ -57,11 +58,13 @@ async fn main() -> error::Result<()> { Ok(result?) } +pub type Peers = BTreeMap; + pub struct App { state: JoecalState, screen: CurrentScreen, // addr -> (alias, fingerprint) - peers: BTreeMap, + peers: Peers, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -89,7 +92,9 @@ impl App { if self.screen == CurrentScreen::Stopping { break; } + let peers = self.state.peers.lock().await; + self.peers.clear(); peers.iter().for_each(|(k, v)| { // k is fingerprint, v is addr, device let addr = v.0; @@ -101,10 +106,6 @@ impl App { Ok(()) } - fn draw(&self, frame: &mut Frame) { - frame.render_widget(self, frame.area()); - } - async fn handle_events(&mut self) -> io::Result<()> { match event::read()? { // it's important to check that the event is a key press event as diff --git a/src/ui.rs b/src/ui.rs index 5bb3995..ec60346 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -5,7 +5,7 @@ use ratatui::{ layout::{Constraint, Direction, Layout, Rect}, style::Stylize, text::{Line, Span}, - widgets::{List, ListItem}, + widgets::{Block, Borders, List, ListItem}, }; use crate::App; @@ -35,16 +35,63 @@ fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect { } impl App { - pub fn peers(&self, frame: &mut Frame) { - let mut items = Vec::with_capacity(self.peers.len()); - for (k, v) in self.peers.iter() { - let item = format!("{:?}: {}({})", k, v.0, v.1); - let s = Line::from(item.yellow()); + pub fn draw(&self, frame: &mut Frame) { + let [top, middle, bottom] = Layout::default() + .direction(Direction::Vertical) + .constraints([Constraint::Min(3), Constraint::Min(3), Constraint::Min(3)]) + .split(frame.area()) + .as_array() + .cloned() + .unwrap(); - let item = ListItem::new(s); - items.push(item); - } - let list = List::new(items); - frame.render_widget(list, frame.area()); + let [footer_left, footer_right] = Layout::default() + .direction(Direction::Horizontal) + .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) + .split(bottom) + .as_array() + .cloned() + .unwrap(); + + frame.render_widget(self, frame.area()); + network_info(frame, footer_left); + peers(&self.peers, frame, footer_right); } } + +fn peers(peers: &crate::Peers, frame: &mut Frame, area: Rect) { + let mut items = Vec::with_capacity(peers.len()); + for (k, v) in peers.iter() { + let item = format!("{:?}: {} ({})", k, v.0, v.1); + let s = Line::from(item.yellow()); + + let item = ListItem::new(s); + items.push(item); + } + let block = Block::default().title("Peers").borders(Borders::all()); + let list = List::new(items).block(block); + frame.render_widget(list, area); +} + +fn network_info(frame: &mut Frame, area: Rect) { + let udp: Line = format!("UDP socket: {:?}", joecalsend::LISTENING_SOCKET_ADDR) + .yellow() + .into(); + let multicast: Line = format!( + "Multicast address: {:?}:{}", + joecalsend::MULTICAST_IP, + joecalsend::DEFAULT_PORT + ) + .yellow() + .into(); + let http: Line = format!("HTTP address: {:?}", joecalsend::LISTENING_SOCKET_ADDR) + .yellow() + .into(); + let items = [ + ListItem::new(udp), + ListItem::new(multicast), + ListItem::new(http), + ]; + let block = Block::default().title("Listeners").borders(Borders::all()); + let list = List::new(items).block(block); + frame.render_widget(list, area); +}