gitai/
ui.rs

1use colored::Colorize;
2use console::Term;
3use indicatif::{ProgressBar, ProgressStyle};
4use parking_lot::Mutex;
5use ratatui::style::Color;
6use std::fmt::Write;
7use std::time::Duration;
8
9pub const STARLIGHT: Color = Color::Rgb(255, 255, 240);
10pub const NEBULA_PURPLE: Color = Color::Rgb(167, 132, 239);
11pub const CELESTIAL_BLUE: Color = Color::Rgb(75, 115, 235);
12pub const SOLAR_YELLOW: Color = Color::Rgb(255, 225, 100);
13pub const AURORA_GREEN: Color = Color::Rgb(140, 255, 170);
14pub const PLASMA_CYAN: Color = Color::Rgb(20, 255, 255);
15pub const METEOR_RED: Color = Color::Rgb(255, 89, 70);
16pub const GALAXY_PINK: Color = Color::Rgb(255, 162, 213);
17pub const COMET_ORANGE: Color = Color::Rgb(255, 165, 0);
18pub const BLACK_HOLE: Color = Color::Rgb(0, 0, 0);
19
20/// Track quiet mode state
21static QUIET_MODE: std::sync::LazyLock<Mutex<bool>> =
22    std::sync::LazyLock::new(|| Mutex::new(false));
23
24/// Enable or disable quiet mode
25pub fn set_quiet_mode(enabled: bool) {
26    let mut quiet_mode = QUIET_MODE.lock();
27    *quiet_mode = enabled;
28}
29
30/// Check if quiet mode is enabled
31pub fn is_quiet_mode() -> bool {
32    *QUIET_MODE.lock()
33}
34
35pub fn create_spinner(message: &str) -> ProgressBar {
36    // Don't create a spinner in quiet mode
37    if is_quiet_mode() {
38        return ProgressBar::hidden();
39    }
40
41    let pb = ProgressBar::new_spinner();
42    let Ok(style) = ProgressStyle::default_spinner()
43        .tick_chars("✦✧✶✷✸✹✺✻✼✽")
44        .template("{spinner} {msg}")
45    else {
46        return ProgressBar::hidden();
47    };
48
49    pb.set_style(style);
50    pb.set_message(message.to_string());
51    pb.enable_steady_tick(Duration::from_millis(100));
52    pb
53}
54
55pub fn print_info(message: &str) {
56    if !is_quiet_mode() {
57        println!("{}", message.cyan().bold());
58    }
59}
60
61pub fn print_warning(message: &str) {
62    if !is_quiet_mode() {
63        println!("{}", message.yellow().bold());
64    }
65}
66
67pub fn print_error(message: &str) {
68    // Always print errors, even in quiet mode
69    eprintln!("{}", message.red().bold());
70}
71
72pub fn print_success(message: &str) {
73    if !is_quiet_mode() {
74        println!("{}", message.green().bold());
75    }
76}
77
78pub fn print_version(version: &str) {
79    if !is_quiet_mode() {
80        println!(
81            "{} {} {}",
82            "🔮 Pilot".magenta().bold(),
83            "version".cyan(),
84            version.green()
85        );
86    }
87}
88
89/// Print content with decorative borders
90pub fn print_bordered_content(content: &str) {
91    if !is_quiet_mode() {
92        println!("{}", "━".repeat(50).bright_purple());
93        println!("{content}");
94        println!("{}", "━".repeat(50).bright_purple());
95    }
96}
97
98/// Print a simple message (respects quiet mode)
99pub fn print_message(message: &str) {
100    if !is_quiet_mode() {
101        println!("{message}");
102    }
103}
104
105/// Print an empty line (respects quiet mode)
106pub fn print_newline() {
107    if !is_quiet_mode() {
108        println!();
109    }
110}
111
112pub fn create_gradient_text(text: &str) -> String {
113    let gradient = vec![
114        (129, 0, 255), // Deep purple
115        (134, 51, 255),
116        (139, 102, 255),
117        (144, 153, 255),
118        (149, 204, 255), // Light cyan
119    ];
120
121    apply_gradient(text, &gradient)
122}
123
124pub fn create_secondary_gradient_text(text: &str) -> String {
125    let gradient = vec![
126        (75, 0, 130),   // Indigo
127        (106, 90, 205), // Slate blue
128        (138, 43, 226), // Blue violet
129        (148, 0, 211),  // Dark violet
130        (153, 50, 204), // Dark orchid
131    ];
132
133    apply_gradient(text, &gradient)
134}
135
136fn apply_gradient(text: &str, gradient: &[(u8, u8, u8)]) -> String {
137    let chars: Vec<char> = text.chars().collect();
138    let chars_len = chars.len();
139    let gradient_len = gradient.len();
140
141    let mut result = String::new();
142
143    if chars_len == 0 || gradient_len == 0 {
144        return result;
145    }
146
147    for (i, &c) in chars.iter().enumerate() {
148        let index = if chars_len == 1 {
149            0
150        } else {
151            i * (gradient_len - 1) / (chars_len - 1)
152        };
153        let (r, g, b) = gradient[index];
154        let _ = write!(result, "{}", c.to_string().truecolor(r, g, b));
155    }
156
157    result
158}
159
160pub fn write_gradient_text(
161    term: &Term,
162    text: &str,
163    gradient: &[(u8, u8, u8)],
164) -> std::io::Result<()> {
165    let gradient_text = apply_gradient(text, gradient);
166    term.write_line(&gradient_text)
167}
168
169pub fn write_colored_text(term: &Term, text: &str, color: (u8, u8, u8)) -> std::io::Result<()> {
170    let colored_text = text.truecolor(color.0, color.1, color.2);
171    term.write_line(&colored_text)
172}
173
174pub fn write_bold_text(term: &Term, text: &str) -> std::io::Result<()> {
175    term.write_line(&text.bold())
176}