use crate::*;
#[cfg(target_arch = "wasm32")]
pub(crate) fn dispatch_signal_update() {
if let Some(win) = window() {
let event: Event = Event::new("__euv_signal_update__").unwrap();
let _ = win.dispatch_event(&event);
}
}
#[cfg(target_arch = "wasm32")]
fn ensure_dispatch_callback() {
let win: Window = window().unwrap();
let key: JsValue = JsValue::from_str("__euv_dispatch");
if Reflect::get(&win, &key)
.unwrap_or(JsValue::UNDEFINED)
.is_undefined()
{
let closure: closure::Closure<dyn FnMut()> = closure::Closure::wrap(Box::new(|| {
SCHEDULED.store(false, Ordering::Relaxed);
dispatch_signal_update();
}));
let _ = Reflect::set(&win, &key, closure.as_ref());
closure.forget();
}
}
pub(crate) fn schedule_signal_update() {
if SCHEDULED.load(Ordering::Relaxed) || SUPPRESS_SCHEDULE.load(Ordering::Relaxed) {
return;
}
SCHEDULED.store(true, Ordering::Relaxed);
#[cfg(target_arch = "wasm32")]
{
let win: Option<Window> = window();
if win.is_none() {
SCHEDULED.store(false, Ordering::Relaxed);
return;
}
ensure_dispatch_callback();
let win: Window = win.unwrap();
let dispatch_fn: JsValue =
Reflect::get(&win, &JsValue::from_str("__euv_dispatch")).unwrap_or(JsValue::UNDEFINED);
if dispatch_fn.is_undefined() {
SCHEDULED.store(false, Ordering::Relaxed);
return;
}
let queue_microtask_val: JsValue =
Reflect::get(&win, &JsValue::from_str("queueMicrotask")).unwrap_or(JsValue::UNDEFINED);
if queue_microtask_val.is_undefined() {
SCHEDULED.store(false, Ordering::Relaxed);
return;
}
let queue_microtask: Function = queue_microtask_val.into();
let _ = queue_microtask.call1(&JsValue::NULL, &dispatch_fn);
}
#[cfg(not(target_arch = "wasm32"))]
{
SCHEDULED.store(false, Ordering::Relaxed);
}
}
pub fn with_suppressed_updates<F, R>(f: F) -> R
where
F: FnOnce() -> R,
{
let previous: bool = SUPPRESS_SCHEDULE.load(Ordering::Relaxed);
SUPPRESS_SCHEDULE.store(true, Ordering::Relaxed);
let result: R = f();
SUPPRESS_SCHEDULE.store(previous, Ordering::Relaxed);
result
}
pub fn subscribe_attr_signal<F>(attr_signal: Signal<String>, compute: F)
where
F: Fn() -> String + 'static,
{
#[cfg(target_arch = "wasm32")]
{
let signal_key: usize = attr_signal.get_inner() as usize;
let closure: Closure<dyn FnMut()> = Closure::wrap(Box::new(move || {
let new_value: String = compute();
attr_signal.set(new_value);
}));
register_attr_signal_listener(signal_key, closure);
}
#[cfg(not(target_arch = "wasm32"))]
{
let _ = attr_signal;
let _ = compute;
}
}
pub(crate) fn bool_signal_to_string_attribute_value(source: Signal<bool>) -> AttributeValue {
let initial: String = source.get().to_string();
let string_signal: Signal<String> = Signal::new(initial);
let string_signal_clone: Signal<String> = string_signal;
source.subscribe({
let source_inner: Signal<bool> = source;
move || {
let new_value: String = source_inner.get().to_string();
string_signal_clone.set(new_value);
}
});
AttributeValue::Signal(string_signal)
}