rustolio_web/hooks/
mod.rs1mod calculated;
12mod callbacks;
13mod context;
14mod effect;
15mod global;
16mod query;
17mod scope;
18mod signal;
19mod storage;
20
21use scope::{Dependency, Scope};
22
23pub(crate) use callbacks::{signal_updater_callback, signal_updater_callback_full};
24
25pub use calculated::Calculated;
26pub use context::Context;
27pub use effect::Effect;
28pub use global::{GlobalWrapper, global};
29pub use query::QuerySignal;
30pub use signal::{
31 GlobalSignal, Signal, SignalBase, SignalGetter, SignalSetter, SignalToggle, SignalUpdater,
32};
33pub use storage::StorageSignal;
34
35#[inline]
45pub fn spawn<F>(future: F)
46where
47 F: std::future::Future<Output = ()> + 'static,
48{
49 let scope_id = Scope::current();
50 spawn_raw(async move {
51 let Some(scope_id) = scope_id else {
52 future.await;
53 return;
54 };
55 Scope::push_existing(scope_id);
56 future.await;
57 Scope::pop();
58 });
59}
60
61pub fn spawn_result<F>(future: F)
62where
63 F: std::future::Future<Output = rustolio_utils::Result<()>> + 'static,
64{
65 spawn(async move { crate::error::match_result("Spawn", future.await) });
66}
67
68pub async fn timeout(ms: u16) -> crate::Result<()> {
73 #[cfg(all(not(target_arch = "wasm32")))]
74 {
75 use std::time::Duration;
76 tokio::time::sleep(Duration::from_millis(ms as u64)).await;
77 }
78
79 #[cfg(target_arch = "wasm32")]
80 {
81 use crate::prelude::*;
82 let _ = (|resolve, _| {
83 let id = crate::prelude::window()
84 .unwrap() .set_timeout_with_callback_and_timeout_and_arguments_0(&resolve, ms as i32)
86 .unwrap(); Scope::register_timeout(id);
88 })
89 .future::<JsValue>()
90 .await
91 .context("Failed to create run timeout")?;
92 }
93
94 Ok(())
95}
96
97fn spawn_raw<F>(future: F)
99where
100 F: std::future::Future<Output = ()> + 'static,
101{
102 #[cfg(not(target_arch = "wasm32"))]
104 futures::executor::block_on(future);
105
106 #[cfg(target_arch = "wasm32")]
108 {
109 wasm_bindgen_futures::spawn_local(future);
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use std::rc::Rc;
116
117 use super::*;
118
119 macro_rules! signal_getter {
120 ($($signal:ident), *) => {
121 $(
122 $signal.value();
123 $signal.peek();
124 )*
125 };
126 }
127
128 macro_rules! signal_setter {
129 ($val:expr, $($signal:ident), *) => {
130 $(
131 $signal.set($val);
132 )*
133 };
134 }
135
136 macro_rules! signal_updater {
137 ($val:expr, $($signal:ident), *) => {
138 $(
139 $signal.update(|s| *s = $val);
140 $signal.set_unchecked($val);
141 )*
142 };
143 }
144
145 #[derive(Clone, PartialEq)]
146 struct _ClonePartialeq;
147 fn _signals_clone_partialeq() {
148 let s = Signal::new(_ClonePartialeq);
149 let g = GlobalSignal::new(_ClonePartialeq);
150 let c = Calculated::new(|| _ClonePartialeq);
151 signal_getter!(s, g, c);
152 signal_setter!(_ClonePartialeq, s, g);
153 signal_updater!(_ClonePartialeq, s, g);
154 }
155
156 #[derive(Clone)]
157 struct _Clone;
158 fn _signals_clone() {
159 let s = Signal::new(_Clone);
160 let g = GlobalSignal::new(_Clone);
161 let c = Calculated::new(|| _Clone);
162 signal_getter!(s, g, c);
163 signal_updater!(_Clone, s, g);
164 }
165
166 #[derive(PartialEq)]
167 struct _Partialeq;
168 fn _signals_partialeq() {
169 let s = Signal::new(_Partialeq);
170 let g = GlobalSignal::new(_Partialeq);
171 let c = Calculated::new(|| Rc::new(_Partialeq));
172 signal_getter!(c);
173 signal_setter!(_Partialeq, s, g);
174 signal_updater!(_Partialeq, s, g);
175 }
176
177 struct _Nothing;
178 fn _signals() {
179 let s = Signal::new(_Nothing);
180 let g = GlobalSignal::new(_Nothing);
181 let c = Calculated::new(|| Rc::new(_Nothing));
182 signal_getter!(c);
183 signal_updater!(_Nothing, s, g);
184 }
185}