use crate::*;
pub(crate) fn get_current_hook_context() -> HookContext {
let hook_context_option: Option<HookContextRc> = current_hook_context().clone();
match hook_context_option {
Some(hook_context_rc) => {
let mut hook_context: HookContext =
HookContext::new(Rc::new(RefCell::new(HookContextInner::default())));
hook_context.set_inner(hook_context_rc);
hook_context
}
None => {
let default_hook_context_rc: HookContextRc =
Rc::new(RefCell::new(HookContextInner::default()));
*current_hook_context_mut() = Some(default_hook_context_rc.clone());
let mut hook_context: HookContext =
HookContext::new(Rc::new(RefCell::new(HookContextInner::default())));
hook_context.set_inner(default_hook_context_rc);
hook_context
}
}
}
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 hook_context: HookContext = get_current_hook_context();
let mut inner: RefMut<HookContextInner> = hook_context.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());
inner
.get_mut_cleanups()
.push(Box::new(move || 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
}