rush_sync_server/ui/
color.rs

1// ## BEGIN ##
2use crate::core::prelude::*;
3use log::Level;
4use once_cell::sync::Lazy;
5use std::collections::HashMap;
6use std::fmt;
7
8#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct AppColor(Color);
10
11// ✅ Zentrale Map für ALLE Farben & Kategorien
12static COLOR_MAP: Lazy<HashMap<&'static str, Color>> = Lazy::new(|| {
13    let mut map = HashMap::new();
14
15    // Standard-Farben
16    map.insert("black", Color::Black);
17    map.insert("red", Color::Red);
18    map.insert("green", Color::Green);
19    map.insert("yellow", Color::Yellow);
20    map.insert("blue", Color::Blue);
21    map.insert("magenta", Color::Magenta);
22    map.insert("cyan", Color::Cyan);
23    map.insert("gray", Color::Gray);
24    map.insert("darkgray", Color::DarkGray);
25    map.insert("lightred", Color::LightRed);
26    map.insert("lightgreen", Color::LightGreen);
27    map.insert("lightyellow", Color::LightYellow);
28    map.insert("lightblue", Color::LightBlue);
29    map.insert("lightmagenta", Color::LightMagenta);
30    map.insert("lightcyan", Color::LightCyan);
31    map.insert("white", Color::White);
32
33    // Kategorien
34    map.insert("error", Color::Red);
35    map.insert("warning", Color::Yellow);
36    map.insert("warn", Color::Yellow);
37    map.insert("info", Color::Green);
38    map.insert("debug", Color::Blue);
39    map.insert("trace", Color::White);
40    map.insert("lang", Color::Cyan);
41    map.insert("version", Color::LightBlue);
42
43    map
44});
45
46impl AppColor {
47    pub fn new(color: Color) -> Self {
48        Self(color)
49    }
50
51    /// Universelle Umwandlung aus Kategorie oder Farbe
52    pub fn from_any<T: Into<String>>(source: T) -> Self {
53        let key = source.into().to_lowercase();
54        Self(*COLOR_MAP.get(key.as_str()).unwrap_or(&Color::Gray))
55    }
56
57    /// Aus explizitem Log-Level
58    pub fn from_log_level(level: Level) -> Self {
59        Self::from_any(level.to_string())
60    }
61
62    /// String-Validierung für Config (bleibt Result)
63    pub fn from_string(color_str: &str) -> crate::core::error::Result<Self> {
64        COLOR_MAP
65            .get(&color_str.to_lowercase().as_str())
66            .map(|&c| Self(c))
67            .ok_or_else(|| AppError::Validation(format!("Ungültige Farbe: {}", color_str)))
68    }
69
70    pub fn format_message(&self, level: &str, message: &str) -> String {
71        if level.is_empty() {
72            format!("\x1B[{}m{}\x1B[0m", self.to_ansi_code(), message)
73        } else {
74            format!(
75                "\x1B[{}m[{}] {}\x1B[0m",
76                self.to_ansi_code(),
77                level,
78                message
79            )
80        }
81    }
82
83    pub fn to_ansi_code(&self) -> u8 {
84        match self.0 {
85            Color::Black => 30,
86            Color::Red => 31,
87            Color::Green => 32,
88            Color::Yellow => 33,
89            Color::Blue => 34,
90            Color::Magenta => 35,
91            Color::Cyan => 36,
92            Color::Gray => 37,
93            Color::DarkGray => 90,
94            Color::LightRed => 91,
95            Color::LightGreen => 92,
96            Color::LightYellow => 93,
97            Color::LightBlue => 94,
98            Color::LightMagenta => 95,
99            Color::LightCyan => 96,
100            Color::White => 97,
101            _ => 37,
102        }
103    }
104
105    pub fn to_name(&self) -> &'static str {
106        COLOR_MAP
107            .iter()
108            .find(|(_, &v)| v == self.0)
109            .map(|(k, _)| *k)
110            .unwrap_or("gray")
111    }
112}
113
114impl fmt::Display for AppColor {
115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116        write!(f, "{}", self.to_name())
117    }
118}
119
120impl From<AppColor> for Color {
121    fn from(app_color: AppColor) -> Self {
122        app_color.0
123    }
124}
125
126impl From<&AppColor> for Color {
127    fn from(app_color: &AppColor) -> Self {
128        app_color.0
129    }
130}
131
132impl Default for AppColor {
133    fn default() -> Self {
134        Self(Color::Gray)
135    }
136}
137// ## END ##