envelope_cli/tui/
terminal.rs1use anyhow::Result;
7use crossterm::{
8 execute,
9 terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
10};
11use ratatui::{backend::CrosstermBackend, Terminal};
12use std::io::{self, Stdout};
13use std::panic;
14
15use crate::config::paths::EnvelopePaths;
16use crate::config::settings::Settings;
17use crate::storage::Storage;
18
19use super::app::App;
20use super::event::{Event, EventHandler};
21use super::handler::handle_event;
22
23pub type Tui = Terminal<CrosstermBackend<Stdout>>;
25
26pub fn init_terminal() -> Result<Tui> {
28 let original_hook = panic::take_hook();
30 panic::set_hook(Box::new(move |panic_info| {
31 let _ = restore_terminal_impl();
33 original_hook(panic_info);
34 }));
35
36 enable_raw_mode()?;
38 let mut stdout = io::stdout();
39 execute!(stdout, EnterAlternateScreen)?;
40
41 let backend = CrosstermBackend::new(stdout);
43 let terminal = Terminal::new(backend)?;
44
45 Ok(terminal)
46}
47
48pub fn restore_terminal() -> Result<()> {
50 restore_terminal_impl()?;
51 Ok(())
52}
53
54fn restore_terminal_impl() -> Result<()> {
56 disable_raw_mode()?;
57 execute!(io::stdout(), LeaveAlternateScreen)?;
58 Ok(())
59}
60
61pub fn run_tui(storage: &Storage, settings: &Settings, paths: &EnvelopePaths) -> Result<()> {
63 let mut terminal = init_terminal()?;
65
66 let mut app = App::new(storage, settings, paths);
68
69 if let Ok(accounts) = storage.accounts.get_active() {
71 if let Some(first) = accounts.first() {
72 app.selected_account = Some(first.id);
73 }
74 }
75
76 let events = EventHandler::default();
78
79 loop {
81 terminal.draw(|frame| {
83 super::views::render(frame, &mut app);
84 })?;
85
86 match events.next()? {
88 Event::Key(key_event) => {
89 handle_event(&mut app, Event::Key(key_event))?;
90 }
91 Event::Mouse(mouse_event) => {
92 handle_event(&mut app, Event::Mouse(mouse_event))?;
93 }
94 Event::Resize(_, _) => {
95 }
97 Event::Tick => {
98 }
101 }
102
103 if app.should_quit {
105 break;
106 }
107 }
108
109 restore_terminal()?;
111
112 Ok(())
113}