lib: Restructure terminal and task modules

This commit is contained in:
Erik Kundt
2024-03-18 23:53:16 +01:00
parent 8d9962c8ff
commit c8e4c752f1
8 changed files with 72 additions and 61 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ use radicle_tui as tui;
use tui::common::cob::inbox::{self};
use tui::flux::store::{State, Store};
use tui::flux::termination::{self, Interrupted};
use tui::flux::task::{self, Interrupted};
use tui::flux::ui::cob::NotificationItem;
use tui::flux::ui::Frontend;
use tui::Exit;
@@ -186,7 +186,7 @@ impl App {
}
pub async fn run(&self) -> Result<Option<Selection>> {
let (terminator, mut interrupt_rx) = termination::create_termination();
let (terminator, mut interrupt_rx) = task::create_termination();
let (store, state_rx) = Store::<Action, InboxState, Selection>::new();
let (frontend, action_rx) = Frontend::<Action>::new();
let state = InboxState::try_from(&self.context)?;
+2 -2
View File
@@ -11,7 +11,7 @@ use radicle_tui as tui;
use tui::common::cob::issue::{self, Filter};
use tui::flux::store::{State, Store};
use tui::flux::termination::{self, Interrupted};
use tui::flux::task::{self, Interrupted};
use tui::flux::ui::cob::IssueItem;
use tui::flux::ui::Frontend;
use tui::Exit;
@@ -115,7 +115,7 @@ impl App {
}
pub async fn run(&self) -> Result<Option<Selection>> {
let (terminator, mut interrupt_rx) = termination::create_termination();
let (terminator, mut interrupt_rx) = task::create_termination();
let (store, state_rx) = Store::<Action, IssuesState, Selection>::new();
let (frontend, action_rx) = Frontend::<Action>::new();
let state = IssuesState::try_from(&self.context)?;
+2 -2
View File
@@ -11,7 +11,7 @@ use radicle_tui as tui;
use tui::common::cob::patch::{self, Filter};
use tui::flux::store::{State, Store};
use tui::flux::termination::{self, Interrupted};
use tui::flux::task::{self, Interrupted};
use tui::flux::ui::cob::PatchItem;
use tui::flux::ui::Frontend;
use tui::Exit;
@@ -116,7 +116,7 @@ impl App {
}
pub async fn run(&self) -> Result<Option<Selection>> {
let (terminator, mut interrupt_rx) = termination::create_termination();
let (terminator, mut interrupt_rx) = task::create_termination();
let (store, state_rx) = Store::<Action, PatchesState, Selection>::new();
let (frontend, action_rx) = Frontend::<Action>::new();
let state = PatchesState::try_from(&self.context)?;
+2 -1
View File
@@ -1,4 +1,5 @@
pub mod event;
pub mod store;
pub mod termination;
pub mod task;
pub mod terminal;
pub mod ui;
+1 -1
View File
@@ -7,7 +7,7 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use crate::Exit;
use super::termination::{Interrupted, Terminator};
use super::task::{Interrupted, Terminator};
const STORE_TICK_RATE: Duration = Duration::from_millis(1000);
+55
View File
@@ -0,0 +1,55 @@
use std::io::{self, Write};
use std::thread;
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};
use ratatui::prelude::*;
use tokio::sync::mpsc::{self};
use super::event::Event;
type Backend = TermionBackendExt<RawTerminal<io::Stdout>>;
pub fn setup(height: usize) -> anyhow::Result<Terminal<Backend>> {
let stdout = io::stdout().into_raw_mode()?;
let options = TerminalOptions {
viewport: Viewport::Inline(height as u16),
};
Ok(Terminal::with_options(
TermionBackendExt::new(stdout),
options,
)?)
}
pub fn restore(terminal: &mut Terminal<Backend>) -> anyhow::Result<()> {
terminal.clear()?;
Ok(())
}
pub fn events() -> mpsc::UnboundedReceiver<Event> {
let (tx, rx) = mpsc::unbounded_channel();
let events_tx = tx.clone();
thread::spawn(move || {
let stdin = io::stdin();
for key in stdin.keys().flatten() {
if events_tx.send(Event::Key(key)).is_err() {
return;
}
}
});
let events_tx = tx.clone();
if let Ok(mut signals) = signal_hook::iterator::Signals::new([libc::SIGWINCH]) {
thread::spawn(move || {
for _ in signals.forever() {
if events_tx.send(Event::Resize).is_err() {
return;
}
}
});
}
rx
}
+8 -53
View File
@@ -8,27 +8,23 @@ pub mod widget;
use std::fmt::Debug;
use std::io::{self};
use std::thread;
use std::time::Duration;
// use termion::event::Event;
use termion::input::TermRead;
use termion::raw::{IntoRawMode, RawTerminal};
use ratatui::prelude::*;
use termion::raw::RawTerminal;
use tokio::sync::broadcast;
use tokio::sync::mpsc::{self, UnboundedReceiver};
use super::event::Event;
use super::store::State;
use super::termination::Interrupted;
use super::task::Interrupted;
use super::terminal;
use super::ui::widget::{Render, Widget};
type Backend = TermionBackend<RawTerminal<io::Stdout>>;
const RENDERING_TICK_RATE: Duration = Duration::from_millis(250);
const INLINE_HEIGHT: u16 = 20;
const INLINE_HEIGHT: usize = 20;
pub struct Frontend<A> {
action_tx: mpsc::UnboundedSender<A>,
@@ -51,9 +47,10 @@ impl<A> Frontend<A> {
W: Widget<S, A> + Render<()>,
P: Clone + Send + Sync + Debug,
{
let mut terminal = setup_terminal()?;
let mut ticker = tokio::time::interval(RENDERING_TICK_RATE);
let mut events_rx = events();
let mut terminal = terminal::setup(INLINE_HEIGHT)?;
let mut events_rx = terminal::events();
let mut root = {
let state = state_rx.recv().await.unwrap();
@@ -84,50 +81,8 @@ impl<A> Frontend<A> {
terminal.draw(|frame| root.render::<Backend>(frame, frame.size(), ()))?;
};
restore_terminal(&mut terminal)?;
terminal::restore(&mut terminal)?;
result
}
}
fn setup_terminal() -> anyhow::Result<Terminal<Backend>> {
let stdout = io::stdout().into_raw_mode()?;
let options = TerminalOptions {
viewport: Viewport::Inline(INLINE_HEIGHT),
};
Ok(Terminal::with_options(
TermionBackend::new(stdout),
options,
)?)
}
fn restore_terminal(terminal: &mut Terminal<Backend>) -> anyhow::Result<()> {
terminal.clear()?;
Ok(())
}
fn events() -> mpsc::UnboundedReceiver<Event> {
let (tx, rx) = mpsc::unbounded_channel();
let events_tx = tx.clone();
thread::spawn(move || {
let stdin = io::stdin();
for key in stdin.keys().flatten() {
if events_tx.send(Event::Key(key)).is_err() {
return;
}
}
});
let events_tx = tx.clone();
if let Ok(mut signals) = signal_hook::iterator::Signals::new([libc::SIGWINCH]) {
thread::spawn(move || {
for _ in signals.forever() {
if events_tx.send(Event::Resize).is_err() {
return;
}
}
});
}
rx
}