use crate::render::Events;
use crossterm::event::{Event, KeyEvent, MouseEvent};
use reactive_graph::computed::Memo;
use reactive_graph::effect::{Effect, EffectFunction};
use reactive_graph::owner::{LocalStorage, expect_context};
use reactive_graph::signal::Trigger;
use reactive_graph::traits::{IsDisposed, Notify, Track};
use std::time::Duration;
use tokio::time::sleep;
#[inline]
#[track_caller]
pub fn create_effect<T, M>(fun: impl EffectFunction<T, M> + 'static) -> Effect<LocalStorage>
where
T: 'static,
{
Effect::new(fun)
}
#[inline]
#[track_caller]
pub fn on_event(mut fun: impl FnMut(&Event) + 'static) -> Effect<LocalStorage> {
let events = expect_context::<Events>();
Effect::watch(
move || events.last(),
move |event, _, _| {
fun(event);
},
false,
)
}
#[inline]
#[track_caller]
pub fn on_key(mut fun: impl FnMut(KeyEvent) + 'static) -> Effect<LocalStorage> {
on_event(move |event| {
if let Some(key_event) = event.as_key_event() {
fun(key_event);
}
})
}
#[inline]
#[track_caller]
pub fn on_mouse(mut fun: impl FnMut(MouseEvent) + 'static) -> Effect<LocalStorage> {
on_event(move |event| {
if let Some(mouse_event) = event.as_mouse_event() {
fun(mouse_event);
}
})
}
#[inline]
#[track_caller]
pub fn on_resize(mut fun: impl FnMut(u16, u16) + 'static) -> Effect<LocalStorage> {
on_event(move |event| {
if let Some((x, y)) = event.as_resize_event() {
fun(x, y);
}
})
}
#[inline]
#[track_caller]
pub fn on_key_press(mut fun: impl FnMut(KeyEvent) + 'static) -> Effect<LocalStorage> {
on_event(move |event| {
if let Some(key_event) = event.as_key_press_event() {
fun(key_event);
}
})
}
#[inline]
#[track_caller]
pub fn create_memo<T: Send + Sync + 'static + PartialEq>(
fun: impl Fn() -> T + Send + Sync + 'static,
) -> Memo<T> {
Memo::new(move |_| fun())
}
#[inline]
#[track_caller]
pub fn create_timeout(mut fun: impl FnMut() + 'static, duration: Duration) -> Effect<LocalStorage> {
let trigger = Trigger::new();
any_spawner::Executor::spawn(async move {
sleep(duration).await;
trigger.notify();
});
Effect::watch(
move || trigger.track(),
move |_, _, _| {
fun();
},
false,
)
}
#[inline]
#[track_caller]
pub fn create_interval(
mut fun: impl FnMut() + 'static,
duration: Duration,
) -> Effect<LocalStorage> {
let trigger = Trigger::new();
any_spawner::Executor::spawn(async move {
loop {
if trigger.is_disposed() {
return;
} else {
trigger.notify();
}
sleep(duration).await;
}
});
Effect::watch(
move || trigger.track(),
move |_, _, _| {
fun();
},
false,
)
}