dioxus/packages/core/src/virtualdom.rs
2022-11-03 17:34:42 -07:00

101 lines
3.1 KiB
Rust

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 crate::{Element, Scope};
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: fn(Scope) -> Element) -> 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 props: *mut VComponentProps<(), ()> = unsafe { std::mem::transmute(props) };
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));
}
}