WIP tui code re-organization

This commit is contained in:
Daniel Flanagan 2024-04-19 18:58:44 -05:00
parent 9d61b04731
commit b3b797f33c
4 changed files with 76 additions and 40 deletions

1
Cargo.lock generated
View file

@ -698,6 +698,7 @@ checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
"bitflags 2.5.0",
"crossterm_winapi",
"futures-core",
"libc",
"mio",
"parking_lot 0.12.1",

View file

@ -12,7 +12,7 @@ clap_derive = "4.5.4"
cliclack = "0.2.5"
color-eyre = "0.6.3"
config = "0.14.0"
crossterm = "0.27.0"
crossterm = { version = "0.27.0", features = ["event-stream"] }
futures = "0.3.30"
keyring = "2.3.2"
ratatui = "0.26.2"

View file

@ -113,8 +113,7 @@ mod ui {
impl Args {
pub async fn run(&self, tasks: SharedTasks) -> Result<()> {
let tui = crate::tui::Tui::new(tasks);
tui.run().await
crate::tui::Tui::run(tasks).await
}
}
}

View file

@ -6,6 +6,7 @@ use crossterm::{
ExecutableCommand,
};
use futures::stream::StreamExt;
use futures::FutureExt;
use ratatui::{
prelude::{CrosstermBackend, Stylize, Terminal},
widgets::Paragraph,
@ -14,39 +15,88 @@ use signal_hook::consts::*;
use signal_hook_tokio::Signals;
use std::io::stdout;
pub struct Tui {
tasks: SharedTasks,
pub struct Tui {}
enum Event {
CrosstermEvent(crossterm::event::Event),
// CrosstermError(Arc<dyn std::error::Error>),
Quit,
Tick,
}
impl Tui {
pub fn new(tasks: SharedTasks) -> Self {
Self { tasks }
}
pub async fn run(&self) -> Result<()> {
self.tui().await
}
async fn tui(&self) -> Result<()> {
pub async fn run(tasks: SharedTasks) -> Result<()> {
stdout().execute(EnterAlternateScreen)?;
enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
terminal.clear()?;
let mut signals = Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT])?;
let signalled: Arc<Mutex<bool>> = Arc::new(Mutex::new(false));
let handle = signals.handle();
let signaler = Arc::clone(&signalled);
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<Event>();
let mut signals = Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT])?;
let signal_handle = signals.handle();
let signal_sender = tx.clone();
tokio::spawn(async move {
// await a signal - once we receive one mark the boolean as true to
// quit the app
// await a signal - once we receive one send the quit event
signals.next().await;
let mut signalled = signaler.lock().await;
*signalled = true;
signal_sender.send(Event::Quit).unwrap();
});
let tick_rate = std::time::Duration::from_millis(1000);
let event_publisher_loop = tokio::spawn(async move {
let mut crossterm_event_stream = crossterm::event::EventStream::new();
let mut interval = tokio::time::interval(tick_rate);
loop {
let delay = interval.tick();
// TODO: read about FusedFutures
let crossterm_event = crossterm_event_stream.next().fuse();
// TODO: fix unwrap?
tokio::select! {
e = crossterm_event => {
match e {
Some(Ok(e)) => {
tx.send(Event::CrosstermEvent(e)).unwrap();
},
Some(Err(_e)) => {
// tx.send(Event::CrosstermError(Arc::new(e))).unwrap();
},
None => {},
}
}
_ = delay => {
tx.send(Event::Tick).unwrap();
}
}
}
});
// TODO: enable isig to re-allow ctrl-z?
loop {
let event = rx.recv().await;
match event {
Some(Event::CrosstermEvent(e)) => match e {
event::Event::Key(key) => {
if key.kind == KeyEventKind::Press
&& key.code == KeyCode::Char('c')
&& key.modifiers == KeyModifiers::CONTROL
{
break;
}
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
break;
}
}
_ => {}
},
Some(Event::Tick) => {}
Some(Event::Quit) => break,
None => {}
}
terminal.draw(|frame| {
let area = frame.size();
frame.render_widget(
@ -54,27 +104,13 @@ impl Tui {
area,
);
})?;
if event::poll(std::time::Duration::from_millis(10))? {
if let event::Event::Key(key) = event::read()? {
if key.kind == KeyEventKind::Press
&& key.code == KeyCode::Char('c')
&& key.modifiers == KeyModifiers::CONTROL
{
break;
}
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
break;
}
}
}
if *(*signalled).lock().await {
break;
}
}
handle.close();
signal_handle.close();
stdout().execute(LeaveAlternateScreen)?;
disable_raw_mode()?;
Ok(())
}
}