From 25ad3da659d578ad42256ed728e3b81f4f6d72b6 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 17 Jan 2024 20:15:16 -0600 Subject: [PATCH] remove some generics from LaunchBuilder --- packages/core/src/lib.rs | 12 +- packages/core/src/platform.rs | 98 -------------- packages/core/src/virtual_dom.rs | 8 +- packages/desktop/src/app.rs | 21 ++- packages/desktop/src/config.rs | 1 - packages/desktop/src/desktop_context.rs | 4 +- packages/desktop/src/edits.rs | 11 +- packages/desktop/src/launch.rs | 48 +++---- packages/desktop/src/lib.rs | 5 +- packages/dioxus/src/launch.rs | 167 +++++++++--------------- packages/fullstack/src/launch.rs | 19 +-- packages/ssr/src/incremental.rs | 20 +-- packages/web/src/lib.rs | 9 +- packages/web/src/platform.rs | 23 ++-- 14 files changed, 142 insertions(+), 304 deletions(-) delete mode 100644 packages/core/src/platform.rs diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index e01f4c628..2cb783ad3 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -13,7 +13,6 @@ mod fragment; mod global_context; mod mutations; mod nodes; -mod platform; mod properties; mod runtime; mod scope_arena; @@ -32,7 +31,6 @@ pub(crate) mod innerlude { pub use crate::global_context::*; pub use crate::mutations::*; pub use crate::nodes::*; - pub use crate::platform::*; pub use crate::properties::*; pub use crate::runtime::{Runtime, RuntimeGuard}; pub use crate::scopes::*; @@ -76,11 +74,11 @@ pub(crate) mod innerlude { pub use crate::innerlude::{ fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering, - AnyProps, AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component, - ComponentFunction, CrossPlatformConfig, DynamicNode, Element, ElementId, Event, Fragment, - HasAttributes, IntoDynNode, Mutation, Mutations, NoOpMutations, PlatformBuilder, Properties, - RenderReturn, Runtime, ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode, - VComponent, VNode, VNodeInner, VPlaceholder, VProps, VText, VirtualDom, WriteMutations, + AnyProps, AnyValue, Attribute, AttributeValue, CapturedError, Component, ComponentFunction, + DynamicNode, Element, ElementId, Event, Fragment, HasAttributes, IntoDynNode, Mutation, + Mutations, NoOpMutations, Properties, RenderReturn, Runtime, ScopeId, ScopeState, Task, + Template, TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder, VProps, + VText, VirtualDom, WriteMutations, }; /// The purpose of this module is to alleviate imports of many common types diff --git a/packages/core/src/platform.rs b/packages/core/src/platform.rs deleted file mode 100644 index ed27a13a4..000000000 --- a/packages/core/src/platform.rs +++ /dev/null @@ -1,98 +0,0 @@ -use std::any::Any; - -use crate::{ - any_props::{AnyProps, VProps}, - properties::ComponentFunction, - VirtualDom, -}; - -/// A boxed object that can be injected into a component's context. -pub struct BoxedContext(Box); - -impl BoxedContext { - /// Create a new boxed context. - pub fn new(value: impl Any + Clone + 'static) -> Self { - Self(Box::new(value)) - } - - /// Unwrap the boxed context into its inner value. - pub fn into_inner(self) -> Box { - self.0.into_inner() - } -} - -impl Clone for BoxedContext { - fn clone(&self) -> Self { - Self(self.0.clone_box()) - } -} - -trait ClonableAny: Any { - fn clone_box(&self) -> Box; - - fn into_inner(self: Box) -> Box; -} - -impl ClonableAny for T { - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } - - fn into_inner(self: Box) -> Box { - self - } -} - -/// The platform-independent part of the config needed to launch an application. -#[derive(Clone)] -pub struct CrossPlatformConfig { - /// The root component function. - props: P, - // /// The contexts to provide to the root component. - // root_contexts: Vec, -} - -impl CrossPlatformConfig

{} - -impl CrossPlatformConfig

{ - /// Create a new cross-platform config. - pub fn new(props: P) -> Self { - CrossPlatformConfig { - props, - // root_contexts, - } - } - - // /// Push a new context into the root component's context. - // pub fn push_context(&mut self, context: T) { - // self.root_contexts.push(BoxedContext::new(context)); - // } - - /// Build a virtual dom from the config. - pub fn build_vdom(self) -> VirtualDom { - let mut vdom = VirtualDom::new_with_component(self.props); - - // for context in self.root_contexts { - // vdom.insert_boxed_root_context(context); - // } - - vdom - } -} - -/// A builder to launch a specific platform. -pub trait PlatformBuilder { - /// The platform-specific config needed to launch an application. - type Config: Default; - - /// Launch the app. - fn launch(config: CrossPlatformConfig

, platform_config: Self::Config); -} - -impl PlatformBuilder

for () { - type Config = (); - - fn launch(_: CrossPlatformConfig

, _: Self::Config) { - panic!("No platform is currently enabled. Please enable a platform feature for the dioxus crate."); - } -} diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 1bd35b337..864a3c5d5 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -13,7 +13,7 @@ use crate::{ nodes::{Template, TemplateId}, runtime::{Runtime, RuntimeGuard}, scopes::ScopeId, - AttributeValue, BoxedContext, ComponentFunction, Element, Event, Mutations, Task, VProps, + AttributeValue, ComponentFunction, Element, Event, Mutations, Task, VProps, }; use futures_util::{pin_mut, StreamExt}; use rustc_hash::{FxHashMap, FxHashSet}; @@ -361,10 +361,8 @@ impl VirtualDom { /// Build the virtualdom with a global context inserted into the base scope /// /// This method is useful for when you want to provide a context in your app without knowing its type - pub fn insert_boxed_root_context(&mut self, context: BoxedContext) { - self.base_scope() - .context() - .provide_any_context(context.into_inner()); + pub fn insert_any_root_context(&mut self, context: Box) { + self.base_scope().context().provide_any_context(context); } /// Manually mark a scope as requiring a re-render diff --git a/packages/desktop/src/app.rs b/packages/desktop/src/app.rs index 00b1ab4c2..cb43a97e3 100644 --- a/packages/desktop/src/app.rs +++ b/packages/desktop/src/app.rs @@ -10,8 +10,8 @@ use crate::{ webview::WebviewInstance, }; use crossbeam_channel::Receiver; -use dioxus_core::AnyProps; -use dioxus_core::{CrossPlatformConfig, ElementId}; +use dioxus_core::ElementId; +use dioxus_core::VirtualDom; use dioxus_html::{ native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData, HtmlEvent, PlatformEventData, @@ -29,10 +29,10 @@ use tao::{ }; /// The single top-level object that manages all the running windows, assets, shortcuts, etc -pub(crate) struct App { +pub(crate) struct App { // move the props into a cell so we can pop it out later to create the first window // iOS panics if we create a window before the event loop is started, so we toss them into a cell - pub(crate) dioxus_config: Cell>>, + pub(crate) unmounted_dom: Cell>, pub(crate) cfg: Cell>, // Stuff we need mutable access to @@ -59,11 +59,8 @@ pub struct SharedContext { pub(crate) target: EventLoopWindowTarget, } -impl App

{ - pub fn new( - cfg: Config, - dioxus_config: CrossPlatformConfig

, - ) -> (EventLoop, Self) { +impl App { + pub fn new(cfg: Config, virtual_dom: VirtualDom) -> (EventLoop, Self) { let event_loop = EventLoopBuilder::::with_user_event().build(); let app = Self { @@ -71,7 +68,7 @@ impl App

{ is_visible_before_start: true, webviews: HashMap::new(), control_flow: ControlFlow::Wait, - dioxus_config: Cell::new(Some(dioxus_config)), + unmounted_dom: Cell::new(Some(virtual_dom)), cfg: Cell::new(Some(cfg)), shared: Rc::new(SharedContext { event_handlers: WindowEventHandlers::default(), @@ -166,12 +163,12 @@ impl App

{ } pub fn handle_start_cause_init(&mut self) { - let dioxus_config = self.dioxus_config.take().unwrap(); + let virtual_dom = self.unmounted_dom.take().unwrap(); let cfg = self.cfg.take().unwrap(); self.is_visible_before_start = cfg.window.window.visible; - let webview = WebviewInstance::new(cfg, dioxus_config.build_vdom(), self.shared.clone()); + let webview = WebviewInstance::new(cfg, virtual_dom, self.shared.clone()); let id = webview.desktop_context.window.id(); self.webviews.insert(id, webview); diff --git a/packages/desktop/src/config.rs b/packages/desktop/src/config.rs index 589fd7c3e..f84baf6ea 100644 --- a/packages/desktop/src/config.rs +++ b/packages/desktop/src/config.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use std::path::PathBuf; -use dioxus_core::prelude::{Component, Element}; use tao::window::{Icon, WindowBuilder, WindowId}; use wry::{ http::{Request as HttpRequest, Response as HttpResponse}, diff --git a/packages/desktop/src/desktop_context.rs b/packages/desktop/src/desktop_context.rs index b0f960328..1c2cd84a1 100644 --- a/packages/desktop/src/desktop_context.rs +++ b/packages/desktop/src/desktop_context.rs @@ -12,11 +12,9 @@ use dioxus_core::{ prelude::{current_scope_id, ScopeId}, use_hook, VirtualDom, }; -use dioxus_interpreter_js::binary_protocol::Channel; use dioxus_interpreter_js::MutationState; -use rustc_hash::FxHashMap; use slab::Slab; -use std::{cell::RefCell, fmt::Debug, rc::Rc, rc::Weak, sync::atomic::AtomicU16}; +use std::{cell::RefCell, fmt::Debug, rc::Rc, rc::Weak}; use tao::{ event::Event, event_loop::EventLoopWindowTarget, diff --git a/packages/desktop/src/edits.rs b/packages/desktop/src/edits.rs index 35da2566f..ac4d7d7f7 100644 --- a/packages/desktop/src/edits.rs +++ b/packages/desktop/src/edits.rs @@ -1,15 +1,6 @@ -use dioxus_core::{AttributeValue, Template, TemplateAttribute, TemplateNode}; -use dioxus_html::event_bubbles; -use dioxus_interpreter_js::binary_protocol::Channel; -use rustc_hash::FxHashMap; -use std::{ - sync::atomic::AtomicU16, - sync::Arc, - sync::{atomic::Ordering, Mutex}, -}; +use std::{sync::Arc, sync::Mutex}; use std::fmt::{Debug, Formatter}; -use wry::RequestAsyncResponder; /// This handles communication between the requests that the webview makes and the interpreter. The interpreter constantly makes long running requests to the webview to get any edits that should be made to the DOM almost like server side events. /// It will hold onto the requests until the interpreter is ready to handle them and hold onto any pending edits until a new request is made. diff --git a/packages/desktop/src/launch.rs b/packages/desktop/src/launch.rs index e30d36b8a..d32070140 100644 --- a/packages/desktop/src/launch.rs +++ b/packages/desktop/src/launch.rs @@ -1,20 +1,18 @@ +pub use crate::Config; use crate::{ app::App, ipc::{EventData, IpcMethod, UserWindowEvent}, - Config, }; use dioxus_core::*; +use std::any::Any; use tao::event::{Event, StartCause, WindowEvent}; /// Launch the WebView and run the event loop, with configuration and root props. /// /// This will block the main thread, and *must* be spawned on the main thread. This function does not assume any runtime /// and is equivalent to calling launch_with_props with the tokio feature disabled. -pub fn launch_with_props_blocking( - dioxus_cfg: CrossPlatformConfig

, - desktop_config: Config, -) { - let (event_loop, mut app) = App::new(desktop_config, dioxus_cfg); +pub fn launch_with_props_blocking(virtual_dom: VirtualDom, desktop_config: Config) { + let (event_loop, mut app) = App::new(desktop_config, virtual_dom); event_loop.run(move |window_event, _, control_flow| { app.tick(&window_event); @@ -50,23 +48,27 @@ pub fn launch_with_props_blocking( }) } -/// The desktop renderer platform -pub struct DesktopPlatform; +/// Launches the WebView and runs the event loop, with configuration and root props. +pub fn launch( + root: fn() -> Element, + contexts: Vec Box + Send>>, + platform_config: Config, +) { + let mut virtual_dom = VirtualDom::new(root); -impl PlatformBuilder

for DesktopPlatform { - type Config = Config; - - fn launch(config: dioxus_core::CrossPlatformConfig

, platform_config: Self::Config) { - #[cfg(feature = "tokio")] - tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .unwrap() - .block_on(tokio::task::unconstrained(async move { - launch_with_props_blocking(config, platform_config) - })); - - #[cfg(not(feature = "tokio"))] - launch_with_props_blocking(config, platform_config) + for context in contexts { + virtual_dom.insert_any_root_context(context()); } + + #[cfg(feature = "tokio")] + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() + .block_on(tokio::task::unconstrained(async move { + launch_with_props_blocking(virtual_dom, platform_config) + })); + + #[cfg(not(feature = "tokio"))] + launch_with_props_blocking(config, platform_config) } diff --git a/packages/desktop/src/lib.rs b/packages/desktop/src/lib.rs index b0c74662f..43e7e006a 100644 --- a/packages/desktop/src/lib.rs +++ b/packages/desktop/src/lib.rs @@ -26,9 +26,8 @@ mod webview; #[cfg(any(target_os = "ios", target_os = "android"))] mod mobile_shortcut; -// The main entrypoint for this crate -pub use launch::*; -mod launch; +/// The main entrypoint for this crate +pub mod launch; // Reexport tao and wry, might want to re-export other important things pub use tao; diff --git a/packages/dioxus/src/launch.rs b/packages/dioxus/src/launch.rs index 92a0040c2..2ab660e62 100644 --- a/packages/dioxus/src/launch.rs +++ b/packages/dioxus/src/launch.rs @@ -5,83 +5,46 @@ use std::any::Any; use crate::prelude::*; use dioxus_core::VProps; use dioxus_core::{prelude::*, AnyProps}; -use dioxus_core::{BoxedContext, CrossPlatformConfig, PlatformBuilder}; - -#[cfg(feature = "fullstack")] -macro_rules! impl_launch_builder { - ($($inner:item)*) => { - impl - LaunchBuilder> - where F: ComponentFunction + Send + Sync + 'static - { - $($inner)* - } - }; -} - -#[cfg(not(feature = "fullstack"))] -macro_rules! impl_launch_builder { - ($($inner:item)*) => { - impl - LaunchBuilder> - where F: ComponentFunction + 'static - { - $($inner)* - } - }; -} /// A builder for a fullstack app. -pub struct LaunchBuilder = CurrentPlatform> { - cross_platform_config: CrossPlatformConfig

, - platform_config: Option<>::Config>, +pub struct LaunchBuilder { + cross_platform_config: fn() -> Element, + #[cfg(feature = "fullstack")] + contexts: Vec Box + Send>>, + #[cfg(not(feature = "fullstack"))] + contexts: Vec Box>>, + platform_config: Option, } // Fullstack platform builder -impl_launch_builder! { +impl LaunchBuilder { /// Create a new builder for your application. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate. - pub fn new(component: F) -> Self - where - Props: Default, - { + pub fn new(component: fn() -> Element) -> Self { Self { - cross_platform_config: CrossPlatformConfig::new(VProps::new( - component, - |_, _| true, - Default::default(), - "root", - )), + cross_platform_config: component, + contexts: Vec::new(), platform_config: None, } } - /// Create a new builder for your application with some root props. This will create a launch configuration for the current platform based on the features enabled on the `dioxus` crate. - pub fn new_with_props(component: F, props: Props) -> Self { - Self { - cross_platform_config: CrossPlatformConfig::new(VProps::new( - component, - |_, _| true, - props, - "root", - )), - platform_config: None, - } + #[cfg(feature = "fullstack")] + /// Inject state into the root component's context. + pub fn context(mut self, state: impl Any + Clone + Send + 'static) -> Self { + self.contexts + .push(Box::new(move || Box::new(state.clone()))); + self } -} -impl> LaunchBuilder { - // /// Inject state into the root component's context. - // pub fn context(mut self, state: impl Any + Clone + 'static) -> Self { - // self.cross_platform_config - // .push_context(BoxedContext::new(state)); - // self - // } + #[cfg(not(feature = "fullstack"))] + /// Inject state into the root component's context. + pub fn context(mut self, state: impl Any + Clone + 'static) -> Self { + self.contexts + .push(Box::new(move || Box::new(state.clone()))); + self + } /// Provide a platform-specific config to the builder. - pub fn cfg( - mut self, - config: impl Into>::Config>>, - ) -> Self { + pub fn cfg(mut self, config: impl Into>) -> Self { if let Some(config) = config.into() { self.platform_config = Some(config); } @@ -91,99 +54,87 @@ impl> LaunchBuilder { #[allow(clippy::unit_arg)] /// Launch the app. pub fn launch(self) { - Platform::launch( + current_platform::launch( self.cross_platform_config, + Default::default(), self.platform_config.unwrap_or_default(), ); } } #[cfg(feature = "web")] -impl LaunchBuilder { +impl LaunchBuilder { /// Launch your web application. pub fn launch_web(self) { - dioxus_web::WebPlatform::launch( + dioxus_web::launch::launch( self.cross_platform_config, - self.platform_config.unwrap_or_default(), + Default::default(), + Default::default(), ); } } #[cfg(feature = "desktop")] -impl LaunchBuilder { +impl LaunchBuilder { /// Launch your desktop application. pub fn launch_desktop(self) { - dioxus_desktop::DesktopPlatform::launch( + dioxus_desktop::launch::launch( self.cross_platform_config, - self.platform_config.unwrap_or_default(), + Default::default(), + Default::default(), ); } } #[cfg(feature = "fullstack")] -impl LaunchBuilder { +impl LaunchBuilder { /// Launch your fullstack application. pub fn launch_fullstack(self) { - dioxus_fullstack::FullstackPlatform::launch( + dioxus_fullstack::launch::launch( self.cross_platform_config, - self.platform_config.unwrap_or_default(), + Default::default(), + Default::default(), ); } } -#[cfg(feature = "fullstack")] -type CurrentPlatform = dioxus_fullstack::FullstackPlatform; -#[cfg(all(feature = "desktop", not(feature = "fullstack")))] -type CurrentPlatform = dioxus_desktop::DesktopPlatform; -#[cfg(all(feature = "web", not(any(feature = "desktop", feature = "fullstack"))))] -type CurrentPlatform = dioxus_web::WebPlatform; -#[cfg(not(any(feature = "desktop", feature = "web", feature = "fullstack")))] -type CurrentPlatform = (); - -#[cfg(feature = "fullstack")] -/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options. -pub fn launch(component: impl ComponentFunction + Send + Sync) -where - Props: Default + Send + Sync + Clone + 'static, - Marker: Send + Sync + 'static, -{ - LaunchBuilder::new(component).launch() +mod current_platform { + #[cfg(all(feature = "desktop", not(feature = "fullstack")))] + pub use dioxus_desktop::launch::*; + #[cfg(feature = "fullstack")] + pub use dioxus_fullstack::launch::*; + #[cfg(all(feature = "web", not(any(feature = "desktop", feature = "fullstack"))))] + pub use dioxus_web::launch::*; + #[cfg(not(any(feature = "desktop", feature = "web", feature = "fullstack")))] + type Config = (); + #[cfg(not(any(feature = "desktop", feature = "web", feature = "fullstack")))] + pub fn launch( + root: fn() -> Element, + contexts: Vec>, + platform_config: Config, + ) { + } } -#[cfg(not(feature = "fullstack"))] /// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options. -pub fn launch(component: impl ComponentFunction) -where - Props: Default + Clone + 'static, -{ +pub fn launch(component: fn() -> Element) { LaunchBuilder::new(component).launch() } #[cfg(all(feature = "web", not(feature = "fullstack")))] /// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options. -pub fn launch_web(component: impl ComponentFunction) -where - Props: Default + Clone + 'static, -{ +pub fn launch_web(component: fn() -> Element) { LaunchBuilder::new(component).launch_web() } #[cfg(all(feature = "desktop", not(feature = "fullstack")))] /// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options. -pub fn launch_desktop(component: impl ComponentFunction) -where - Props: Default + Clone + 'static, -{ +pub fn launch_desktop(component: fn() -> Element) { LaunchBuilder::new(component).launch_desktop() } #[cfg(feature = "fullstack")] /// Launch your fullstack application without any additional configuration. See [`LaunchBuilder`] for more options. -pub fn launch_fullstack( - component: impl ComponentFunction + Send + Sync, -) where - Props: Default + Send + Sync + Clone + 'static, - Marker: Send + Sync + 'static, -{ +pub fn launch_fullstack(component: fn() -> Element) { LaunchBuilder::new(component).launch_fullstack() } diff --git a/packages/fullstack/src/launch.rs b/packages/fullstack/src/launch.rs index af98b7558..1ca304a91 100644 --- a/packages/fullstack/src/launch.rs +++ b/packages/fullstack/src/launch.rs @@ -6,15 +6,16 @@ use dioxus_lib::prelude::{ *, }; -/// The desktop renderer platform -pub struct FullstackPlatform; +pub mod launch { + use dioxus_lib::prelude::{dioxus_core::BoxedContext, Element, VirtualDom}; -impl dioxus_core::PlatformBuilder - for FullstackPlatform -{ - type Config = Config; + pub type Config = crate::Config; - fn launch(config: dioxus_core::CrossPlatformConfig, platform_config: Self::Config) { + pub fn launch( + root: fn() -> Element, + contexts: Vec Box + Send>>, + platform_config: Config, + ) { #[cfg(feature = "ssr")] tokio::runtime::Runtime::new() .unwrap() @@ -24,9 +25,9 @@ impl dioxus_core::PlatformBuild #[cfg(not(feature = "ssr"))] { #[cfg(feature = "web")] - platform_config.launch_web(config); + platform_config.launch_web(dom); #[cfg(feature = "desktop")] - platform_config.launch_desktop(config); + platform_config.launch_desktop(dom); } } } diff --git a/packages/ssr/src/incremental.rs b/packages/ssr/src/incremental.rs index 0d1ebf2e9..72077eeb0 100644 --- a/packages/ssr/src/incremental.rs +++ b/packages/ssr/src/incremental.rs @@ -3,7 +3,7 @@ #![allow(non_snake_case)] use crate::fs_cache::ValidCachedPath; -use dioxus_core::{AnyProps, CrossPlatformConfig, VirtualDom}; +use dioxus_core::VirtualDom; use rustc_hash::FxHasher; use std::{ future::Future, @@ -69,22 +69,22 @@ impl IncrementalRenderer { self.invalidate_after.is_some() } - async fn render_and_cache<'a, P: AnyProps + 'static, R: WrapBody + Send + Sync>( + async fn render_and_cache<'a, R: WrapBody + Send + Sync>( &'a mut self, route: String, - dioxus_config: CrossPlatformConfig

, + mut virtual_dom: VirtualDom, output: &'a mut (impl AsyncWrite + Unpin + Send), rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin + '_>>, renderer: &'a R, ) -> Result { let mut html_buffer = WriteBuffer { buffer: Vec::new() }; { - let mut vdom = dioxus_config.build_vdom(); - vdom.in_runtime(crate::eval::init_eval); - rebuild_with(&mut vdom).await; + virtual_dom.in_runtime(crate::eval::init_eval); + rebuild_with(&mut virtual_dom).await; renderer.render_before_body(&mut *html_buffer)?; - self.ssr_renderer.render_to(&mut html_buffer, &vdom)?; + self.ssr_renderer + .render_to(&mut html_buffer, &virtual_dom)?; } renderer.render_after_body(&mut *html_buffer)?; let html_buffer = html_buffer.buffer; @@ -167,10 +167,10 @@ impl IncrementalRenderer { } /// Render a route or get it from cache. - pub async fn render( + pub async fn render( &mut self, route: String, - dioxus_config: CrossPlatformConfig

, + virtual_dom: VirtualDom, output: &mut (impl AsyncWrite + Unpin + std::marker::Send), rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin + '_>>, renderer: &R, @@ -181,7 +181,7 @@ impl IncrementalRenderer { } else { // if not, create it let freshness = self - .render_and_cache(route, dioxus_config, output, rebuild_with, renderer) + .render_and_cache(route, virtual_dom, output, rebuild_with, renderer) .await?; tracing::trace!("cache miss"); Ok(freshness) diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 9b52e9a95..ddfbb90d7 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -60,7 +60,7 @@ use std::rc::Rc; pub use crate::cfg::Config; #[cfg(feature = "file_engine")] pub use crate::file_engine::WebFileEngineExt; -use dioxus_core::{AnyProps, CrossPlatformConfig}; +use dioxus_core::VirtualDom; use futures_util::{ future::{select, Either}, pin_mut, FutureExt, StreamExt, @@ -99,13 +99,10 @@ mod rehydrate; /// wasm_bindgen_futures::spawn_local(app_fut); /// } /// ``` -pub async fn run_with_props( - dioxus_config: CrossPlatformConfig

, - web_config: Config, -) { +pub async fn run(virtual_dom: VirtualDom, web_config: Config) { tracing::info!("Starting up"); - let mut dom = dioxus_config.build_vdom(); + let mut dom = virtual_dom; #[cfg(feature = "eval")] { diff --git a/packages/web/src/platform.rs b/packages/web/src/platform.rs index c17679399..274946bb3 100644 --- a/packages/web/src/platform.rs +++ b/packages/web/src/platform.rs @@ -1,16 +1,21 @@ -use dioxus_core::*; +pub mod launch { + use std::any::Any; -use crate::Config; + use dioxus_core::prelude::*; -/// The web renderer platform -pub struct WebPlatform; + pub type Config = crate::Config; -impl PlatformBuilder

for WebPlatform { - type Config = Config; - - fn launch(config: CrossPlatformConfig

, platform_config: Self::Config) { + pub fn launch( + root: fn() -> Element, + contexts: Vec Box + Send>>, + platform_config: Config, + ) { wasm_bindgen_futures::spawn_local(async move { - crate::run_with_props(config, platform_config).await; + let mut vdom = VirtualDom::new(root); + for context in contexts { + vdom.insert_any_root_context(context()); + } + crate::run(vdom, platform_config).await; }); } }