theme config, layout preview, container alignment
Server: ThemeConfig entity + CRUD (GET/PUT /theme), SQLite persistence, ThemeUpdate broadcast to ESP32 on save and initial connect. Client: render engine uses theme colors, full-screen redraw on theme change. SPA: theme page with color pickers + presets, layout preview with TS port of layout engine, justify/align controls on containers. DisplayHint refactored to struct (kind + h_align + v_align).
This commit is contained in:
@@ -21,6 +21,10 @@ pub struct LayoutNodeDto {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub padding: Option<u8>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub justify_content: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub align_items: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub children: Option<Vec<LayoutChildDto>>,
|
||||
}
|
||||
|
||||
@@ -44,6 +48,8 @@ impl From<&LayoutNode> for LayoutNodeDto {
|
||||
direction: None,
|
||||
gap: None,
|
||||
padding: None,
|
||||
justify_content: None,
|
||||
align_items: None,
|
||||
children: None,
|
||||
},
|
||||
LayoutNode::Container(c) => Self {
|
||||
@@ -58,6 +64,25 @@ impl From<&LayoutNode> for LayoutNodeDto {
|
||||
),
|
||||
gap: Some(c.gap),
|
||||
padding: Some(c.padding),
|
||||
justify_content: Some(
|
||||
match c.justify_content {
|
||||
JustifyContent::Start => "start",
|
||||
JustifyContent::Center => "center",
|
||||
JustifyContent::End => "end",
|
||||
JustifyContent::SpaceBetween => "space_between",
|
||||
JustifyContent::SpaceEvenly => "space_evenly",
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
align_items: Some(
|
||||
match c.align_items {
|
||||
AlignItems::Start => "start",
|
||||
AlignItems::Center => "center",
|
||||
AlignItems::End => "end",
|
||||
AlignItems::Stretch => "stretch",
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
children: Some(
|
||||
c.children
|
||||
.iter()
|
||||
@@ -109,12 +134,26 @@ impl LayoutNodeDto {
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let justify_content = match self.justify_content.as_deref() {
|
||||
Some("center") => JustifyContent::Center,
|
||||
Some("end") => JustifyContent::End,
|
||||
Some("space_between") => JustifyContent::SpaceBetween,
|
||||
Some("space_evenly") => JustifyContent::SpaceEvenly,
|
||||
_ => JustifyContent::Start,
|
||||
};
|
||||
let align_items = match self.align_items.as_deref() {
|
||||
Some("center") => AlignItems::Center,
|
||||
Some("end") => AlignItems::End,
|
||||
Some("stretch") => AlignItems::Stretch,
|
||||
_ => AlignItems::Start,
|
||||
};
|
||||
|
||||
Ok(LayoutNode::Container(ContainerNode {
|
||||
direction,
|
||||
gap: self.gap.unwrap_or(0),
|
||||
padding: self.padding.unwrap_or(0),
|
||||
justify_content: JustifyContent::Start,
|
||||
align_items: AlignItems::Stretch,
|
||||
justify_content,
|
||||
align_items,
|
||||
children,
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@ pub mod client;
|
||||
pub mod data_source;
|
||||
pub mod layout;
|
||||
pub mod preset;
|
||||
pub mod theme;
|
||||
pub mod widget;
|
||||
|
||||
pub use client::ClientDto;
|
||||
pub use data_source::DataSourceDto;
|
||||
pub use layout::{LayoutChildDto, LayoutDto, LayoutNodeDto, SizingDto};
|
||||
pub use preset::{CreatePresetDto, PresetDto};
|
||||
pub use theme::{ColorDto, ThemeDto};
|
||||
pub use widget::{CreateWidgetDto, KeyMappingDto, WidgetDto};
|
||||
|
||||
52
crates/api-types/src/theme.rs
Normal file
52
crates/api-types/src/theme.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use domain::{ThemeColor, ThemeConfig};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ColorDto {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ThemeDto {
|
||||
pub primary: ColorDto,
|
||||
pub secondary: ColorDto,
|
||||
pub accent: ColorDto,
|
||||
pub text: ColorDto,
|
||||
pub background: ColorDto,
|
||||
}
|
||||
|
||||
impl From<&ThemeConfig> for ThemeDto {
|
||||
fn from(t: &ThemeConfig) -> Self {
|
||||
let c = |c: &ThemeColor| ColorDto {
|
||||
r: c.r,
|
||||
g: c.g,
|
||||
b: c.b,
|
||||
};
|
||||
Self {
|
||||
primary: c(&t.primary),
|
||||
secondary: c(&t.secondary),
|
||||
accent: c(&t.accent),
|
||||
text: c(&t.text),
|
||||
background: c(&t.background),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ThemeDto {
|
||||
pub fn into_domain(self) -> ThemeConfig {
|
||||
let c = |c: ColorDto| ThemeColor {
|
||||
r: c.r,
|
||||
g: c.g,
|
||||
b: c.b,
|
||||
};
|
||||
ThemeConfig {
|
||||
primary: c(self.primary),
|
||||
secondary: c(self.secondary),
|
||||
accent: c(self.accent),
|
||||
text: c(self.text),
|
||||
background: c(self.background),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user