dioxus_native/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! A native renderer for Dioxus.
4//!
5//! ## Feature flags
6//!  - `default`: Enables the features listed below.
7//!  - `accessibility`: Enables [`accesskit`] accessibility support.
8//!  - `hot-reload`: Enables hot-reloading of Dioxus RSX.
9//!  - `menu`: Enables the [`muda`] menubar.
10//!  - `tracing`: Enables tracing support.
11
12mod assets;
13mod contexts;
14mod dioxus_application;
15mod dioxus_document;
16mod event;
17mod event_handler;
18mod mutation_writer;
19
20pub use dioxus_application::DioxusNativeApplication;
21pub use dioxus_document::DioxusDocument;
22pub use event::DioxusNativeEvent;
23
24use blitz_shell::{create_default_event_loop, BlitzShellEvent, Config, WindowConfig};
25use dioxus_core::{ComponentFunction, Element, VirtualDom};
26use std::any::Any;
27
28type NodeId = usize;
29
30/// Launch an interactive HTML/CSS renderer driven by the Dioxus virtualdom
31pub fn launch(app: fn() -> Element) {
32    launch_cfg(app, vec![], vec![])
33}
34
35pub fn launch_cfg(
36    app: fn() -> Element,
37    contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
38    cfg: Vec<Box<dyn Any>>,
39) {
40    launch_cfg_with_props(app, (), contexts, cfg)
41}
42
43// todo: props shouldn't have the clone bound - should try and match dioxus-desktop behavior
44pub fn launch_cfg_with_props<P: Clone + 'static, M: 'static>(
45    app: impl ComponentFunction<P, M>,
46    props: P,
47    contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send + Sync>>,
48    _cfg: Vec<Box<dyn Any>>,
49) {
50    let _cfg = _cfg
51        .into_iter()
52        .find_map(|cfg| cfg.downcast::<Config>().ok())
53        .unwrap_or_default();
54    let event_loop = create_default_event_loop::<BlitzShellEvent>();
55
56    // Turn on the runtime and enter it
57    let rt = tokio::runtime::Builder::new_multi_thread()
58        .enable_all()
59        .build()
60        .unwrap();
61    let _guard = rt.enter();
62
63    // Setup hot-reloading if enabled.
64    #[cfg(all(
65        feature = "hot-reload",
66        debug_assertions,
67        not(target_os = "android"),
68        not(target_os = "ios")
69    ))]
70    {
71        use crate::event::DioxusNativeEvent;
72        let proxy = event_loop.create_proxy();
73        dioxus_devtools::connect(move |event| {
74            let dxn_event = DioxusNativeEvent::DevserverEvent(event);
75            let _ = proxy.send_event(BlitzShellEvent::embedder_event(dxn_event));
76        })
77    }
78
79    // Spin up the virtualdom
80    // We're going to need to hit it with a special waker
81    // Note that we are delaying the initialization of window-specific contexts (net provider, document, etc)
82    let mut vdom = VirtualDom::new_with_props(app, props);
83
84    // Add contexts
85    for context in contexts {
86        vdom.insert_any_root_context(context());
87    }
88
89    // Create application
90    let mut application = DioxusNativeApplication::new(event_loop.create_proxy(), vdom);
91
92    // Run event loop
93    event_loop.run_app(&mut application).unwrap();
94}