use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WidgetItem {
pub key: String,
pub value: String,
pub group: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WidgetWindowConfig {
pub label: String,
#[serde(default)]
pub url: Option<String>,
pub width: f64,
pub height: f64,
pub x: Option<f64>,
pub y: Option<f64>,
#[serde(default)]
pub always_on_top: bool,
#[serde(default = "default_true")]
pub skip_taskbar: bool,
#[serde(default)]
pub group: Option<String>,
#[serde(default)]
pub size: Option<String>,
}
fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WidgetConfig {
#[serde(default = "default_version")]
pub version: u32,
pub small: Option<WidgetElement>,
pub medium: Option<WidgetElement>,
pub large: Option<WidgetElement>,
}
fn default_version() -> u32 {
1
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum WidgetElement {
#[serde(rename = "vstack")]
VStack {
#[serde(default)]
children: Vec<WidgetElement>,
#[serde(default)]
spacing: Option<f64>,
#[serde(default)]
alignment: Option<HorizontalAlignment>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "hstack")]
HStack {
#[serde(default)]
children: Vec<WidgetElement>,
#[serde(default)]
spacing: Option<f64>,
#[serde(default)]
alignment: Option<VerticalAlignment>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "zstack")]
ZStack {
#[serde(default)]
children: Vec<WidgetElement>,
#[serde(default)]
alignment: Option<String>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "grid")]
Grid {
#[serde(default)]
children: Vec<WidgetElement>,
#[serde(default = "default_columns")]
columns: u32,
#[serde(default)]
spacing: Option<f64>,
#[serde(rename = "rowSpacing", default)]
row_spacing: Option<f64>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "container")]
Container {
#[serde(default)]
children: Vec<WidgetElement>,
#[serde(rename = "contentAlignment", default)]
content_alignment: Option<String>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "text")]
Text {
content: String,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(rename = "fontWeight", default)]
font_weight: Option<FontWeight>,
#[serde(rename = "fontDesign", default)]
font_design: Option<FontDesign>,
#[serde(rename = "textStyle", default)]
text_style: Option<TextStyle>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(default)]
alignment: Option<TextAlignment>,
#[serde(rename = "lineLimit", default)]
line_limit: Option<u32>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "image")]
Image {
#[serde(rename = "systemName", default)]
system_name: Option<String>,
#[serde(default)]
data: Option<String>,
#[serde(default)]
url: Option<String>,
#[serde(default)]
size: Option<f64>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(rename = "contentMode", default)]
content_mode: Option<ContentMode>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "progress")]
Progress {
value: f64,
#[serde(default = "default_total")]
total: f64,
#[serde(default)]
label: Option<String>,
#[serde(default)]
tint: Option<ColorValue>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(default)]
bar_style: Option<ProgressStyle>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "gauge")]
Gauge {
value: f64,
#[serde(default)]
min: Option<f64>,
#[serde(default)]
max: Option<f64>,
#[serde(default)]
label: Option<String>,
#[serde(rename = "currentValueLabel", default)]
current_value_label: Option<String>,
#[serde(default)]
tint: Option<ColorValue>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(rename = "gaugeStyle", default)]
gauge_style: Option<GaugeStyle>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "button")]
Button {
label: String,
#[serde(default)]
url: Option<String>,
#[serde(default)]
action: Option<String>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(rename = "backgroundColor", default)]
background_color: Option<ColorValue>,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(rename = "textAlignment", default)]
text_alignment: Option<TextAlignment>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "toggle")]
Toggle {
#[serde(rename = "isOn")]
is_on: bool,
#[serde(default)]
label: Option<String>,
#[serde(default)]
tint: Option<String>,
#[serde(default)]
action: Option<String>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "divider")]
Divider {
#[serde(default)]
color: Option<ColorValue>,
#[serde(default)]
thickness: Option<f64>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "spacer")]
Spacer {
#[serde(rename = "minLength", default)]
min_length: Option<f64>,
},
#[serde(rename = "date")]
Date {
date: String,
#[serde(rename = "dateStyle", default)]
date_style: Option<DateStyle>,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "chart")]
Chart {
#[serde(rename = "chartType")]
chart_type: ChartType,
#[serde(rename = "chartData")]
chart_data: Vec<ChartDataPoint>,
#[serde(default)]
tint: Option<ColorValue>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "list")]
List {
#[serde(default)]
items: Vec<ListItem>,
#[serde(default)]
spacing: Option<f64>,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "link")]
Link {
#[serde(default)]
children: Vec<WidgetElement>,
#[serde(default)]
url: Option<String>,
#[serde(default)]
action: Option<String>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "shape")]
Shape {
#[serde(rename = "shapeType")]
shape_type: ShapeType,
#[serde(default)]
fill: Option<ColorValue>,
#[serde(default)]
stroke: Option<ColorValue>,
#[serde(rename = "strokeWidth", default)]
stroke_width: Option<f64>,
#[serde(default)]
size: Option<f64>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "timer")]
Timer {
#[serde(rename = "targetDate")]
target_date: String,
#[serde(default)]
counting: Option<TimerCounting>,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(rename = "fontWeight", default)]
font_weight: Option<FontWeight>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "canvas")]
Canvas {
width: f64,
height: f64,
#[serde(default)]
elements: Vec<CanvasDrawCommand>,
#[serde(flatten)]
style: ElementStyle,
},
#[serde(rename = "label")]
Label {
text: String,
#[serde(rename = "systemName")]
system_name: String,
#[serde(rename = "iconColor", default)]
icon_color: Option<ColorValue>,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(rename = "fontWeight", default)]
font_weight: Option<FontWeight>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(default)]
spacing: Option<f64>,
#[serde(flatten)]
style: ElementStyle,
},
}
fn default_columns() -> u32 {
2
}
fn default_total() -> f64 {
1.0
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ElementStyle {
pub padding: Option<PaddingValue>,
pub background: Option<BackgroundValue>,
#[serde(rename = "cornerRadius")]
pub corner_radius: Option<f64>,
pub opacity: Option<f64>,
pub frame: Option<FrameConfig>,
pub border: Option<BorderConfig>,
pub shadow: Option<ShadowConfig>,
#[serde(rename = "clipShape")]
pub clip_shape: Option<ClipShape>,
pub flex: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ColorValue {
Solid(String),
Adaptive { light: String, dark: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ClipShape {
Circle,
Capsule,
Rectangle,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TextStyle {
LargeTitle,
Title,
Title2,
Title3,
Headline,
Subheadline,
Body,
Callout,
Footnote,
Caption,
Caption2,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum BackgroundValue {
Solid(String),
Gradient(GradientConfig),
Adaptive { light: String, dark: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GradientConfig {
#[serde(rename = "gradientType")]
pub gradient_type: GradientType,
pub colors: Vec<String>,
#[serde(default)]
pub direction: Option<GradientDirection>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum GradientType {
Linear,
Radial,
Angular,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum GradientDirection {
TopToBottom,
BottomToTop,
LeadingToTrailing,
TrailingToLeading,
TopLeadingToBottomTrailing,
TopTrailingToBottomLeading,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ShadowConfig {
#[serde(default)]
pub color: Option<String>,
#[serde(default)]
pub radius: Option<f64>,
#[serde(default)]
pub x: Option<f64>,
#[serde(default)]
pub y: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PaddingValue {
Uniform(f64),
Edges {
top: Option<f64>,
bottom: Option<f64>,
leading: Option<f64>,
trailing: Option<f64>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FrameConfig {
pub width: Option<f64>,
pub height: Option<f64>,
#[serde(rename = "maxWidth")]
pub max_width: Option<FrameDimension>,
#[serde(rename = "maxHeight")]
pub max_height: Option<FrameDimension>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FrameDimension {
Fixed(f64),
Keyword(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BorderConfig {
pub color: String,
#[serde(default = "default_border_width")]
pub width: f64,
}
fn default_border_width() -> f64 {
1.0
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum FontWeight {
Ultralight,
Thin,
Light,
Regular,
Medium,
Semibold,
Bold,
Heavy,
Black,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum FontDesign {
Default,
Monospaced,
Rounded,
Serif,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TextAlignment {
Leading,
Center,
Trailing,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum HorizontalAlignment {
Leading,
Center,
Trailing,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum VerticalAlignment {
Top,
Center,
Bottom,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ContentMode {
Fit,
Fill,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ProgressStyle {
Linear,
Circular,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum GaugeStyle {
Circular,
Linear,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum DateStyle {
Time,
Date,
Relative,
Offset,
Timer,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ChartType {
Bar,
Line,
Area,
Pie,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ShapeType {
Circle,
Capsule,
Rectangle,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum TimerCounting {
Up,
Down,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChartDataPoint {
pub label: String,
pub value: f64,
pub color: Option<ColorValue>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListItem {
pub text: String,
#[serde(default)]
pub checked: Option<bool>,
#[serde(default)]
pub action: Option<String>,
#[serde(default)]
pub payload: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "draw", rename_all = "camelCase")]
pub enum CanvasDrawCommand {
#[serde(rename = "circle")]
Circle {
cx: f64,
cy: f64,
r: f64,
#[serde(default)]
fill: Option<ColorValue>,
#[serde(default)]
stroke: Option<ColorValue>,
#[serde(rename = "strokeWidth", default)]
stroke_width: Option<f64>,
},
#[serde(rename = "line")]
Line {
x1: f64,
y1: f64,
x2: f64,
y2: f64,
#[serde(default)]
stroke: Option<ColorValue>,
#[serde(rename = "strokeWidth", default)]
stroke_width: Option<f64>,
#[serde(rename = "lineCap", default)]
line_cap: Option<String>,
},
#[serde(rename = "rect")]
Rect {
x: f64,
y: f64,
width: f64,
height: f64,
#[serde(default)]
fill: Option<ColorValue>,
#[serde(default)]
stroke: Option<ColorValue>,
#[serde(rename = "strokeWidth", default)]
stroke_width: Option<f64>,
#[serde(rename = "cornerRadius", default)]
corner_radius: Option<f64>,
},
#[serde(rename = "arc")]
Arc {
cx: f64,
cy: f64,
r: f64,
#[serde(rename = "startAngle")]
start_angle: f64,
#[serde(rename = "endAngle")]
end_angle: f64,
#[serde(default)]
fill: Option<ColorValue>,
#[serde(default)]
stroke: Option<ColorValue>,
#[serde(rename = "strokeWidth", default)]
stroke_width: Option<f64>,
},
#[serde(rename = "text")]
Text {
x: f64,
y: f64,
content: String,
#[serde(rename = "fontSize", default)]
font_size: Option<f64>,
#[serde(default)]
color: Option<ColorValue>,
#[serde(default)]
anchor: Option<String>,
},
#[serde(rename = "path")]
Path {
d: String,
#[serde(default)]
fill: Option<ColorValue>,
#[serde(default)]
stroke: Option<ColorValue>,
#[serde(rename = "strokeWidth", default)]
stroke_width: Option<f64>,
},
}