From 9b2172aa3a645d718db3f46fbc42f9cc2cbc00a1 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Tue, 29 Jul 2025 16:27:49 -0700 Subject: [PATCH] add logging screen, clean up widget rendering --- src/discovery.rs | 5 +- src/frontend/mod.rs | 143 +++++++++++++++++++++++++------------------- 2 files changed, 84 insertions(+), 64 deletions(-) diff --git a/src/discovery.rs b/src/discovery.rs index 067c7ea..cde4d42 100644 --- a/src/discovery.rs +++ b/src/discovery.rs @@ -8,7 +8,7 @@ use axum::{ Json, extract::{ConnectInfo, State}, }; -use log::{error, warn}; +use log::{debug, error, warn}; use tokio::net::UdpSocket; use crate::{Config, JoecalState, RunningState, models::Device}; @@ -19,6 +19,7 @@ impl JoecalState { socket: Option, config: &Config, ) -> crate::error::Result<()> { + debug!("announcing"); announce_http(&self.device, socket, self.client.clone()).await?; announce_multicast(&self.device, config.multicast_addr, self.socket.clone()).await?; Ok(()) @@ -38,10 +39,12 @@ impl JoecalState { }; if rstate == RunningState::Stopping { + debug!("stopping multicast listen"); break; } }, r = self.socket.recv_from(&mut buf) => { + debug!("received multicast datagram"); match r { Ok((size, src)) => { let received_msg = String::from_utf8_lossy(&buf[..size]); diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 7ad3a1b..62f822b 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -46,6 +46,7 @@ pub enum CurrentScreen { Sending, Receiving, Stopping, + Logging, } impl Default for App { @@ -165,6 +166,7 @@ impl App { KeyCode::Char('q') => self.exit(), KeyCode::Char('s') => self.send(), KeyCode::Char('r') => self.recv(), + KeyCode::Char('l') => self.logs(), KeyCode::Esc => self.pop(), _ => {} } @@ -194,6 +196,14 @@ impl App { } } + fn logs(&mut self) { + let last = self.screen.last(); + match last { + Some(CurrentScreen::Logging) => {} + _ => self.screen.push(CurrentScreen::Logging), + } + } + fn pop(&mut self) { self.screen.pop(); if self.screen.last().is_none() { @@ -204,83 +214,90 @@ impl App { impl Widget for &App { fn render(self, area: Rect, buf: &mut Buffer) { - let [top, middle, bottom] = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Min(10), Constraint::Min(10), Constraint::Min(3)]) - .split(area) - .as_array() - .cloned() - .unwrap(); + let [top, middle, bottom] = + Layout::vertical([Constraint::Min(5), Constraint::Min(10), Constraint::Min(3)]) + .split(area) + .as_array() + .cloned() + .unwrap(); - let [footer_left, footer_right] = Layout::default() - .direction(Direction::Horizontal) - .constraints([Constraint::Percentage(30), Constraint::Percentage(70)]) - .split(bottom) - .as_array() - .cloned() - .unwrap(); + let [footer_left, footer_right] = + Layout::horizontal([Constraint::Percentage(30), Constraint::Percentage(70)]) + .split(bottom) + .as_array() + .cloned() + .unwrap(); - let [header_left, header_right] = Layout::default() - .direction(Direction::Horizontal) - .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) - .split(top) - .as_array() - .cloned() - .unwrap(); + let [header_left, header_right] = + Layout::horizontal([Constraint::Percentage(50), Constraint::Percentage(50)]) + .split(top) + .as_array() + .cloned() + .unwrap(); - let logger = TuiLoggerWidget::default() - .output_separator('|') - .output_timestamp(Some("%F %H:%M:%S%.3f".to_string())) - .output_level(Some(TuiLoggerLevelOutput::Abbreviated)) - .output_target(false) - .output_file(false) - .output_line(false) - .block(Block::bordered().border_set(border::THICK)) - .style(Style::default()) - .state(&TuiWidgetState::new().set_default_display_level(LevelFilter::Debug)); - - { - let title = Line::from(" Joecalsend ".bold()); - let instructions = Line::from(vec![ - " Send ".into(), - "".blue().bold(), - " Receive ".into(), - "".blue().bold(), - " Discover ".into(), - "".blue().bold(), - " Quit ".into(), - " ".blue().bold(), - ]); - let block = Block::bordered() - .title(title.centered()) - .title_bottom(instructions.centered()) - .border_set(border::THICK); - - let current_screen = format!( - "{:?}", - self.screen.last().copied().unwrap_or(CurrentScreen::Main) - ); - let text = Text::from(Line::from(current_screen.yellow())); - - Paragraph::new(text) - .centered() - .block(block) - .render(area, buf); - } let mode = self.screen.last().unwrap(); match mode { CurrentScreen::Main => { + main_page(*mode, area, buf); + logger(header_right.inner(Margin::new(1, 2)), buf); let peers = PeersWidget { peers: &self.peers }; peers.render(footer_right.inner(Margin::new(1, 1)), buf); NetworkInfoWidget.render(footer_left.inner(Margin::new(1, 1)), buf); - logger.render(header_right.inner(Margin::new(1, 2)), buf); } - CurrentScreen::Receiving => {} - _ => {} + CurrentScreen::Receiving => { + main_page(*mode, area, buf); + } + CurrentScreen::Logging => { + main_page(*mode, area, buf); + logger(area.inner(Margin::new(2, 4)), buf); + } + _ => { + main_page(*mode, area, buf); + } } } } +fn logger(area: Rect, buf: &mut Buffer) { + let logger = TuiLoggerWidget::default() + .output_separator('|') + .output_timestamp(Some("%H:%M:%S%.3f".to_string())) + .output_level(Some(TuiLoggerLevelOutput::Abbreviated)) + .output_target(true) + .output_file(false) + .output_line(false) + .block(Block::bordered().border_set(border::THICK)) + .style(Style::default()) + .state(&TuiWidgetState::new().set_default_display_level(LevelFilter::Debug)); + logger.render(area, buf); +} + +fn main_page(screen: CurrentScreen, area: Rect, buf: &mut Buffer) { + let title = Line::from(" Joecalsend ".bold()); + let instructions = Line::from(vec![ + " Send ".into(), + "".blue().bold(), + " Receive ".into(), + "".blue().bold(), + " Logs ".into(), + "".blue().bold(), + " Quit ".into(), + " ".blue().bold(), + ]); + let block = Block::bordered() + .title(title.centered()) + .title_bottom(instructions.centered()) + .border_set(border::THICK); + + let current_screen = format!("{screen:?}",); + let text = Text::from(Line::from(current_screen.yellow())); + + Paragraph::new(text) + .centered() + .block(block) + .render(area, buf); +} + async fn shutdown(handles: &mut JoinSet) { let mut alarm = tokio::time::interval(tokio::time::Duration::from_secs(5)); alarm.tick().await;