Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 79 additions & 5 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::app::Message;
use crate::i18n::{UnitSystem, unit_system};
use crate::services::upower::PeripheralDeviceKind;
use crate::utils::celsius_to_fahrenheit;
use crate::utils::themes::PrebuiltTheme;
use hex_color::HexColor;
use iced::futures::StreamExt;
use iced::{Color, Subscription, futures::SinkExt, stream::channel, theme::palette};
Expand Down Expand Up @@ -1033,11 +1034,9 @@ impl Default for MenuAppearance {
}
}

#[derive(Deserialize, Clone, Debug)]
#[serde(default)]
#[derive(Clone, Debug)]
pub struct Appearance {
pub font_name: Option<String>,
#[serde(deserialize_with = "scale_factor_deserializer")]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??

pub scale_factor: f64,
pub bar: BarAppearance,
pub menu: MenuAppearance,
Expand All @@ -1049,11 +1048,85 @@ pub struct Appearance {
pub text_color: AppearanceColor,
pub workspace_colors: Vec<AppearanceColor>,
pub special_workspace_colors: Option<Vec<AppearanceColor>>,
/// Blur the wallpaper behind ashell's translucent surfaces via
/// `ext-background-effect-v1`. No-op where the protocol is unsupported.
Comment on lines -1052 to -1053

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??

pub blur: BlurMode,
pub theme: Option<String>,
}

// 2. Define a Shadow Struct that replicates your fields as raw Serde values

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ai tool comment

#[derive(Deserialize)]
struct AppearanceShadow {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why AppearanceShadow?

font_name: Option<String>,
scale_factor: Option<serde_json::Value>, // Intercepted for your custom helper
bar: Option<BarAppearance>,
menu: Option<MenuAppearance>,
background_color: Option<BackgroundAppearanceColor>,
primary_color: Option<AppearanceColor>,
success_color: Option<AppearanceColor>,
warning_color: Option<AppearanceColor>,
danger_color: Option<AppearanceColor>,
text_color: Option<AppearanceColor>,
workspace_colors: Option<Vec<AppearanceColor>>,
special_workspace_colors: Option<Vec<AppearanceColor>>,
blur: Option<BlurMode>,
theme: Option<String>,
}
impl<'de> Deserialize<'de> for Appearance {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let shadow = AppearanceShadow::deserialize(deserializer)?;
let mut app = Appearance::default();
if let Some(ref theme_name) = shadow.theme {
app.theme = Some(theme_name.clone());
if let Some(theme) = PrebuiltTheme::parse(theme_name) {
theme.apply(&mut app);
}
}
if let Some(font) = shadow.font_name {
app.font_name = Some(font);
}
if let Some(bar_cfg) = shadow.bar {
app.bar = bar_cfg;
}
if let Some(menu_cfg) = shadow.menu {
app.menu = menu_cfg;
}
if let Some(bg_color) = shadow.background_color {
app.background_color = bg_color;
}
if let Some(primary) = shadow.primary_color {
app.primary_color = primary;
}
if let Some(success) = shadow.success_color {
app.success_color = success;
}
if let Some(warning) = shadow.warning_color {
app.warning_color = warning;
}
if let Some(danger) = shadow.danger_color {
app.danger_color = danger;
}
if let Some(text) = shadow.text_color {
app.text_color = text;
}
if let Some(workspaces) = shadow.workspace_colors {
app.workspace_colors = workspaces;
}
if let Some(special) = shadow.special_workspace_colors {
app.special_workspace_colors = Some(special);
}
if let Some(blur_cfg) = shadow.blur {
app.blur = blur_cfg;
}
if let Some(raw_scale) = shadow.scale_factor {
app.scale_factor =
scale_factor_deserializer(raw_scale).map_err(serde::de::Error::custom)?;
}

Ok(app)
}
}
/// When to ask the compositor for background blur.
#[derive(Deserialize, Default, Clone, Copy, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
Expand Down Expand Up @@ -1152,6 +1225,7 @@ impl Default for Appearance {
],
special_workspace_colors: None,
blur: BlurMode::default(),
theme: None,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use unicode_segmentation::UnicodeSegmentation;

pub mod launcher;
pub mod remote_value;

