use crate::*;
pub(crate) fn get_current_hook_context() -> HookContext {
let opt: Option<HookContextRc> = current_hook_context().clone();
match opt {
Some(rc) => {
let mut ctx: HookContext =
HookContext::new(Rc::new(RefCell::new(HookContextInner::default())));
ctx.set_inner(rc);
ctx
}
None => {
let default_rc: HookContextRc = Rc::new(RefCell::new(HookContextInner::default()));
*current_hook_context_mut() = Some(default_rc.clone());
let mut ctx: HookContext =
HookContext::new(Rc::new(RefCell::new(HookContextInner::default())));
ctx.set_inner(default_rc);
ctx
}
}
}
pub(crate) fn with_hook_context<F, R>(context: HookContext, f: F) -> R
where
F: FnOnce() -> R,
{
let previous: Option<HookContextRc> = current_hook_context_mut().take();
*current_hook_context_mut() = Some(context.get_inner().clone());
let result: R = f();
*current_hook_context_mut() = previous;
result
}
pub(crate) fn create_hook_context() -> HookContext {
HookContext::default()
}
pub fn use_signal<T, F>(init: F) -> Signal<T>
where
T: Clone + PartialEq + 'static,
F: FnOnce() -> T,
{
let ctx: HookContext = get_current_hook_context();
let mut inner: RefMut<HookContextInner> = ctx.get_inner().borrow_mut();
let index: usize = inner.get_hook_index();
inner.set_hook_index(index + 1);
if index < inner.get_hooks().len()
&& let Some(existing) = inner.get_hooks()[index].downcast_ref::<Signal<T>>()
{
return *existing;
}
let signal: Signal<T> = Signal::create(init());
let cleanup_signal: Signal<T> = signal;
inner
.get_mut_cleanups()
.push(Box::new(move || cleanup_signal.clear_listeners()));
if index < inner.get_hooks().len() {
inner.get_mut_hooks()[index] = Box::new(signal);
} else {
inner.get_mut_hooks().push(Box::new(signal));
}
signal
}