use dioxus::prelude::*; use dioxus_native_core::{custom_element::CustomElement, prelude::*}; use dioxus_native_core_macro::partial_derive_state; use shipyard::Component; use tokio::time::sleep; #[derive(Debug, Clone, PartialEq, Eq, Default, Component)] pub struct BlablaState { count: usize, } #[partial_derive_state] impl State for BlablaState { type ParentDependencies = (Self,); type ChildDependencies = (); type NodeDependencies = (); const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new() .with_attrs(AttributeMaskBuilder::Some(&["blabla"])) .with_element(); fn update<'a>( &mut self, _: NodeView, _: ::ElementBorrowed<'a>, parent: Option<::ElementBorrowed<'a>>, _: Vec<::ElementBorrowed<'a>>, _: &SendAnyMap, ) -> bool { if let Some((parent,)) = parent { if parent.count != 0 { self.count += 1; } } true } fn create<'a>( node_view: NodeView<()>, node: ::ElementBorrowed<'a>, parent: Option<::ElementBorrowed<'a>>, children: Vec<::ElementBorrowed<'a>>, context: &SendAnyMap, ) -> Self { let mut myself = Self::default(); myself.update(node_view, node, parent, children, context); myself } } mod dioxus_elements { macro_rules! builder_constructors { ( $( $(#[$attr:meta])* $name:ident { $( $(#[$attr_method:meta])* $fil:ident: $vil:ident, )* }; )* ) => { $( #[allow(non_camel_case_types)] $(#[$attr])* pub struct $name; impl $name { pub const TAG_NAME: &'static str = stringify!($name); pub const NAME_SPACE: Option<&'static str> = None; $( pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false); )* } impl GlobalAttributes for $name {} )* } } pub trait GlobalAttributes {} pub trait SvgAttributes {} builder_constructors! { blabla { }; testing132 { }; } } #[test] fn native_core_is_okay() { use std::sync::{Arc, Mutex}; use std::time::Duration; fn app(cx: Scope) -> Element { let colors = use_state(cx, || vec!["green", "blue", "red"]); let padding = use_state(cx, || 10); use_effect(cx, colors, |colors| async move { sleep(Duration::from_millis(1000)).await; colors.with_mut(|colors| colors.reverse()); }); use_effect(cx, padding, |padding| async move { sleep(Duration::from_millis(10)).await; padding.with_mut(|padding| { if *padding < 65 { *padding += 1; } else { *padding = 5; } }); }); let _big = colors[0]; let _mid = colors[1]; let _small = colors[2]; cx.render(rsx! { blabla { blabla { testing132 {} } } }) } let rt = tokio::runtime::Builder::new_current_thread() .enable_time() .build() .unwrap(); rt.block_on(async { let rdom = Arc::new(Mutex::new(RealDom::new([BlablaState::to_type_erased()]))); rdom.lock() .unwrap() .register_custom_element::(); let mut dioxus_state = DioxusState::create(&mut rdom.lock().unwrap()); let mut dom = VirtualDom::new(app); let mutations = dom.rebuild(); dioxus_state.apply_mutations(&mut rdom.lock().unwrap(), mutations); let ctx = SendAnyMap::new(); rdom.lock().unwrap().update_state(ctx); for _ in 0..10 { dom.wait_for_work().await; let mutations = dom.render_immediate(); dioxus_state.apply_mutations(&mut rdom.lock().unwrap(), mutations); let ctx = SendAnyMap::new(); rdom.lock().unwrap().update_state(ctx); } }); } struct TestElement { root: NodeId, } impl CustomElement for TestElement { const NAME: &'static str = "blabla"; fn create(dom: &mut RealDom<()>) -> Self { let root = dom.create_node(ElementNode { tag: "shadow_root".into(), namespace: None, attributes: Default::default(), listeners: Default::default(), }); Self { root: root.id() } } fn root(&self) -> NodeId { self.root } fn attributes_changed( &mut self, _dom: &mut RealDom<()>, attributes: &dioxus_native_core::node_ref::AttributeMask, ) { println!("attributes_changed"); println!("{:?}", attributes); } }