pub mod themes;
#[derive(Debug, Clone, Copy)]
pub enum IndicatorState {
Normal,
Expand Down
107 changes: 107 additions & 0 deletions src/utils/themes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use hex_color::HexColor;
use iced::{Color, Theme};

use crate::config::{Appearance, AppearanceColor};

pub struct PrebuiltTheme {
pub theme: Theme,
}
impl PrebuiltTheme {
pub fn parse(theme_name: &String) -> Option<Self> {
let theme = match theme_name
.to_lowercase()
.replace(|c| [' ', '-', '_'].contains(&c), "")
.as_str()
{
"light" => Some(Theme::Light),
"dark" => Some(Theme::Dark),
"dracula" => Some(Theme::Dracula),
"nord" => Some(Theme::Nord),
"solarizedlight" => Some(Theme::SolarizedLight),
"solarizeddark" => Some(Theme::SolarizedDark),
"gruvboxlight" => Some(Theme::GruvboxLight),
"gruvboxdark" => Some(Theme::GruvboxDark),
"catppuccinlatte" => Some(Theme::CatppuccinLatte),
"catppuccinfrappe" => Some(Theme::CatppuccinFrappe),
"catppuccinmacchiato" => Some(Theme::CatppuccinMacchiato),
"catppuccinmocha" | "catppuccin" => Some(Theme::CatppuccinMocha),
"tokyonight" => Some(Theme::TokyoNight),
"tokyonightstorm" => Some(Theme::TokyoNightStorm),
"tokyonightlight" => Some(Theme::TokyoNightLight),
"kanagawawave" => Some(Theme::KanagawaWave),
"kanagawadragon" => Some(Theme::KanagawaDragon),
"kanagawalotus" => Some(Theme::KanagawaLotus),
"moonfly" => Some(Theme::Moonfly),
"nightfly" => Some(Theme::Nightfly),
"oxocarbon" => Some(Theme::Oxocarbon),
"ferra" => Some(Theme::Ferra),
//Can add more using the custom theme in iced
_ => None,
};
if let Some(t) = theme {
return Some(PrebuiltTheme { theme: t });
}
return None;
}
pub fn apply(&self, app: &mut Appearance) {
let extended = self.theme.extended_palette();
let background = extended.background;
app.background_color = crate::config::BackgroundAppearanceColor::Complete {
base: color_to_hex_color(background.base.color),
weakest: Some(color_to_hex_color(background.weakest.color)),
weaker: Some(color_to_hex_color(background.weaker.color)),
weak: Some(color_to_hex_color(background.weak.color)),
neutral: Some(color_to_hex_color(background.neutral.color)),
strong: Some(color_to_hex_color(background.strong.color)),
stronger: Some(color_to_hex_color(background.stronger.color)),
strongest: Some(color_to_hex_color(background.strongest.color)),
text: Some(color_to_hex_color(background.base.text)),
};
let primary = extended.primary;
app.primary_color = AppearanceColor::Complete {
base: color_to_hex_color(primary.base.color),
strong: Some(color_to_hex_color(primary.strong.color)),
weak: Some(color_to_hex_color(primary.weak.color)),
text: Some(color_to_hex_color(primary.base.color)),
};
let success = extended.success;
app.success_color = AppearanceColor::Complete {
base: color_to_hex_color(success.base.color),
strong: Some(color_to_hex_color(success.strong.color)),
weak: Some(color_to_hex_color(success.weak.color)),
text: Some(color_to_hex_color(success.base.color)),
};
let warning = extended.warning;
app.warning_color = AppearanceColor::Complete {
base: color_to_hex_color(warning.base.color),
strong: Some(color_to_hex_color(warning.strong.color)),
weak: Some(color_to_hex_color(warning.weak.color)),
text: Some(color_to_hex_color(warning.base.color)),
};
let danger = extended.danger;
app.danger_color = AppearanceColor::Complete {
base: color_to_hex_color(danger.base.color),
strong: Some(color_to_hex_color(danger.strong.color)),
weak: Some(color_to_hex_color(danger.weak.color)),
text: Some(color_to_hex_color(danger.base.color)),
};
app.text_color = AppearanceColor::Complete {
base: color_to_hex_color(primary.base.color),
strong: Some(color_to_hex_color(primary.strong.color)),
weak: Some(color_to_hex_color(primary.weak.color)),
text: None,
};
app.workspace_colors = vec![
AppearanceColor::Simple(color_to_hex_color(primary.base.color)),
AppearanceColor::Simple(color_to_hex_color(success.base.color)),
AppearanceColor::Simple(color_to_hex_color(warning.base.color)),
];
}
}
pub fn color_to_hex_color(color: Color) -> HexColor {
let r = (color.r.clamp(0.0, 1.0) * 255.0).round() as u8;
let g = (color.g.clamp(0.0, 1.0) * 255.0).round() as u8;
let b = (color.b.clamp(0.0, 1.0) * 255.0).round() as u8;
let a = (color.a.clamp(0.0, 1.0) * 255.0).round() as u8;
HexColor { r, g, b, a }
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to avoid this conversion?

Loading