use a vec instead of vecdeque for screen state stack

This commit is contained in:
Joe Ardent 2025-07-14 16:05:08 -07:00
parent 90312a4332
commit b5a950d49e
5 changed files with 44 additions and 17 deletions

10
Cargo.lock generated
View file

@ -375,6 +375,15 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "directories"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
dependencies = [
"dirs-sys",
]
[[package]] [[package]]
name = "dirs" name = "dirs"
version = "6.0.0" version = "6.0.0"
@ -1045,6 +1054,7 @@ dependencies = [
"axum", "axum",
"chrono", "chrono",
"crossterm", "crossterm",
"directories",
"figment", "figment",
"futures", "futures",
"julid-rs", "julid-rs",

View file

@ -7,6 +7,7 @@ edition = "2024"
axum = { version = "0.8", features = ["macros"] } axum = { version = "0.8", features = ["macros"] }
chrono = "0.4" chrono = "0.4"
crossterm = { version = "0.28", features = ["event-stream"] } crossterm = { version = "0.28", features = ["event-stream"] }
directories = "6.0.0"
figment = { version = "0.10", features = ["toml", "test", "env"] } figment = { version = "0.10", features = ["toml", "test", "env"] }
futures = "0.3.31" futures = "0.3.31"
julid-rs = { version = "1", default-features = false, features = ["serde"] } julid-rs = { version = "1", default-features = false, features = ["serde"] }

View file

@ -24,7 +24,7 @@ pub type Peers = BTreeMap<SocketAddr, (String, String)>;
pub struct App { pub struct App {
pub state: JoecalState, pub state: JoecalState,
pub screen: VecDeque<CurrentScreen>, pub screen: Vec<CurrentScreen>,
pub events: EventStream, pub events: EventStream,
// addr -> (alias, fingerprint) // addr -> (alias, fingerprint)
pub peers: Peers, pub peers: Peers,
@ -42,7 +42,7 @@ impl App {
pub fn new(state: JoecalState) -> Self { pub fn new(state: JoecalState) -> Self {
App { App {
state, state,
screen: VecDeque::from([CurrentScreen::Main]), screen: vec![CurrentScreen::Main],
peers: Default::default(), peers: Default::default(),
events: Default::default(), events: Default::default(),
} }
@ -53,7 +53,7 @@ impl App {
terminal.draw(|frame| self.draw(frame))?; terminal.draw(|frame| self.draw(frame))?;
self.handle_events().await?; self.handle_events().await?;
if let Some(&top) = self.screen.back() if let Some(&top) = self.screen.last()
&& top == CurrentScreen::Stopping && top == CurrentScreen::Stopping
{ {
self.state.stop().await; self.state.stop().await;
@ -105,23 +105,22 @@ impl App {
} }
fn exit(&mut self) { fn exit(&mut self) {
self.screen.clear(); self.screen.push(CurrentScreen::Stopping);
self.screen.push_back(CurrentScreen::Stopping);
} }
fn send(&mut self) { fn send(&mut self) {
self.screen.clear(); self.screen.push(CurrentScreen::Sending);
self.screen.push_back(CurrentScreen::Sending);
} }
fn recv(&mut self) { fn recv(&mut self) {
self.screen.clear(); self.screen.push(CurrentScreen::Receiving);
self.screen.push_back(CurrentScreen::Receiving);
} }
fn pop(&mut self) { fn pop(&mut self) {
if self.screen.pop_back().is_none() { if self.screen.last().is_none() {
self.screen.push_back(CurrentScreen::Main); self.screen.push(CurrentScreen::Main);
} else {
self.screen.pop();
} }
} }
} }
@ -146,7 +145,7 @@ impl Widget for &App {
let current_screen = format!( let current_screen = format!(
"{:?}", "{:?}",
self.screen.back().cloned().unwrap_or(CurrentScreen::Main) self.screen.last().copied().unwrap_or(CurrentScreen::Main)
); );
let text = Text::from(Line::from(current_screen.yellow())); let text = Text::from(Line::from(current_screen.yellow()));

View file

@ -3,10 +3,18 @@ use ratatui::{
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
style::Stylize, style::Stylize,
text::Line, text::Line,
widgets::{Block, Borders, List, ListItem}, widgets::{Block, Borders, List, ListItem, Padding},
}; };
use crate::{App, frontend::Peers}; use crate::{
App,
frontend::{CurrentScreen, Peers},
};
enum Action {
PushScreen(CurrentScreen),
PopScreen,
}
impl App { impl App {
pub fn draw(&self, frame: &mut Frame) { pub fn draw(&self, frame: &mut Frame) {
@ -43,7 +51,10 @@ fn peers(peers: &Peers, frame: &mut Frame, area: Rect) {
items.push(item); items.push(item);
} }
let title = Line::from(" Peers ".bold()).centered(); let title = Line::from(" Peers ".bold()).centered();
let block = Block::default().title(title).borders(Borders::all()); let block = Block::default()
.title(title)
.borders(Borders::all())
.padding(Padding::uniform(1));
let list = List::new(items).block(block); let list = List::new(items).block(block);
frame.render_widget(list, area); frame.render_widget(list, area);
} }
@ -68,7 +79,10 @@ fn network_info(frame: &mut Frame, area: Rect) {
ListItem::new(http), ListItem::new(http),
]; ];
let title = Line::from(" Listeners ".bold()).centered(); let title = Line::from(" Listeners ".bold()).centered();
let block = Block::default().title(title).borders(Borders::all()); let block = Block::default()
.title(title)
.borders(Borders::all())
.padding(Padding::uniform(1));
let list = List::new(items).block(block); let list = List::new(items).block(block);
frame.render_widget(list, area); frame.render_widget(list, area);
} }

View file

@ -44,6 +44,9 @@ async fn main() -> error::Result<()> {
let result = app.run(&mut terminal).await; let result = app.run(&mut terminal).await;
ratatui::restore(); ratatui::restore();
let mut alarm = tokio::time::interval(tokio::time::Duration::from_secs(5));
alarm.tick().await;
loop { loop {
tokio::select! { tokio::select! {
handle = handles.join_next() => { handle = handles.join_next() => {
@ -55,7 +58,7 @@ async fn main() -> error::Result<()> {
None => break, None => break,
} }
} }
_ = tokio::time::sleep(tokio::time::Duration::from_secs(5)) => { _ = alarm.tick() => {
println!("Exit timeout reached, aborting all unjoined tasks"); println!("Exit timeout reached, aborting all unjoined tasks");
handles.abort_all(); handles.abort_all();
break; break;