checker_tema_3_sd/
lib.rs

1use std::io::stdout;
2use std::sync::Arc;
3use std::time::Duration;
4
5use app::{App, AppReturn};
6use eyre::Result;
7use inputs::events::Events;
8use inputs::InputEvent;
9use io::IoEvent;
10use tui::backend::CrosstermBackend;
11use tui::Terminal;
12
13use crate::app::ui;
14
15pub mod app;
16pub mod inputs;
17pub mod io;
18
19pub async fn start_ui(app: &Arc<tokio::sync::Mutex<App>>) -> Result<()> {
20    // Configure Crossterm backend for tui
21    let mut stdout = stdout();
22    crossterm::terminal::enable_raw_mode()?;
23    crossterm::execute!(
24        stdout,
25        crossterm::terminal::EnterAlternateScreen,
26        crossterm::event::EnableMouseCapture
27    )?;
28    let backend = CrosstermBackend::new(stdout);
29    let mut terminal = Terminal::new(backend)?;
30    terminal.clear()?;
31    terminal.hide_cursor()?;
32
33    // User event handler
34    let tick_rate = Duration::from_millis(200);
35    let mut events = Events::new(tick_rate);
36
37    // Trigger state change from Init to Initialized
38    {
39        let mut app = app.lock().await;
40        app.dispatch(IoEvent::Initialize).await;
41    }
42
43    loop {
44        let mut app = app.lock().await;
45
46        // Render
47        terminal.draw(|rect| ui::draw(rect, &mut app))?;
48
49        // Handle inputs
50        let result = match events.next().await {
51            InputEvent::Input(key) => app.do_action(key).await,
52            InputEvent::Tick => app.update_on_tick().await,
53        };
54        // Check if we should exit
55        if result == AppReturn::Exit {
56            events.close();
57            break;
58        }
59    }
60
61    // Restore the terminal and close application
62    // terminal.clear()?;
63    terminal.show_cursor()?;
64    crossterm::execute!(
65        terminal.backend_mut(),
66        crossterm::terminal::LeaveAlternateScreen,
67        crossterm::event::DisableMouseCapture
68    )?;
69    crossterm::terminal::disable_raw_mode()?;
70
71    Ok(())
72}