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 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 pub fn elapsed(&self) -> bool {
35 (self.elapsed)()
36 }
37
38 pub fn reset(&mut self) {
40 self.instant.set_if_modified(Instant::now());
41 self.elapsed.set_if_modified(false);
42 }
43}
44
45pub fn use_timeout(duration: impl FnOnce() -> Duration) -> Timeout {
51 use_hook(|| Timeout::create(duration()))
52}