mirror of
https://seed.radicle.dev/rad:z39mP9rQAaGmERfUMPULfPUi473tY.git
synced 2026-11-01 01:10:51 +08:00
lib: Restructure terminal and task modules
This commit is contained in:
@@ -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)?;
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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
@@ -1,4 +1,5 @@
|
||||
pub mod event;
|
||||
pub mod store;
|
||||
pub mod termination;
|
||||
pub mod task;
|
||||
pub mod terminal;
|
||||
pub mod ui;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user