make widgets for status panes

This commit is contained in:
Joe Ardent 2025-07-28 15:51:00 -07:00
parent 9fff83a721
commit a9ceeeb6de
4 changed files with 92 additions and 69 deletions

View file

@ -27,12 +27,15 @@ impl JoecalState {
let mut buf = [0; 65536];
let mut timeout = tokio::time::interval(Duration::from_secs(5));
timeout.tick().await;
loop {
tokio::select! {
_ = timeout.tick() => {
let rstate = self.running_state.lock().await;
if *rstate == RunningState::Stopping
let rstate = {
*self.running_state.lock().await
};
if rstate == RunningState::Stopping
{
break;
}
@ -45,7 +48,6 @@ impl JoecalState {
}
Err(e) => {
eprintln!("Error receiving message: {e}");
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
}
}
@ -63,8 +65,10 @@ impl JoecalState {
let mut src = src;
src.set_port(device.port); // Update the port to the one the device sent
let mut peers = self.peers.lock().await;
peers.insert(device.fingerprint.clone(), (src, device.clone()));
{
let mut peers = self.peers.lock().await;
peers.insert(device.fingerprint.clone(), (src, device.clone()));
}
if device.announce != Some(true) {
return;

View file

@ -23,6 +23,7 @@ use tokio::{
};
pub mod ui;
pub mod widgets;
pub type Peers = BTreeMap<SocketAddr, (String, String)>;

View file

@ -1,23 +1,12 @@
use ratatui::{
Frame,
layout::{Constraint, Direction, Layout, Margin, Rect},
style::Stylize,
text::Line,
widgets::{Block, Borders, List, ListItem, Padding},
};
use crate::{
App,
frontend::{CurrentScreen, Peers},
};
enum Action {
PushScreen(CurrentScreen),
PopScreen,
}
use crate::{App, frontend::widgets::*};
impl App {
pub fn draw(&self, frame: &mut Frame) {
pub fn draw(&mut self, frame: &mut Frame) {
let [top, middle, bottom] = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(3), Constraint::Min(3), Constraint::Min(3)])
@ -34,62 +23,15 @@ impl App {
.cloned()
.unwrap();
network_info(frame, footer_left.inner(Margin::new(1, 1)));
peers(&self.peers, frame, footer_right.inner(Margin::new(1, 1)));
let peers = PeersWidget { peers: &self.peers };
frame.render_widget(peers, footer_right.inner(Margin::new(1, 1)));
frame.render_widget(NetworkInfoWidget, footer_left.inner(Margin::new(1, 1)));
// draw the main frame last
frame.render_widget(self, frame.area());
}
}
fn peers(peers: &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 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);
frame.render_widget(list, area);
}
fn network_info(frame: &mut Frame, area: Rect) {
let udp: Line = format!("UDP socket:\t\t\t {:?}", joecalsend::LISTENING_SOCKET_ADDR)
.yellow()
.into();
let multicast: Line = format!(
"Multicast address:\t\t {:?}:{}",
joecalsend::MULTICAST_IP,
joecalsend::DEFAULT_PORT
)
.yellow()
.into();
let http: Line = format!(
"HTTP address:\t\t\t {:?}",
joecalsend::LISTENING_SOCKET_ADDR
)
.yellow()
.into();
let items = [
ListItem::new(udp),
ListItem::new(multicast),
ListItem::new(http),
];
let title = Line::from(" Listeners ".bold()).centered();
let block = Block::default()
.title(title)
.borders(Borders::all())
.padding(Padding::uniform(1));
let list = List::new(items).block(block);
frame.render_widget(list, area);
}
// helper function to create a centered rect using up certain percentage of the
// available rect `r`
fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {

76
src/frontend/widgets.rs Normal file
View file

@ -0,0 +1,76 @@
use ratatui::{
buffer::Buffer,
layout::Rect,
style::Stylize,
text::Line,
widgets::{Block, Borders, List, ListItem, Padding, Widget},
};
use super::Peers;
#[derive(Debug, Clone)]
pub struct PeersWidget<'p> {
pub peers: &'p Peers,
}
impl<'p> Widget for PeersWidget<'p> {
fn render(self, area: Rect, buf: &mut Buffer)
where
Self: Sized,
{
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());
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);
list.render(area, buf);
}
}
#[derive(Debug, Clone)]
pub struct NetworkInfoWidget;
impl Widget for NetworkInfoWidget {
fn render(self, area: Rect, buf: &mut Buffer)
where
Self: Sized,
{
let udp: Line = format!("UDP socket:\t\t\t {:?}", joecalsend::LISTENING_SOCKET_ADDR)
.yellow()
.into();
let multicast: Line = format!(
"Multicast address:\t\t {:?}:{}",
joecalsend::MULTICAST_IP,
joecalsend::DEFAULT_PORT
)
.yellow()
.into();
let http: Line = format!(
"HTTP address:\t\t\t {:?}",
joecalsend::LISTENING_SOCKET_ADDR
)
.yellow()
.into();
let items = [
ListItem::new(udp),
ListItem::new(multicast),
ListItem::new(http),
];
let title = Line::from(" Listeners ".bold()).centered();
let block = Block::default()
.title(title)
.borders(Borders::all())
.padding(Padding::uniform(1));
let list = List::new(items).block(block);
list.render(area, buf);
}
}