1use crate::composer_context;
2use crate::location_key;
3use crate::owned::Owned;
4use crate::runtime;
5use crate::state::{
6 DerivedState, MutableState, OwnedMutableState, SnapshotStateList, SnapshotStateMap, State,
7};
8use std::hash::Hash;
9use std::rc::Rc;
10
11pub fn remember<T: 'static>(init: impl FnOnce() -> T) -> Owned<T> {
12 composer_context::with_composer(|composer| composer.remember(init))
13}
14
15#[allow(non_snake_case)]
43pub fn rememberUpdatedState<T: Clone + 'static>(value: T) -> MutableState<T> {
44 composer_context::with_composer(|composer| {
45 let runtime = composer.runtime_handle();
46 let state = composer.remember(|| OwnedMutableState::with_runtime(value.clone(), runtime));
47 state.with(|s| {
48 s.set(value);
49 s.handle()
50 })
51 })
52}
53
54#[cfg(feature = "internal")]
55#[allow(non_snake_case)]
56pub fn withFrameNanos(
57 callback: impl FnOnce(u64) + 'static,
58) -> crate::internal::FrameCallbackRegistration {
59 composer_context::with_composer(|composer| {
60 composer
61 .runtime_handle()
62 .frame_clock()
63 .with_frame_nanos(callback)
64 })
65}
66
67#[cfg(feature = "internal")]
68#[allow(non_snake_case)]
69pub fn withFrameMillis(
70 callback: impl FnOnce(u64) + 'static,
71) -> crate::internal::FrameCallbackRegistration {
72 composer_context::with_composer(|composer| {
73 composer
74 .runtime_handle()
75 .frame_clock()
76 .with_frame_millis(callback)
77 })
78}
79
80#[allow(non_snake_case)]
116pub fn mutableStateOf<T: Clone + 'static>(initial: T) -> MutableState<T> {
117 let runtime = composer_context::try_with_composer(|composer| composer.runtime_handle())
118 .or_else(runtime::current_runtime_handle)
119 .expect("mutableStateOf requires an active runtime. Create state inside a composition or after a Runtime is created.");
120 runtime.alloc_persistent_state(initial)
121}
122
123#[allow(non_snake_case)]
124pub fn ownedMutableStateOf<T: Clone + 'static>(initial: T) -> OwnedMutableState<T> {
125 let runtime = composer_context::try_with_composer(|composer| composer.runtime_handle())
126 .or_else(runtime::current_runtime_handle)
127 .expect("ownedMutableStateOf requires an active runtime. Create state inside a composition or after a Runtime is created.");
128 OwnedMutableState::with_runtime(initial, runtime)
129}
130
131#[allow(non_snake_case)]
136pub fn try_mutableStateOf<T: Clone + 'static>(initial: T) -> Option<MutableState<T>> {
137 let runtime = composer_context::try_with_composer(|composer| composer.runtime_handle())
138 .or_else(runtime::current_runtime_handle)?;
139 Some(runtime.alloc_persistent_state(initial))
140}
141
142#[allow(non_snake_case)]
143pub fn mutableStateListOf<T, I>(values: I) -> SnapshotStateList<T>
144where
145 T: Clone + 'static,
146 I: IntoIterator<Item = T>,
147{
148 composer_context::with_composer(move |composer| composer.mutable_state_list_of(values))
149}
150
151#[allow(non_snake_case)]
152pub fn mutableStateList<T: Clone + 'static>() -> SnapshotStateList<T> {
153 mutableStateListOf(std::iter::empty::<T>())
154}
155
156#[allow(non_snake_case)]
157pub fn mutableStateMapOf<K, V, I>(pairs: I) -> SnapshotStateMap<K, V>
158where
159 K: Clone + Eq + Hash + 'static,
160 V: Clone + 'static,
161 I: IntoIterator<Item = (K, V)>,
162{
163 composer_context::with_composer(move |composer| composer.mutable_state_map_of(pairs))
164}
165
166#[allow(non_snake_case)]
167pub fn mutableStateMap<K, V>() -> SnapshotStateMap<K, V>
168where
169 K: Clone + Eq + Hash + 'static,
170 V: Clone + 'static,
171{
172 mutableStateMapOf(std::iter::empty::<(K, V)>())
173}
174
175#[allow(non_snake_case)]
201pub fn useState<T: Clone + 'static>(init: impl FnOnce() -> T) -> MutableState<T> {
202 composer_context::with_composer(|composer| {
203 let runtime = composer.runtime_handle();
204 composer
205 .remember(|| OwnedMutableState::with_runtime(init(), runtime))
206 .with(|state| state.handle())
207 })
208}
209
210#[allow(non_snake_case)]
211pub fn derivedStateOf<T: 'static + Clone>(compute: impl Fn() -> T + 'static) -> State<T> {
212 composer_context::with_composer(|composer| {
213 let key = location_key(file!(), line!(), column!());
214 composer.with_group(key, |composer| {
215 let should_recompute = composer
216 .current_recranpose_scope()
217 .map(|scope| scope.should_recompose())
218 .unwrap_or(true);
219 let runtime = composer.runtime_handle();
220 let compute_rc: Rc<dyn Fn() -> T> = Rc::new(compute);
221 let derived =
222 composer.remember(|| DerivedState::new(runtime.clone(), compute_rc.clone()));
223 derived.update(|derived| {
224 derived.set_compute(compute_rc.clone());
225 if should_recompute {
226 derived.recompute();
227 }
228 });
229 derived.with(|derived| derived.state.as_state())
230 })
231 })
232}