freya_sdk/
timeout.rs

1use std::time::{
2    Duration,
3    Instant,
4};
5
6use async_io::Timer;
7use freya_core::prelude::*;
8
9#[derive(Clone, Copy, PartialEq)]
10pub struct Timeout {
11    elapsed: State<bool>,
12    instant: State<Instant>,
13}
14
15impl Timeout {
16    /// You most likely want to use [use_timeout].
17    pub fn create(duration: Duration) -> Self {
18        let mut elapsed = State::create(false);
19        let instant = State::create(Instant::now());
20
21        spawn(async move {
22            loop {
23                Timer::after(duration).await;
24                if instant.read().elapsed() >= duration && !elapsed() {
25                    elapsed.set(true);
26                }
27            }
28        });
29
30        Timeout { elapsed, instant }
31    }
32
33    /// Check if the timeout has passed its specified [Duration].
34    pub fn elapsed(&self) -> bool {
35        (self.elapsed)()
36    }
37
38    /// Reset the timer.
39    pub fn reset(&mut self) {
40        self.instant.set_if_modified(Instant::now());
41        self.elapsed.set_if_modified(false);
42    }
43}
44
45/// Create a timeout with a given [Duration].
46/// This is useful to dinamically render a UI if only the timeout has not elapsed yet.
47///
48/// You can reset it by calling [Timeout::reset],
49/// use [Timeout::elapsed] to check if it has timed out or not.
50pub fn use_timeout(duration: impl FnOnce() -> Duration) -> Timeout {
51    use_hook(|| Timeout::create(duration()))
52}