use std::collections::BTreeMap;
use super::context::current_context;
use super::effect::{register_client_effect, use_effect, Effect};
use super::signal::{Signal, SignalId};
pub fn use_task<F>(callback: F) -> Effect
where
F: FnMut() + Send + Sync + 'static,
{
use_effect(callback)
}
pub fn use_visible_task(source: impl Into<String>) -> VisibleTaskId {
use_visible_task_with_captures(source, BTreeMap::new())
}
pub fn use_visible_task_with_captures(
source: impl Into<String>,
captures: BTreeMap<String, SignalId>,
) -> VisibleTaskId {
let source = source.into();
let id = current_context()
.map(|c| c.register_visible_task(&source, captures))
.unwrap_or(0);
VisibleTaskId(id)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct VisibleTaskId(pub u32);
pub fn visible_task_js(body: &str) -> String {
format!("(async (state, __resuma) => {{ {} }})", body)
}
pub fn use_debounce<T, F>(signal: &Signal<T>, ms: u64, mut on_change: F)
where
T: Clone + serde::Serialize + Send + Sync + 'static,
F: FnMut(T) + Send + Sync + 'static,
{
let _ = ms; let signal = signal.clone();
use_effect(move || {
on_change(signal.get());
});
}
pub fn register_debounce_effect<T>(
signal: &Signal<T>,
ms: u64,
captures: BTreeMap<String, super::signal::SignalId>,
js_body: &str,
) where
T: Clone + serde::Serialize + Send + Sync + 'static,
{
let signal_id = signal.id();
let mut watch_ids: Vec<super::signal::SignalId> = captures.values().copied().collect();
if !watch_ids.contains(&signal_id) {
watch_ids.push(signal_id);
}
let subscribe_lines: String = watch_ids
.iter()
.map(|id| {
format!(
"if (state.{id}) cleanups.push(state.{id}.subscribe(schedule));",
id = id
)
})
.collect::<Vec<_>>()
.join("\n ");
let body = format!(
"(state, __resuma) => {{
const key = '__deb_{n}';
const run = {js_body};
const cleanups = [];
const schedule = () => {{
clearTimeout(state[key]);
state[key] = setTimeout(() => run(state, __resuma), {ms});
}};
{subscribe_lines}
schedule();
return () => {{
clearTimeout(state[key]);
for (const unsub of cleanups) unsub?.();
}};
}}",
n = signal_id.0,
js_body = js_body,
ms = ms,
subscribe_lines = subscribe_lines,
);
register_client_effect("debounce", body, captures, None, Some(ms));
}