framework_tool_tui/
event.rs1use std::time::Duration;
2
3use color_eyre::eyre::Report;
4use crossterm::event::EventStream;
5use futures::{FutureExt, StreamExt};
6use tokio::sync::{mpsc, watch};
7
8pub enum Event {
9 Tick,
10 Input(crossterm::event::Event),
11}
12
13pub struct EventLoop {
14 tx: mpsc::UnboundedSender<Event>,
15 rx: mpsc::UnboundedReceiver<Event>,
16 interval_tx: watch::Sender<Duration>,
17}
18
19impl Default for EventLoop {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25impl EventLoop {
26 pub fn new() -> Self {
27 let (tx, rx) = mpsc::unbounded_channel();
28 let (interval_tx, _interval_rx) = watch::channel(Duration::from_millis(1000));
29
30 Self {
31 tx,
32 rx,
33 interval_tx,
34 }
35 }
36
37 pub fn run(&self, tick_interval: Duration) {
38 let tx = self.tx.clone();
39 let mut interval_rx = self.interval_tx.subscribe();
40
41 tokio::spawn(async move {
42 let mut event_stream = EventStream::new();
43 let mut tick = tokio::time::interval(tick_interval);
44
45 loop {
46 let tick_event = tick.tick();
47 let input_event = event_stream.next().fuse();
48
49 tokio::select! {
50 _ = tick_event => {
51 let _ = tx.send(Event::Tick);
52 }
53 Some(Ok(event)) = input_event => {
54 let _ = tx.send(Event::Input(event));
55 }
56 Ok(()) = interval_rx.changed() => {
57 let new_interval = *interval_rx.borrow_and_update();
58 tick = tokio::time::interval(new_interval);
59 }
60 }
61 }
62 });
63 }
64
65 pub fn set_tick_interval(&self, tick_interval: Duration) {
66 let _ = self.interval_tx.send(tick_interval);
67 }
68
69 pub async fn next(&mut self) -> color_eyre::Result<Event> {
70 self.rx
71 .recv()
72 .await
73 .ok_or(Report::msg("Event loop async channel error"))
74 }
75}