diff --git a/ui-dioxus/Cargo.lock b/ui-dioxus/Cargo.lock index e1e410e..af253d0 100644 --- a/ui-dioxus/Cargo.lock +++ b/ui-dioxus/Cargo.lock @@ -135,7 +135,6 @@ version = "0.1.0" dependencies = [ "agor-core", "dioxus", - "dioxus-motion", "log", "serde", "serde_json", @@ -543,12 +542,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "base16" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" - [[package]] name = "base64" version = "0.22.1" @@ -1355,7 +1348,6 @@ dependencies = [ "dioxus-html", "dioxus-logger", "dioxus-native", - "dioxus-router", "dioxus-signals", "dioxus-stores", "dioxus-web", @@ -1586,25 +1578,6 @@ dependencies = [ "tracing-wasm", ] -[[package]] -name = "dioxus-motion" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf087cf8951428be38394cff816a327f1d15f2953af8a65986578179dff21a6" -dependencies = [ - "dioxus", - "easer", - "futures-channel", - "futures-util", - "instant", - "smallvec", - "spin_sleep", - "thiserror 2.0.18", - "tokio", - "tracing", - "wide 1.2.0", -] - [[package]] name = "dioxus-native" version = "0.7.3" @@ -1651,41 +1624,6 @@ dependencies = [ "rustc-hash 2.1.1", ] -[[package]] -name = "dioxus-router" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5b31f9e27231389bf5a117b7074d22d8c58358b484a2558e56fbab20e64ca4" -dependencies = [ - "dioxus-cli-config", - "dioxus-core", - "dioxus-core-macro", - "dioxus-history", - "dioxus-hooks", - "dioxus-html", - "dioxus-router-macro", - "dioxus-signals", - "percent-encoding", - "rustversion", - "tracing", - "url", -] - -[[package]] -name = "dioxus-router-macro" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "838b9b441a95da62b39cae4defd240b5ebb0ec9f2daea1126099e00a838dc86f" -dependencies = [ - "base16", - "digest", - "proc-macro2", - "quote", - "sha2", - "slab", - "syn 2.0.117", -] - [[package]] name = "dioxus-rsx" version = "0.7.3" @@ -1873,15 +1811,6 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" -[[package]] -name = "easer" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba524f8b83c9c5bde02c2bb1627de9d1f81980489a6d54168cdfd08c258f917" -dependencies = [ - "num-traits", -] - [[package]] name = "either" version = "1.15.0" @@ -2979,15 +2908,6 @@ dependencies = [ "cfb", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "ioctl-rs" version = "0.1.6" @@ -4868,15 +4788,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "safe_arch" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7caad094bd561859bcd467734a720c3c1f5d1f338995351fefe2190c45efed" -dependencies = [ - "bytemuck", -] - [[package]] name = "same-file" version = "1.0.6" @@ -5119,17 +5030,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -5319,15 +5219,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "spin_sleep" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c07347b7c0301b9adba4350bdcf09c039d0e7160922050db0439b3c6723c8ab" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -6096,7 +5987,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a28554d13eb5daba527cc1b91b6c341372a0ae45ed277ffb2c6fbc04f319d7e" dependencies = [ - "wide 0.7.33", + "wide", ] [[package]] @@ -6944,17 +6835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" dependencies = [ "bytemuck", - "safe_arch 0.7.4", -] - -[[package]] -name = "wide" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198f6abc41fab83526d10880fa5c17e2b4ee44e763949b4bb34e2fd1e8ca48e4" -dependencies = [ - "bytemuck", - "safe_arch 1.0.0", + "safe_arch", ] [[package]] diff --git a/ui-dioxus/Cargo.toml b/ui-dioxus/Cargo.toml index 6df1156..1c88773 100644 --- a/ui-dioxus/Cargo.toml +++ b/ui-dioxus/Cargo.toml @@ -15,5 +15,4 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" uuid = { version = "1", features = ["v4"] } tokio = { version = "1", features = ["full"] } -dioxus-motion = { version = "0.3", default-features = false, features = ["desktop"] } log = "0.4" diff --git a/ui-dioxus/src/components/pulsing_dot.rs b/ui-dioxus/src/components/pulsing_dot.rs index f639b63..e899d32 100644 --- a/ui-dioxus/src/components/pulsing_dot.rs +++ b/ui-dioxus/src/components/pulsing_dot.rs @@ -1,10 +1,15 @@ -/// PulsingDot — Blitz-compatible animated status indicator using dioxus-motion. +/// PulsingDot — Blitz-compatible animated status indicator. /// -/// Uses dioxus-motion's Tween with LoopMode::Alternate for infinite ping-pong. -/// Avoids CSS @keyframes entirely — no Blitz full-scene repaint loop. +/// Instead of animating opacity (Blitz doesn't reliably restyle inline style changes), +/// we toggle between "bright" and "dim" CSS classes using a simple OS thread timer. +/// This changes the `class` attribute which Blitz DOES process for restyling. +/// +/// CPU cost: schedule_update fires every 1s (2 updates per cycle), not 30fps. use dioxus::prelude::*; -use dioxus_motion::prelude::*; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::time::Duration; #[derive(Clone, PartialEq)] pub enum DotState { @@ -18,44 +23,43 @@ pub enum DotState { #[component] pub fn PulsingDot(state: DotState, size: Option) -> Element { let should_pulse = matches!(state, DotState::Running | DotState::Stalled); - let mut opacity = use_motion(1.0f32); + let is_dim = use_hook(|| Arc::new(AtomicBool::new(false))); - // Infinite ping-pong tween: 1.0 → 0.4 → 1.0 → ... if should_pulse { - use_effect(move || { - opacity.animate_to( - 0.4, - AnimationConfig::new(AnimationMode::Tween( - Tween::new(Duration::from_millis(1000)) - )) - .with_loop(LoopMode::Alternate), - ); + let dim = is_dim.clone(); + let updater = use_hook(|| dioxus::dioxus_core::schedule_update()); + + use_hook(move || { + std::thread::spawn(move || { + loop { + std::thread::sleep(Duration::from_millis(1000)); + dim.fetch_xor(true, Ordering::Relaxed); // toggle + updater(); // trigger re-render + } + }); }); } - let (color, shadow) = match state { - DotState::Running => ("var(--ctp-green)", "0 0 6px var(--ctp-green)"), - DotState::Idle => ("var(--ctp-overlay0)", "none"), - DotState::Stalled => ("var(--ctp-peach)", "0 0 4px var(--ctp-peach)"), - DotState::Done => ("var(--ctp-blue)", "none"), - DotState::Error => ("var(--ctp-red)", "0 0 4px var(--ctp-red)"), + let base_class = match state { + DotState::Running => "dot-running", + DotState::Idle => "dot-idle", + DotState::Stalled => "dot-stalled", + DotState::Done => "dot-done", + DotState::Error => "dot-error", + }; + + let dim_class = if should_pulse && is_dim.load(Ordering::Relaxed) { + "dot-dim" + } else { + "" }; let sz = size.unwrap_or_else(|| "8px".to_string()); - let op = if should_pulse { opacity.get_value() } else { 1.0 }; rsx! { span { - style: " - display: inline-block; - width: {sz}; - height: {sz}; - border-radius: 50%; - background: {color}; - box-shadow: {shadow}; - opacity: {op}; - flex-shrink: 0; - ", + class: "pulsing-dot {base_class} {dim_class}", + style: "width: {sz}; height: {sz};", } } } diff --git a/ui-dioxus/src/theme.rs b/ui-dioxus/src/theme.rs index 8cd3adc..fcb10d9 100644 --- a/ui-dioxus/src/theme.rs +++ b/ui-dioxus/src/theme.rs @@ -257,6 +257,35 @@ body {{ .status-dot.stalled {{ background: var(--ctp-peach); }} + +/* PulsingDot component classes */ +.pulsing-dot {{ + display: inline-block; + border-radius: 50%; + flex-shrink: 0; +}} +.dot-running {{ + background: var(--ctp-green); + box-shadow: 0 0 6px var(--ctp-green); +}} +.dot-idle {{ + background: var(--ctp-overlay0); +}} +.dot-stalled {{ + background: var(--ctp-peach); + box-shadow: 0 0 4px var(--ctp-peach); +}} +.dot-done {{ + background: var(--ctp-blue); +}} +.dot-error {{ + background: var(--ctp-red); + box-shadow: 0 0 4px var(--ctp-red); +}} +.dot-dim {{ + background: var(--ctp-surface1); + box-shadow: none; +}} .status-dot.error {{ background: var(--ctp-red); }}