use serde::{Deserialize, Serialize};
use tuirealm::props::Color;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThemeMetadata {
pub name: String,
pub description: String,
pub author: String,
pub theme_name: Option<String>,
pub flavor_name: Option<String>,
pub theme_icon: Option<String>,
pub flavor_icon: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThemeColors {
pub text_primary: String,
pub text_muted: String,
pub surface: String,
pub primary_accent: String,
pub title_accent: String,
pub header_accent: String,
pub selection_bg: String,
pub selection_fg: String,
pub message_sequence: String,
pub message_id: String,
pub message_timestamp: String,
pub message_delivery_count: String,
pub message_state_ready: String,
pub message_state_deferred: String,
pub message_state_outcome: String,
pub message_state_failed: String,
pub queue_count: String,
pub namespace_list_item: String,
pub status_success: String,
pub status_warning: String,
pub status_error: String,
pub status_info: String,
pub status_loading: String,
pub shortcut_key: String,
pub shortcut_description: String,
pub help_section_title: String,
pub popup_background: String,
pub popup_text: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Theme {
pub metadata: ThemeMetadata,
pub colors: ThemeColors,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ThemeConfig {
pub theme_name: String,
pub flavor_name: String,
}
pub type FlavorMetadata = (String, String, String);
pub type ThemeCollectionWithMetadata = Vec<(String, Vec<FlavorMetadata>)>;
impl ThemeColors {
pub fn hex_to_color(&self, hex: &str) -> Color {
if hex.is_empty() || hex == "reset" {
return Color::Reset;
}
match hex.to_lowercase().as_str() {
"black" => Color::Black,
"red" => Color::Red,
"green" => Color::Green,
"yellow" => Color::Yellow,
"blue" => Color::Blue,
"magenta" => Color::Magenta,
"cyan" => Color::Cyan,
"white" => Color::White,
"gray" | "grey" => Color::Gray,
"darkgray" | "darkgrey" => Color::DarkGray,
"lightred" => Color::LightRed,
"lightgreen" => Color::LightGreen,
"lightyellow" => Color::LightYellow,
"lightblue" => Color::LightBlue,
"lightmagenta" => Color::LightMagenta,
"lightcyan" => Color::LightCyan,
"reset" => Color::Reset,
_ => {
if let Ok(rgb) = self.parse_hex_color(hex) {
Color::Rgb(rgb.0, rgb.1, rgb.2)
} else {
Color::Reset
}
}
}
}
fn parse_hex_color(&self, hex: &str) -> Result<(u8, u8, u8), &'static str> {
let hex = hex.trim_start_matches('#');
if hex.len() != 6 {
return Err("Invalid hex color format");
}
let r = u8::from_str_radix(&hex[0..2], 16).map_err(|_| "Invalid red component")?;
let g = u8::from_str_radix(&hex[2..4], 16).map_err(|_| "Invalid green component")?;
let b = u8::from_str_radix(&hex[4..6], 16).map_err(|_| "Invalid blue component")?;
Ok((r, g, b))
}
}
impl Default for ThemeConfig {
fn default() -> Self {
Self {
theme_name: "quetty".to_string(),
flavor_name: "dark".to_string(),
}
}
}