use crate::any_props::VComponentProps; use crate::arena::ElementPath; use crate::component::Component; use crate::diff::DirtyScope; use crate::future_container::FutureQueue; use crate::innerlude::SchedulerMsg; use crate::mutations::Mutation; use crate::nodes::{Template, TemplateId}; use crate::{ arena::ElementId, scopes::{ScopeId, ScopeState}, }; use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender}; use slab::Slab; use std::collections::{BTreeSet, HashMap}; pub struct VirtualDom { pub(crate) templates: HashMap<TemplateId, Template<'static>>, pub(crate) elements: Slab<ElementPath>, pub(crate) scopes: Slab<ScopeState>, pub(crate) scope_stack: Vec<ScopeId>, pub(crate) element_stack: Vec<ElementId>, pub(crate) dirty_scopes: BTreeSet<DirtyScope>, pub(crate) pending_futures: FutureQueue, pub(crate) sender: UnboundedSender<SchedulerMsg>, pub(crate) receiver: UnboundedReceiver<SchedulerMsg>, } impl VirtualDom { pub fn new(app: Component<()>) -> Self { let (sender, receiver) = futures_channel::mpsc::unbounded(); let mut res = Self { templates: Default::default(), scopes: Slab::default(), elements: Default::default(), scope_stack: Vec::new(), element_stack: vec![ElementId(0)], dirty_scopes: BTreeSet::new(), pending_futures: FutureQueue::new(sender.clone()), receiver, sender, }; let props = Box::into_raw(Box::new(VComponentProps::new_empty(app))); let root = res.new_scope(props); assert_eq!(root, ScopeId(0)); res } /// Render the virtualdom, without processing any suspense. pub fn rebuild<'a>(&'a mut self, mutations: &mut Vec<Mutation<'a>>) { // let root = self.scopes.get(0).unwrap(); let root_node = unsafe { std::mem::transmute(self.run_scope(ScopeId(0))) }; // let root_node = unsafe { std::mem::transmute(root.root_node()) }; self.scope_stack.push(ScopeId(0)); self.create(mutations, root_node); self.scope_stack.pop(); } /// Render what you can given the timeline and then move on pub async fn render_with_deadline<'a>( &'a mut self, future: impl std::future::Future<Output = ()>, mutations: &mut Vec<Mutation<'a>>, ) { todo!() } // Whenever the future is canceled, the VirtualDom will be pub async fn render<'a>(&'a mut self, mutations: &mut Vec<Mutation<'a>>) { // } /// Wait for futures internal to the virtualdom /// /// This is cancel safe, so if the future is dropped, you can push events into the virtualdom pub async fn wait_for_work(&mut self) {} pub fn get_scope(&self, id: ScopeId) -> Option<&ScopeState> { self.scopes.get(id.0) } pub fn base_scope(&self) -> &ScopeState { self.scopes.get(0).unwrap() } } impl Drop for VirtualDom { fn drop(&mut self) { // self.drop_scope(ScopeId(0)); } }