better network info

This commit is contained in:
Joe Ardent 2025-08-07 12:27:20 -07:00
parent c829a4b188
commit 514dee438f
3 changed files with 51 additions and 52 deletions

View file

@ -1,4 +1,4 @@
use std::sync::LazyLock; use std::{net::Ipv4Addr, sync::LazyLock};
use jocalsend::ReceiveRequest; use jocalsend::ReceiveRequest;
use log::LevelFilter; use log::LevelFilter;
@ -146,7 +146,11 @@ impl Widget for &mut App {
footer_right.inner(footer_margin), footer_right.inner(footer_margin),
buf, buf,
); );
NetworkInfoWidget.render(footer_left.inner(footer_margin), buf); network_info(
&self.service.config.local_ip_addr,
footer_left.inner(footer_margin),
buf,
);
receive_requests( receive_requests(
&rx_reqs, &rx_reqs,
&mut self.receiving_state, &mut self.receiving_state,
@ -354,52 +358,41 @@ fn peers(peers: &[Peer], state: &mut ListState, area: Rect, buf: &mut Buffer) {
ratatui::widgets::StatefulWidget::render(list, area, buf, state); ratatui::widgets::StatefulWidget::render(list, area, buf, state);
} }
#[derive(Debug, Clone)] fn network_info(local_ip_addr: &Ipv4Addr, area: Rect, buf: &mut Buffer) {
pub struct NetworkInfoWidget; let local_addr = format!("{local_ip_addr:?}:{}", jocalsend::DEFAULT_PORT);
let local_addr = local_addr.to_line().right_aligned();
impl Widget for NetworkInfoWidget { let http = "HTTP address";
fn render(self, area: Rect, buf: &mut Buffer) let http = Row::new(vec![http.to_line().left_aligned(), local_addr.clone()]).yellow();
where
Self: Sized,
{
let udp = "UDP socket";
let udp = udp.to_line().left_aligned();
let uaddr = format!("{:?}", jocalsend::LISTENING_SOCKET_ADDR);
let udp = Row::new(vec![udp, uaddr.to_line().right_aligned()]).yellow();
let mip = format!( let udp = "UDP socket";
"{:?}:{:?}", let udp = udp.to_line().left_aligned();
jocalsend::MULTICAST_IP, let udp = Row::new(vec![udp, local_addr]).yellow();
jocalsend::DEFAULT_PORT
);
let multicast = "Multicast address";
let multicast = Row::new(vec![
multicast.to_line().left_aligned(),
mip.to_line().right_aligned(),
])
.yellow();
let haddr = format!("{:?}", jocalsend::LISTENING_SOCKET_ADDR); let mip = format!(
let http = "HTTP address"; "{:?}:{:?}",
let http = Row::new(vec![ jocalsend::MULTICAST_IP,
http.to_line().left_aligned(), jocalsend::DEFAULT_PORT
haddr.to_line().right_aligned(), );
]) let multicast = "Multicast address";
.yellow(); let multicast = Row::new(vec![
multicast.to_line().left_aligned(),
mip.to_line().right_aligned(),
])
.yellow();
let rows = vec![udp, multicast, http]; let rows = vec![http, udp, multicast];
let widths = vec![Constraint::Percentage(50), Constraint::Percentage(50)]; let widths = vec![Constraint::Percentage(50), Constraint::Percentage(50)];
let title = Line::from(" Listeners ".bold()).centered(); let title = Line::from(" Listeners ".bold()).centered();
let block = Block::default() let block = Block::default()
.title(title) .title(title)
.borders(Borders::all()) .borders(Borders::all())
.padding(Padding::uniform(1)); .padding(Padding::uniform(1));
let table = Table::new(rows, widths).block(block); let table = Table::new(rows, widths).block(block);
table.render(area, buf); table.render(area, buf);
}
} }
// helpers // helpers

View file

@ -7,11 +7,13 @@ pub mod transfer;
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
fmt::Debug, fmt::Debug,
net::{Ipv4Addr, SocketAddr, SocketAddrV4}, net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
sync::{Arc, OnceLock}, sync::{Arc, OnceLock},
}; };
use error::LocalSendError;
use julid::Julid; use julid::Julid;
use local_ip_address::local_ip;
use log::error; use log::error;
use models::{Device, FileMetadata}; use models::{Device, FileMetadata};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -195,18 +197,22 @@ pub struct Config {
pub multicast_addr: SocketAddrV4, pub multicast_addr: SocketAddrV4,
pub port: u16, pub port: u16,
pub download_dir: String, pub download_dir: String,
pub local_ip_addr: SocketAddr, pub local_ip_addr: Ipv4Addr,
} }
impl Default for Config { impl Config {
fn default() -> Self { pub fn new() -> error::Result<Self> {
let home = std::env::home_dir().unwrap_or("/tmp".into()); let home = std::env::home_dir().unwrap_or("/tmp".into());
let dd = home.join("jocalsend-downloads"); let dd = home.join("jocalsend-downloads");
Self { let IpAddr::V4(local_ip_addr) = local_ip()? else {
return Err(LocalSendError::IPv6Unsupported);
};
Ok(Self {
multicast_addr: SocketAddrV4::new(MULTICAST_IP, DEFAULT_PORT), multicast_addr: SocketAddrV4::new(MULTICAST_IP, DEFAULT_PORT),
port: DEFAULT_PORT, port: DEFAULT_PORT,
download_dir: dd.to_string_lossy().into(), download_dir: dd.to_string_lossy().into(),
local_ip_addr: ([0u8; 4], DEFAULT_PORT).into(), local_ip_addr,
} })
} }
} }

View file

@ -1,4 +1,4 @@
use jocalsend::{Config, JocalService, Listeners, error, models::Device}; use jocalsend::{Config, JocalService, Listeners, error::Result, models::Device};
use log::{error, info}; use log::{error, info};
use ratatui::DefaultTerminal; use ratatui::DefaultTerminal;
use tokio::{sync::mpsc::unbounded_channel, task::JoinSet}; use tokio::{sync::mpsc::unbounded_channel, task::JoinSet};
@ -7,7 +7,7 @@ use tui_logger::{LevelFilter, init_logger, set_env_filter_from_env};
mod app; mod app;
use app::{App, CurrentScreen, Peer}; use app::{App, CurrentScreen, Peer};
fn main() -> error::Result<()> { fn main() -> Result<()> {
let device = Device::default(); let device = Device::default();
if std::env::var("RUST_LOG").is_err() { if std::env::var("RUST_LOG").is_err() {
@ -18,7 +18,7 @@ fn main() -> error::Result<()> {
init_logger(LevelFilter::Info).map_err(|e| std::io::Error::other(format!("{e}")))?; init_logger(LevelFilter::Info).map_err(|e| std::io::Error::other(format!("{e}")))?;
set_env_filter_from_env(None); set_env_filter_from_env(None);
let config = Config::default(); let config = Config::new()?;
let mut terminal = ratatui::init(); let mut terminal = ratatui::init();
let result = start_and_run(&mut terminal, config, device); let result = start_and_run(&mut terminal, config, device);
@ -32,7 +32,7 @@ async fn start_and_run(
terminal: &mut DefaultTerminal, terminal: &mut DefaultTerminal,
config: Config, config: Config,
device: Device, device: Device,
) -> error::Result<()> { ) -> Result<()> {
let (event_tx, event_listener) = unbounded_channel(); let (event_tx, event_listener) = unbounded_channel();
let service = JocalService::new(device, config.clone(), event_tx) let service = JocalService::new(device, config.clone(), event_tx)