dioxus_motion/
platform.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use instant::{Duration, Instant};
use std::future::Future;

pub trait TimeProvider {
    fn now() -> Instant;
    fn delay(duration: Duration) -> impl Future<Output = ()>;
}

#[derive(Debug, Clone, Copy)]
pub struct WebTime;

impl TimeProvider for WebTime {
    fn now() -> Instant {
        Instant::now()
    }

    fn delay(duration: Duration) -> impl Future<Output = ()> {
        // Use web-sys for wasm-bindgen compatible setTimeout
        #[cfg(feature = "web")]
        {
            use futures_util::FutureExt;
            use wasm_bindgen::prelude::*;
            use web_sys::window;

            let (sender, receiver) = futures_channel::oneshot::channel::<()>();

            if let Some(window) = window() {
                let cb = Closure::once(move || {
                    let _ = sender.send(());
                });

                // Use requestAnimationFrame for smoother animations
                if duration.as_millis() < 16 {
                    window
                        .request_animation_frame(cb.as_ref().unchecked_ref())
                        .unwrap();
                    cb.forget();
                } else {
                    // Use setTimeout for longer delays
                    window
                        .set_timeout_with_callback_and_timeout_and_arguments_0(
                            cb.as_ref().unchecked_ref(),
                            duration.as_millis() as i32,
                        )
                        .unwrap();
                    cb.forget();
                }
            }

            receiver.map(|_| ())
        }

        // Fallback for non-wasm or in case of window lookup failure
        #[cfg(not(feature = "web"))]
        {
            use futures_util::future::ready;
            std::thread::sleep(duration);
            ready(())
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct DesktopTime;

impl TimeProvider for DesktopTime {
    fn now() -> Instant {
        Instant::now()
    }

    fn delay(duration: Duration) -> impl Future<Output = ()> {
        #[cfg(not(feature = "web"))]
        {
            async move {
                tokio::time::sleep(duration).await;
            }
        }

        #[cfg(feature = "web")]
        {
            WebTime::delay(duration)
        }
    }
}