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