1use std::any::Any;
2use std::cell::RefCell;
3use std::rc::{Rc, Weak};
4
5use crate::{Signal, reactive, remember_with_key, scoped_effect, signal};
6
7pub struct MutableState<T: Clone + 'static> {
8 inner: Signal<T>,
9 saver: Option<Box<dyn StateSaver<T>>>,
10}
11
12pub trait StateSaver<T>: 'static {
13 fn save(&self, value: &T) -> Box<dyn Any>;
14 fn restore(&self, saved: &dyn Any) -> Option<T>;
15}
16
17pub fn remember_derived<T: Clone + 'static>(
18 key: impl Into<String>,
19 producer: impl Fn() -> T + 'static + Clone,
20) -> std::rc::Rc<crate::Signal<T>> {
21 let key: String = key.into();
22 produce_state(format!("derived:{key}"), producer)
23}
24
25pub trait StateHolder: 'static {
27 type State: Clone;
28 type Event;
29
30 fn initial_state() -> Self::State;
31 fn reduce(state: &Self::State, event: Self::Event) -> Self::State;
32}
33
34pub fn produce_state<T: Clone + 'static>(
39 key: impl Into<String>,
40 producer: impl Fn() -> T + 'static + Clone,
41) -> Rc<Signal<T>> {
42 let key = key.into();
43 remember_with_key(format!("produce:{key}"), || {
44 let out: Signal<T> = signal(producer());
45 let out_clone = out.clone();
46
47 let obs_id = reactive::new_observer({
48 let producer = producer.clone();
49 move || {
50 let v = producer();
51 out_clone.set(v);
52 }
53 });
54
55 reactive::run_observer_now(obs_id);
57
58 scoped_effect(move || {
59 Box::new(move || {
61 reactive::remove_observer(obs_id);
62 })
63 });
64 out
65 })
66}