use crate::composer_context;
use crate::location_key;
use crate::owned::Owned;
use crate::runtime;
use crate::state::{
DerivedState, MutableState, OwnedMutableState, SnapshotStateList, SnapshotStateMap, State,
};
use std::hash::Hash;
use std::rc::Rc;
pub fn remember<T: 'static>(init: impl FnOnce() -> T) -> Owned<T> {
composer_context::with_composer(|composer| composer.remember(init))
}
#[allow(non_snake_case)]
pub fn rememberUpdatedState<T: Clone + 'static>(value: T) -> MutableState<T> {
composer_context::with_composer(|composer| {
let runtime = composer.runtime_handle();
let state = composer.remember(|| OwnedMutableState::with_runtime(value.clone(), runtime));
state.with(|s| {
s.set(value);
s.handle()
})
})
}
#[cfg(feature = "internal")]
#[allow(non_snake_case)]
pub fn withFrameNanos(
callback: impl FnOnce(u64) + 'static,
) -> crate::internal::FrameCallbackRegistration {
composer_context::with_composer(|composer| {
composer
.runtime_handle()
.frame_clock()
.with_frame_nanos(callback)
})
}
#[cfg(feature = "internal")]
#[allow(non_snake_case)]
pub fn withFrameMillis(
callback: impl FnOnce(u64) + 'static,
) -> crate::internal::FrameCallbackRegistration {
composer_context::with_composer(|composer| {
composer
.runtime_handle()
.frame_clock()
.with_frame_millis(callback)
})
}
#[allow(non_snake_case)]
pub fn mutableStateOf<T: Clone + 'static>(initial: T) -> MutableState<T> {
let runtime = composer_context::try_with_composer(|composer| composer.runtime_handle())
.or_else(runtime::current_runtime_handle)
.expect("mutableStateOf requires an active runtime. Create state inside a composition or after a Runtime is created.");
runtime.alloc_persistent_state(initial)
}
#[allow(non_snake_case)]
pub fn ownedMutableStateOf<T: Clone + 'static>(initial: T) -> OwnedMutableState<T> {
let runtime = composer_context::try_with_composer(|composer| composer.runtime_handle())
.or_else(runtime::current_runtime_handle)
.expect("ownedMutableStateOf requires an active runtime. Create state inside a composition or after a Runtime is created.");
OwnedMutableState::with_runtime(initial, runtime)
}
#[allow(non_snake_case)]
pub fn try_mutableStateOf<T: Clone + 'static>(initial: T) -> Option<MutableState<T>> {
let runtime = composer_context::try_with_composer(|composer| composer.runtime_handle())
.or_else(runtime::current_runtime_handle)?;
Some(runtime.alloc_persistent_state(initial))
}
#[allow(non_snake_case)]
pub fn mutableStateListOf<T, I>(values: I) -> SnapshotStateList<T>
where
T: Clone + 'static,
I: IntoIterator<Item = T>,
{
composer_context::with_composer(move |composer| composer.mutable_state_list_of(values))
}
#[allow(non_snake_case)]
pub fn mutableStateList<T: Clone + 'static>() -> SnapshotStateList<T> {
mutableStateListOf(std::iter::empty::<T>())
}
#[allow(non_snake_case)]
pub fn mutableStateMapOf<K, V, I>(pairs: I) -> SnapshotStateMap<K, V>
where
K: Clone + Eq + Hash + 'static,
V: Clone + 'static,
I: IntoIterator<Item = (K, V)>,
{
composer_context::with_composer(move |composer| composer.mutable_state_map_of(pairs))
}
#[allow(non_snake_case)]
pub fn mutableStateMap<K, V>() -> SnapshotStateMap<K, V>
where
K: Clone + Eq + Hash + 'static,
V: Clone + 'static,
{
mutableStateMapOf(std::iter::empty::<(K, V)>())
}
#[allow(non_snake_case)]
pub fn useState<T: Clone + 'static>(init: impl FnOnce() -> T) -> MutableState<T> {
composer_context::with_composer(|composer| {
let runtime = composer.runtime_handle();
composer
.remember(|| OwnedMutableState::with_runtime(init(), runtime))
.with(|state| state.handle())
})
}
#[allow(non_snake_case)]
pub fn derivedStateOf<T: 'static + Clone>(compute: impl Fn() -> T + 'static) -> State<T> {
composer_context::with_composer(|composer| {
let key = location_key(file!(), line!(), column!());
composer.with_group(key, |composer| {
let should_recompute = composer
.current_recranpose_scope()
.map(|scope| scope.should_recompose())
.unwrap_or(true);
let runtime = composer.runtime_handle();
let compute_rc: Rc<dyn Fn() -> T> = Rc::new(compute);
let derived =
composer.remember(|| DerivedState::new(runtime.clone(), compute_rc.clone()));
derived.update(|derived| {
derived.set_compute(compute_rc.clone());
if should_recompute {
derived.recompute();
}
});
derived.with(|derived| derived.state.as_state())
})
})
}