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    /// Check if the timeout has passed its specified [Duration].
17    pub fn elapsed(&self) -> bool {
18        (self.elapsed)()
19    }
20
21    /// Reset the timer.
22    pub fn reset(&mut self) {
23        self.instant.set_if_modified(Instant::now());
24        self.elapsed.set_if_modified(false);
25    }
26}
27
28/// Create a timeout with a given [Duration].
29/// This is useful to dinamically render a UI if only the timeout has not elapsed yet.
30///
31/// You can reset it by calling [Timeout::reset],
32/// use [Timeout::elapsed] to check if it has timed out or not.
33pub fn use_timeout(duration: impl FnOnce() -> Duration) -> Timeout {
34    use_hook(|| {
35        let duration = duration();
36        let mut elapsed = State::create(false);
37        let instant = State::create(Instant::now());
38
39        spawn(async move {
40            loop {
41                Timer::after(duration).await;
42                if instant.read().elapsed() >= duration && !elapsed() {
43                    elapsed.set(true);
44                }
45            }
46        });
47
48        Timeout { elapsed, instant }
49    })
50}