leptos_use/
use_timeout_fn.rs1use leptos::prelude::*;
2use std::marker::PhantomData;
3
4pub fn use_timeout_fn<CbFn, Arg, D>(
43 callback: CbFn,
44 delay: D,
45) -> UseTimeoutFnReturn<impl Fn(Arg) + Clone + Send + Sync, Arg, impl Fn() + Clone + Send + Sync>
46where
47 CbFn: Fn(Arg) + Clone + 'static,
48 Arg: 'static,
49 D: Into<Signal<f64>>,
50{
51 let delay = delay.into();
52
53 let (is_pending, set_pending) = signal(false);
54
55 let start;
56 let stop;
57
58 #[cfg(not(feature = "ssr"))]
59 {
60 use crate::sendwrap_fn;
61 use leptos::leptos_dom::helpers::TimeoutHandle;
62 use std::sync::{Arc, Mutex};
63 use std::time::Duration;
64
65 let timer = Arc::new(Mutex::new(None::<TimeoutHandle>));
66
67 let clear = {
68 let timer = Arc::clone(&timer);
69
70 move || {
71 let timer = timer.lock().unwrap();
72 if let Some(timer) = *timer {
73 timer.clear();
74 }
75 }
76 };
77
78 stop = {
79 let clear = clear.clone();
80
81 sendwrap_fn!(move || {
82 set_pending.set(false);
83 clear();
84 })
85 };
86
87 start = {
88 let timer = Arc::clone(&timer);
89 let callback = callback.clone();
90
91 sendwrap_fn!(move |arg: Arg| {
92 set_pending.set(true);
93
94 let handle = set_timeout_with_handle(
95 {
96 let timer = Arc::clone(&timer);
97 let callback = callback.clone();
98
99 move || {
100 set_pending.set(false);
101 *timer.lock().unwrap() = None;
102
103 #[cfg(debug_assertions)]
104 let _z = leptos::reactive::diagnostics::SpecialNonReactiveZone::enter();
105
106 callback(arg);
107 }
108 },
109 Duration::from_millis(delay.get_untracked() as u64),
110 )
111 .ok();
112
113 *timer.lock().unwrap() = handle;
114 })
115 };
116
117 on_cleanup(clear);
118 }
119
120 #[cfg(feature = "ssr")]
121 {
122 let _ = set_pending;
123 let _ = callback;
124 let _ = delay;
125
126 start = move |_: Arg| ();
127 stop = move || ();
128 }
129
130 UseTimeoutFnReturn {
131 is_pending: is_pending.into(),
132 start,
133 stop,
134 _marker: PhantomData,
135 }
136}
137
138pub struct UseTimeoutFnReturn<StartFn, StartArg, StopFn>
140where
141 StartFn: Fn(StartArg) + Clone + Send + Sync,
142 StopFn: Fn() + Clone + Send + Sync,
143{
144 pub is_pending: Signal<bool>,
146
147 pub start: StartFn,
149
150 pub stop: StopFn,
152
153 _marker: PhantomData<StartArg>,
154}