mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-26 14:10:20 +00:00
remove some generics from LaunchBuilder
This commit is contained in:
parent
16e2c3f2f2
commit
25ad3da659
14 changed files with 142 additions and 304 deletions
|
@ -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
|
||||
|
|
|
@ -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<dyn ClonableAny>);
|
||||
|
||||
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<dyn Any> {
|
||||
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<dyn ClonableAny>;
|
||||
|
||||
fn into_inner(self: Box<Self>) -> Box<dyn Any>;
|
||||
}
|
||||
|
||||
impl<T: Any + Clone> ClonableAny for T {
|
||||
fn clone_box(&self) -> Box<dyn ClonableAny> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn into_inner(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The platform-independent part of the config needed to launch an application.
|
||||
#[derive(Clone)]
|
||||
pub struct CrossPlatformConfig<P: AnyProps> {
|
||||
/// The root component function.
|
||||
props: P,
|
||||
// /// The contexts to provide to the root component.
|
||||
// root_contexts: Vec<BoxedContext>,
|
||||
}
|
||||
|
||||
impl<P: AnyProps> CrossPlatformConfig<P> {}
|
||||
|
||||
impl<P: AnyProps> CrossPlatformConfig<P> {
|
||||
/// 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<T: Any + Clone + 'static>(&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<P: AnyProps> {
|
||||
/// The platform-specific config needed to launch an application.
|
||||
type Config: Default;
|
||||
|
||||
/// Launch the app.
|
||||
fn launch(config: CrossPlatformConfig<P>, platform_config: Self::Config);
|
||||
}
|
||||
|
||||
impl<P: AnyProps> PlatformBuilder<P> for () {
|
||||
type Config = ();
|
||||
|
||||
fn launch(_: CrossPlatformConfig<P>, _: Self::Config) {
|
||||
panic!("No platform is currently enabled. Please enable a platform feature for the dioxus crate.");
|
||||
}
|
||||
}
|
|
@ -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<dyn Any>) {
|
||||
self.base_scope().context().provide_any_context(context);
|
||||
}
|
||||
|
||||
/// Manually mark a scope as requiring a re-render
|
||||
|
|
|
@ -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<P: AnyProps> {
|
||||
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<Option<CrossPlatformConfig<P>>>,
|
||||
pub(crate) unmounted_dom: Cell<Option<VirtualDom>>,
|
||||
pub(crate) cfg: Cell<Option<Config>>,
|
||||
|
||||
// Stuff we need mutable access to
|
||||
|
@ -59,11 +59,8 @@ pub struct SharedContext {
|
|||
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
||||
}
|
||||
|
||||
impl<P: AnyProps> App<P> {
|
||||
pub fn new(
|
||||
cfg: Config,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
) -> (EventLoop<UserWindowEvent>, Self) {
|
||||
impl App {
|
||||
pub fn new(cfg: Config, virtual_dom: VirtualDom) -> (EventLoop<UserWindowEvent>, Self) {
|
||||
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
||||
|
||||
let app = Self {
|
||||
|
@ -71,7 +68,7 @@ impl<P: AnyProps> App<P> {
|
|||
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<P: AnyProps> App<P> {
|
|||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<P: AnyProps>(
|
||||
dioxus_cfg: CrossPlatformConfig<P>,
|
||||
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<P: AnyProps>(
|
|||
})
|
||||
}
|
||||
|
||||
/// 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<dyn Fn() -> Box<dyn Any> + Send>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
let mut virtual_dom = VirtualDom::new(root);
|
||||
|
||||
impl<P: AnyProps> PlatformBuilder<P> for DesktopPlatform {
|
||||
type Config = Config;
|
||||
|
||||
fn launch(config: dioxus_core::CrossPlatformConfig<P>, 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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<F, Props: Clone + Send + Sync + 'static, M: Send + Sync + 'static>
|
||||
LaunchBuilder<VProps<F, Props, M>>
|
||||
where F: ComponentFunction<Props, M> + Send + Sync + 'static
|
||||
{
|
||||
$($inner)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "fullstack"))]
|
||||
macro_rules! impl_launch_builder {
|
||||
($($inner:item)*) => {
|
||||
impl<F, Props: Clone + 'static, M: 'static>
|
||||
LaunchBuilder<VProps<F, Props, M>>
|
||||
where F: ComponentFunction<Props, M> + 'static
|
||||
{
|
||||
$($inner)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A builder for a fullstack app.
|
||||
pub struct LaunchBuilder<P: AnyProps, Platform: PlatformBuilder<P> = CurrentPlatform> {
|
||||
cross_platform_config: CrossPlatformConfig<P>,
|
||||
platform_config: Option<<Platform as PlatformBuilder<P>>::Config>,
|
||||
pub struct LaunchBuilder {
|
||||
cross_platform_config: fn() -> Element,
|
||||
#[cfg(feature = "fullstack")]
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send>>,
|
||||
#[cfg(not(feature = "fullstack"))]
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any>>>,
|
||||
platform_config: Option<current_platform::Config>,
|
||||
}
|
||||
|
||||
// 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<P: AnyProps, Platform: PlatformBuilder<P>> LaunchBuilder<P, Platform> {
|
||||
// /// 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<Option<<Platform as PlatformBuilder<P>>::Config>>,
|
||||
) -> Self {
|
||||
pub fn cfg(mut self, config: impl Into<Option<current_platform::Config>>) -> Self {
|
||||
if let Some(config) = config.into() {
|
||||
self.platform_config = Some(config);
|
||||
}
|
||||
|
@ -91,99 +54,87 @@ impl<P: AnyProps, Platform: PlatformBuilder<P>> LaunchBuilder<P, Platform> {
|
|||
#[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<P: AnyProps> LaunchBuilder<P, dioxus_web::WebPlatform> {
|
||||
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<P: AnyProps> LaunchBuilder<P, dioxus_desktop::DesktopPlatform> {
|
||||
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<P: AnyProps + Clone + Send + Sync> LaunchBuilder<P, dioxus_fullstack::FullstackPlatform> {
|
||||
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<Props, Marker>(component: impl ComponentFunction<Props, Marker> + 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<Box<dyn CloneAny + Send + Sync>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "fullstack"))]
|
||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
|
||||
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<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
|
||||
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<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
|
||||
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<Props, Marker>(
|
||||
component: impl ComponentFunction<Props, Marker> + 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()
|
||||
}
|
||||
|
|
|
@ -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<Props: AnyProps + Clone + Send + Sync + 'static> dioxus_core::PlatformBuilder<Props>
|
||||
for FullstackPlatform
|
||||
{
|
||||
type Config = Config;
|
||||
pub type Config = crate::Config;
|
||||
|
||||
fn launch(config: dioxus_core::CrossPlatformConfig<Props>, platform_config: Self::Config) {
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send>>,
|
||||
platform_config: Config,
|
||||
) {
|
||||
#[cfg(feature = "ssr")]
|
||||
tokio::runtime::Runtime::new()
|
||||
.unwrap()
|
||||
|
@ -24,9 +25,9 @@ impl<Props: AnyProps + Clone + Send + Sync + 'static> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<P>,
|
||||
mut virtual_dom: VirtualDom,
|
||||
output: &'a mut (impl AsyncWrite + Unpin + Send),
|
||||
rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
|
||||
renderer: &'a R,
|
||||
) -> Result<RenderFreshness, IncrementalRendererError> {
|
||||
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<P: AnyProps, R: WrapBody + Send + Sync>(
|
||||
pub async fn render<R: WrapBody + Send + Sync>(
|
||||
&mut self,
|
||||
route: String,
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
virtual_dom: VirtualDom,
|
||||
output: &mut (impl AsyncWrite + Unpin + std::marker::Send),
|
||||
rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
|
||||
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)
|
||||
|
|
|
@ -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<P: AnyProps>(
|
||||
dioxus_config: CrossPlatformConfig<P>,
|
||||
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")]
|
||||
{
|
||||
|
|
|
@ -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<P: AnyProps> PlatformBuilder<P> for WebPlatform {
|
||||
type Config = Config;
|
||||
|
||||
fn launch(config: CrossPlatformConfig<P>, platform_config: Self::Config) {
|
||||
pub fn launch(
|
||||
root: fn() -> Element,
|
||||
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue