mirror of
https://github.com/DioxusLabs/dioxus
synced 2025-01-23 10:05:03 +00:00
141 lines
3.9 KiB
Rust
141 lines
3.9 KiB
Rust
use std::{
|
|
any::{Any, TypeId},
|
|
cell::RefCell,
|
|
collections::HashMap,
|
|
rc::Rc,
|
|
sync::Arc,
|
|
};
|
|
|
|
use dioxus_core::ScopeId;
|
|
use im_rc::HashSet;
|
|
|
|
use crate::Readable;
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
pub struct AtomId {
|
|
pub(crate) ptr: *const (),
|
|
pub(crate) type_id: TypeId,
|
|
}
|
|
|
|
pub struct AtomRoot {
|
|
pub atoms: RefCell<HashMap<AtomId, Slot>>,
|
|
pub update_any: Arc<dyn Fn(ScopeId)>,
|
|
}
|
|
|
|
pub struct Slot {
|
|
pub value: Rc<dyn Any>,
|
|
pub subscribers: HashSet<ScopeId>,
|
|
}
|
|
|
|
impl AtomRoot {
|
|
pub fn new(update_any: Arc<dyn Fn(ScopeId)>) -> Self {
|
|
Self {
|
|
update_any,
|
|
atoms: RefCell::new(HashMap::new()),
|
|
}
|
|
}
|
|
|
|
pub fn initialize<V: 'static>(&self, f: impl Readable<V>) {
|
|
let id = f.unique_id();
|
|
if self.atoms.borrow().get(&id).is_none() {
|
|
self.atoms.borrow_mut().insert(
|
|
id,
|
|
Slot {
|
|
value: Rc::new(f.init()),
|
|
subscribers: HashSet::new(),
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn register<V: 'static>(&self, f: impl Readable<V>, scope: ScopeId) -> Rc<V> {
|
|
let mut atoms = self.atoms.borrow_mut();
|
|
|
|
// initialize the value if it's not already initialized
|
|
if let Some(slot) = atoms.get_mut(&f.unique_id()) {
|
|
slot.subscribers.insert(scope);
|
|
match slot.value.clone().downcast() {
|
|
Ok(res) => res,
|
|
Err(e) => panic!(
|
|
"Downcasting atom failed: {:?}. Has typeid of {:?} but needs typeid of {:?}",
|
|
f.unique_id(),
|
|
e.type_id(),
|
|
TypeId::of::<V>()
|
|
),
|
|
}
|
|
} else {
|
|
let value = Rc::new(f.init());
|
|
let mut subscribers = HashSet::new();
|
|
subscribers.insert(scope);
|
|
|
|
atoms.insert(
|
|
f.unique_id(),
|
|
Slot {
|
|
value: value.clone(),
|
|
subscribers,
|
|
},
|
|
);
|
|
value
|
|
}
|
|
}
|
|
|
|
pub fn set<V: 'static>(&self, ptr: AtomId, value: V) {
|
|
let mut atoms = self.atoms.borrow_mut();
|
|
|
|
if let Some(slot) = atoms.get_mut(&ptr) {
|
|
slot.value = Rc::new(value);
|
|
log::trace!("found item with subscribers {:?}", slot.subscribers);
|
|
|
|
for scope in &slot.subscribers {
|
|
log::trace!("updating subcsriber");
|
|
(self.update_any)(*scope);
|
|
}
|
|
} else {
|
|
log::trace!("no atoms found for {:?}", ptr);
|
|
atoms.insert(
|
|
ptr,
|
|
Slot {
|
|
value: Rc::new(value),
|
|
subscribers: HashSet::new(),
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn unsubscribe(&self, ptr: AtomId, scope: ScopeId) {
|
|
let mut atoms = self.atoms.borrow_mut();
|
|
|
|
if let Some(slot) = atoms.get_mut(&ptr) {
|
|
slot.subscribers.remove(&scope);
|
|
}
|
|
}
|
|
|
|
// force update of all subscribers
|
|
pub fn force_update(&self, ptr: AtomId) {
|
|
if let Some(slot) = self.atoms.borrow_mut().get(&ptr) {
|
|
for scope in slot.subscribers.iter() {
|
|
log::trace!("updating subcsriber");
|
|
(self.update_any)(*scope);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn read<V: 'static>(&self, f: impl Readable<V>) -> Rc<V> {
|
|
let mut atoms = self.atoms.borrow_mut();
|
|
|
|
// initialize the value if it's not already initialized
|
|
if let Some(slot) = atoms.get_mut(&f.unique_id()) {
|
|
slot.value.clone().downcast().unwrap()
|
|
} else {
|
|
let value = Rc::new(f.init());
|
|
atoms.insert(
|
|
f.unique_id(),
|
|
Slot {
|
|
value: value.clone(),
|
|
subscribers: HashSet::new(),
|
|
},
|
|
);
|
|
value
|
|
}
|
|
}
|
|
}
|