rush_sync_server/ui/
terminal.rs

1// =====================================================
2// FILE: src/ui/terminal.rs - FIXED OHNE FUTURES DEPENDENCY
3// =====================================================
4
5use 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        // ✅ SCHRITT 1: VOLLSTÄNDIGER RAW MODE
34        self.enable_full_raw_mode().await?;
35
36        // ✅ SCHRITT 2: TERMINAL SETUP
37        execute!(
38            self.stdout,
39            terminal::Clear(ClearType::All),
40            EnterAlternateScreen,
41            terminal::DisableLineWrap,
42            terminal::SetTitle(APP_TITLE),
43            // Cursor-Zustand beim Setup zurücksetzen
44            crossterm::style::Print("\x1B]112\x07"), // Reset cursor color
45            crossterm::style::Print("\x1B[0 q"),     // Reset cursor shape
46            cursor::Hide
47        )?;
48
49        Ok(())
50    }
51
52    /// ✅ VOLLSTÄNDIGER RAW MODE - Übernimmt ALLE Tastatur-Events
53    async fn enable_full_raw_mode(&mut self) -> Result<()> {
54        // Standard Raw Mode aktivieren
55        enable_raw_mode()?;
56        self.raw_mode_enabled = true;
57
58        // ✅ ERWEITERTE TERMINAL-KONTROLLE
59        execute!(
60            self.stdout,
61            // Alle Terminal-Escape-Sequenzen deaktivieren
62            crossterm::style::Print("\x1B[?1000h"), // Mouse tracking an (optional)
63            crossterm::style::Print("\x1B[?1002h"), // Cell motion mouse tracking
64            crossterm::style::Print("\x1B[?1015h"), // Enable urxvt mouse mode
65            crossterm::style::Print("\x1B[?1006h"), // Enable SGR mouse mode
66            // Spezielle Key-Kombinationen abfangen
67            crossterm::style::Print("\x1B[?1049h"), // Enable alternative screen buffer
68        )?;
69        Ok(())
70    }
71
72    pub async fn cleanup(&mut self) -> Result<()> {
73        log::info!("🔄 Starting terminal cleanup...");
74
75        // ✅ SCHRITT 1: Raw Mode zuerst deaktivieren
76        if self.raw_mode_enabled {
77            self.disable_full_raw_mode().await?;
78        }
79
80        // ✅ SCHRITT 2: Cursor-Farbe KOMPLETT zurücksetzen
81        execute!(
82            self.stdout,
83            // Reset cursor color (multiple standards for maximum compatibility)
84            crossterm::style::Print("\x1B]12;\x07"), // Xterm: empty = default
85            crossterm::style::Print("\x1B]Pl\x1B\\"), // iTerm2: reset
86            crossterm::style::Print("\x1B]112\x07"), // OSC 112: reset cursor color
87            crossterm::style::Print("\x1B[0 q"),     // Reset cursor shape to default
88            ResetColor,                              // Reset ANSI colors
89            cursor::Show,                            // Show cursor
90        )?;
91
92        // ✅ SCHRITT 3: Terminal-Modi zurücksetzen
93        execute!(
94            self.stdout,
95            terminal::Clear(ClearType::All),
96            LeaveAlternateScreen,
97            terminal::EnableLineWrap,
98            cursor::MoveTo(0, 0)
99        )?;
100
101        // ✅ SCHRITT 4: FINAL RESET - garantiert Standard-Terminal
102        execute!(
103            self.stdout,
104            // Kompletter Reset aller Terminal-Modi
105            crossterm::style::Print("\x1B[!p"), // RIS - Reset to Initial State
106            crossterm::style::Print("\x1B]12;white\x07"), // Explicit white cursor color
107            crossterm::style::Print("\x1B[0 q"), // Default cursor shape
108            crossterm::style::Print("\x1B[?25h"), // Show cursor
109            ResetColor,                         // Final color reset
110        )?;
111
112        // Buffer explizit leeren
113        self.stdout.flush()?;
114
115        log::info!("{}", get_translation("terminal.cleanup.done", &[]));
116        Ok(())
117    }
118
119    /// ✅ ERWEITERTEN RAW MODE DEAKTIVIEREN
120    async fn disable_full_raw_mode(&mut self) -> Result<()> {
121        if !self.raw_mode_enabled {
122            return Ok(());
123        }
124
125        // Erweiterte Modi deaktivieren
126        execute!(
127            self.stdout,
128            // Mouse tracking deaktivieren
129            crossterm::style::Print("\x1B[?1000l"), // Mouse tracking off
130            crossterm::style::Print("\x1B[?1002l"), // Cell motion mouse tracking off
131            crossterm::style::Print("\x1B[?1015l"), // Disable urxvt mouse mode
132            crossterm::style::Print("\x1B[?1006l"), // Disable SGR mouse mode
133            // Alternative screen buffer deaktivieren
134            crossterm::style::Print("\x1B[?1049l"), // Disable alternative screen buffer
135        )?;
136
137        // Standard Raw Mode deaktivieren
138        disable_raw_mode()?;
139        self.raw_mode_enabled = false;
140        Ok(())
141    }
142
143    /// ✅ DEBUG: Prüfe ob Raw Mode aktiv ist
144    pub fn is_raw_mode_enabled(&self) -> bool {
145        self.raw_mode_enabled
146    }
147
148    /// ✅ FORCE RAW MODE (falls es während der Laufzeit verloren geht)
149    pub async fn force_raw_mode(&mut self) -> Result<()> {
150        if !self.raw_mode_enabled {
151            log::warn!("🚨 Raw mode was lost, re-enabling...");
152            self.enable_full_raw_mode().await?;
153        }
154        Ok(())
155    }
156}
157
158// ✅ SICHERER DESTRUCTOR OHNE FUTURES
159impl Drop for TerminalManager {
160    fn drop(&mut self) {
161        if self.raw_mode_enabled {
162            // ✅ SYNC CLEANUP (ohne futures::executor)
163            let _ = disable_raw_mode();
164            let _ = execute!(
165                std::io::stdout(),
166                terminal::LeaveAlternateScreen,
167                cursor::Show,
168                ResetColor
169            );
170            log::warn!("🚨 Emergency terminal cleanup in destructor");
171        }
172    }
173}