Add: windows mvp - transparent bugs not fixed

This commit is contained in:
DaZuo0122
2026-02-12 22:58:33 +08:00
commit 61825f647d
147 changed files with 28498 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
[package]
name = "sprimo-protocol"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
[lints]
workspace = true
[dependencies]
serde.workspace = true
uuid.workspace = true
[dev-dependencies]
serde_json.workspace = true

View File

@@ -0,0 +1,173 @@
pub mod v1 {
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FrontendState {
Idle,
Active,
Success,
Error,
Dragging,
Hidden,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AnimationPriority(pub u8);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CommandEnvelope {
pub id: Uuid,
pub ts_ms: i64,
pub command: FrontendCommand,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", content = "payload", rename_all = "snake_case")]
pub enum FrontendCommand {
SetState {
state: FrontendState,
ttl_ms: Option<u64>,
},
PlayAnimation {
name: String,
priority: AnimationPriority,
duration_ms: Option<u64>,
interrupt: Option<bool>,
},
SetSpritePack {
pack_id_or_path: String,
},
SetTransform {
x: Option<f32>,
y: Option<f32>,
anchor: Option<String>,
scale: Option<f32>,
opacity: Option<f32>,
},
SetFlags {
click_through: Option<bool>,
always_on_top: Option<bool>,
visible: Option<bool>,
},
Toast {
text: String,
ttl_ms: Option<u64>,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CapabilityFlags {
pub supports_click_through: bool,
pub supports_transparency: bool,
pub supports_tray: bool,
pub supports_global_hotkey: bool,
pub supports_skip_taskbar: bool,
}
impl Default for CapabilityFlags {
fn default() -> Self {
Self {
supports_click_through: false,
supports_transparency: true,
supports_tray: false,
supports_global_hotkey: false,
supports_skip_taskbar: false,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OverlayFlags {
pub click_through: bool,
pub always_on_top: bool,
pub visible: bool,
}
impl Default for OverlayFlags {
fn default() -> Self {
Self {
click_through: false,
always_on_top: true,
visible: true,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FrontendStateSnapshot {
pub state: FrontendState,
pub current_animation: String,
pub flags: OverlayFlags,
pub x: f32,
pub y: f32,
pub scale: f32,
pub active_sprite_pack: String,
pub capabilities: CapabilityFlags,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_error: Option<String>,
}
impl FrontendStateSnapshot {
#[must_use]
pub fn idle(capabilities: CapabilityFlags) -> Self {
Self {
state: FrontendState::Idle,
current_animation: "idle".to_string(),
flags: OverlayFlags::default(),
x: 200.0,
y: 200.0,
scale: 1.0,
active_sprite_pack: "default".to_string(),
capabilities,
last_error: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct HealthResponse {
pub version: String,
pub build: String,
pub uptime_seconds: u64,
pub active_sprite_pack: String,
pub capabilities: CapabilityFlags,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ErrorResponse {
pub code: String,
pub message: String,
}
}
#[cfg(test)]
mod tests {
use super::v1::{AnimationPriority, CommandEnvelope, FrontendCommand, FrontendState};
use uuid::Uuid;
#[test]
fn command_envelope_roundtrip() {
let payload = CommandEnvelope {
id: Uuid::nil(),
ts_ms: 1_737_000_000_000,
command: FrontendCommand::PlayAnimation {
name: "dance".to_string(),
priority: AnimationPriority(9),
duration_ms: Some(1_200),
interrupt: Some(true),
},
};
let encoded = serde_json::to_string(&payload).expect("serialize");
let decoded: CommandEnvelope = serde_json::from_str(&encoded).expect("deserialize");
assert_eq!(decoded, payload);
}
#[test]
fn state_serializes_as_snake_case() {
let encoded = serde_json::to_string(&FrontendState::Hidden).expect("serialize");
assert_eq!(encoded, "\"hidden\"");
}
}