use altar::*; use tokio::sync::mpsc; struct SimpleAsyncApp { count: usize, super_charge: Option, } enum Message { Charge, } impl SimpleAsyncApp { fn handle_key_event( &mut self, key_event: KeyEvent, tx: &mpsc::UnboundedSender, ) -> bool { match key_event.code { KeyCode::Down => self.count = self.count.saturating_sub(1), KeyCode::Up => self.count = self.count.saturating_add(1), KeyCode::Left => self.charged_adjust(false), KeyCode::Right => self.charged_adjust(true), KeyCode::Char('q') => return false, KeyCode::Char('c') => self.start_charging(tx), _ => {} } true } fn charged_adjust(&mut self, should_add: bool) { if let Some(charge) = self.super_charge { if charge == 10 { if should_add { self.count = self.count.saturating_add(10); } else { self.count = self.count.saturating_sub(10); } self.super_charge = None; } } } fn start_charging(&mut self, tx: &mpsc::UnboundedSender) { if self.super_charge.is_none() { self.super_charge = Some(0); let tx = tx.clone(); tokio::spawn(async move { for _ in 0..10 { tokio::time::sleep(std::time::Duration::from_millis(50)).await; tx.send(Message::Charge).unwrap(); } }); } } } impl AsyncTerminalApp for SimpleAsyncApp { type Message = Message; fn render(&self) -> impl View { let count = self.count.to_string(); let children = // okay for_each_view(0..self.count, |i| i.to_string()); let charging = self.super_charge.map(|c| { let slots: String = "=".repeat(c) + &" ".repeat(10 - c); hstack(( "CHARGING: ", hstack(("|", slots, "|")).spacing(0).color(Color::Red), )) }); vstack((hstack(("Count:", count)), charging, vstack(children))) .border() .border_style(BorderStyle::Rounded) } fn update( &mut self, event: Event, tx: &mpsc::UnboundedSender, ) -> bool { match event { Event::Key(key_event) => self.handle_key_event(key_event, tx), Event::Message(Message::Charge) => { self.super_charge = self.super_charge.map(|x| x.saturating_add(1)); true } } } } #[tokio::main] async fn main() { let mut app = SimpleAsyncApp { count: 5, super_charge: None, }; app.run(false).await; }