rush_sync_server/ui/
terminal.rs1use crate::core::constants::APP_TITLE;
6use crate::core::prelude::*;
7use crate::i18n::get_translation;
8use crossterm::{
9 cursor, execute,
10 style::ResetColor,
11 terminal::{
12 self, disable_raw_mode, enable_raw_mode, ClearType, EnterAlternateScreen,
13 LeaveAlternateScreen,
14 },
15};
16use std::io::Stdout;
17
18pub struct TerminalManager {
19 stdout: Stdout,
20 raw_mode_enabled: bool,
21}
22
23impl TerminalManager {
24 pub async fn new() -> Result<Self> {
25 let stdout = io::stdout();
26 Ok(Self {
27 stdout,
28 raw_mode_enabled: false,
29 })
30 }
31
32 pub async fn setup(&mut self) -> Result<()> {
33 self.enable_full_raw_mode().await?;
35
36 execute!(
38 self.stdout,
39 terminal::Clear(ClearType::All),
40 EnterAlternateScreen,
41 terminal::DisableLineWrap,
42 terminal::SetTitle(APP_TITLE),
43 crossterm::style::Print("\x1B]112\x07"), crossterm::style::Print("\x1B[0 q"), cursor::Hide
47 )?;
48
49 log::info!("✅ Terminal initialized");
50 log::debug!("🔧 Full raw mode enabled - All shortcuts intercepted");
51
52 Ok(())
53 }
54
55 async fn enable_full_raw_mode(&mut self) -> Result<()> {
57 enable_raw_mode()?;
59 self.raw_mode_enabled = true;
60
61 execute!(
63 self.stdout,
64 crossterm::style::Print("\x1B[?1000h"), crossterm::style::Print("\x1B[?1002h"), crossterm::style::Print("\x1B[?1015h"), crossterm::style::Print("\x1B[?1006h"), crossterm::style::Print("\x1B[?1049h"), )?;
72
73 log::debug!("🚀 Enhanced raw mode enabled - Terminal shortcuts bypassed");
74 Ok(())
75 }
76
77 pub async fn cleanup(&mut self) -> Result<()> {
78 log::info!("🔄 Starting terminal cleanup...");
79
80 if self.raw_mode_enabled {
82 self.disable_full_raw_mode().await?;
83 }
84
85 execute!(
87 self.stdout,
88 crossterm::style::Print("\x1B]12;\x07"), crossterm::style::Print("\x1B]Pl\x1B\\"), crossterm::style::Print("\x1B]112\x07"), crossterm::style::Print("\x1B[0 q"), ResetColor, cursor::Show, )?;
96
97 execute!(
99 self.stdout,
100 terminal::Clear(ClearType::All),
101 LeaveAlternateScreen,
102 terminal::EnableLineWrap,
103 cursor::MoveTo(0, 0)
104 )?;
105
106 execute!(
108 self.stdout,
109 crossterm::style::Print("\x1B[!p"), crossterm::style::Print("\x1B]12;white\x07"), crossterm::style::Print("\x1B[0 q"), crossterm::style::Print("\x1B[?25h"), ResetColor, )?;
116
117 self.stdout.flush()?;
119
120 log::info!("{}", get_translation("terminal.cleanup.done", &[]));
121 Ok(())
122 }
123
124 async fn disable_full_raw_mode(&mut self) -> Result<()> {
126 if !self.raw_mode_enabled {
127 return Ok(());
128 }
129
130 execute!(
132 self.stdout,
133 crossterm::style::Print("\x1B[?1000l"), crossterm::style::Print("\x1B[?1002l"), crossterm::style::Print("\x1B[?1015l"), crossterm::style::Print("\x1B[?1006l"), crossterm::style::Print("\x1B[?1049l"), )?;
141
142 disable_raw_mode()?;
144 self.raw_mode_enabled = false;
145
146 log::debug!("🔄 Enhanced raw mode disabled - Terminal shortcuts restored");
147 Ok(())
148 }
149
150 pub fn is_raw_mode_enabled(&self) -> bool {
152 self.raw_mode_enabled
153 }
154
155 pub async fn force_raw_mode(&mut self) -> Result<()> {
157 if !self.raw_mode_enabled {
158 log::warn!("🚨 Raw mode was lost, re-enabling...");
159 self.enable_full_raw_mode().await?;
160 }
161 Ok(())
162 }
163}
164
165impl Drop for TerminalManager {
167 fn drop(&mut self) {
168 if self.raw_mode_enabled {
169 let _ = futures::executor::block_on(self.disable_full_raw_mode());
171 log::warn!("🚨 Emergency terminal cleanup in destructor");
172 }
173 }
174}