remove some generics from LaunchBuilder
This commit is contained in:
1 parent
16e2c3f2f2
commit
25ad3da659
14 files changed
+142
-304
No files matched your search
@@ -13,7 +13,6 @@ mod fragment;
|
|||||||
mod global_context;
|
mod global_context;
|
||||||
mod mutations;
|
mod mutations;
|
||||||
mod nodes;
|
mod nodes;
|
||||||
mod platform;
|
|
||||||
mod properties;
|
mod properties;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod scope_arena;
|
mod scope_arena;
|
||||||
@@ -32,7 +31,6 @@ pub(crate) mod innerlude {
|
|||||||
pub use crate::global_context::*;
|
pub use crate::global_context::*;
|
||||||
pub use crate::mutations::*;
|
pub use crate::mutations::*;
|
||||||
pub use crate::nodes::*;
|
pub use crate::nodes::*;
|
||||||
pub use crate::platform::*;
|
|
||||||
pub use crate::properties::*;
|
pub use crate::properties::*;
|
||||||
pub use crate::runtime::{Runtime, RuntimeGuard};
|
pub use crate::runtime::{Runtime, RuntimeGuard};
|
||||||
pub use crate::scopes::*;
|
pub use crate::scopes::*;
|
||||||
@@ -76,11 +74,11 @@ pub(crate) mod innerlude {
|
|||||||
|
|
||||||
pub use crate::innerlude::{
|
pub use crate::innerlude::{
|
||||||
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
||||||
AnyProps, AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component,
|
AnyProps, AnyValue, Attribute, AttributeValue, CapturedError, Component, ComponentFunction,
|
||||||
ComponentFunction, CrossPlatformConfig, DynamicNode, Element, ElementId, Event, Fragment,
|
DynamicNode, Element, ElementId, Event, Fragment, HasAttributes, IntoDynNode, Mutation,
|
||||||
HasAttributes, IntoDynNode, Mutation, Mutations, NoOpMutations, PlatformBuilder, Properties,
|
Mutations, NoOpMutations, Properties, RenderReturn, Runtime, ScopeId, ScopeState, Task,
|
||||||
RenderReturn, Runtime, ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode,
|
Template, TemplateAttribute, TemplateNode, VComponent, VNode, VNodeInner, VPlaceholder, VProps,
|
||||||
VComponent, VNode, VNodeInner, VPlaceholder, VProps, VText, VirtualDom, WriteMutations,
|
VText, VirtualDom, WriteMutations,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The purpose of this module is to alleviate imports of many common types
|
/// 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},
|
nodes::{Template, TemplateId},
|
||||||
runtime::{Runtime, RuntimeGuard},
|
runtime::{Runtime, RuntimeGuard},
|
||||||
scopes::ScopeId,
|
scopes::ScopeId,
|
||||||
AttributeValue, BoxedContext, ComponentFunction, Element, Event, Mutations, Task, VProps,
|
AttributeValue, ComponentFunction, Element, Event, Mutations, Task, VProps,
|
||||||
};
|
};
|
||||||
use futures_util::{pin_mut, StreamExt};
|
use futures_util::{pin_mut, StreamExt};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
@@ -361,10 +361,8 @@ impl VirtualDom {
|
|||||||
/// Build the virtualdom with a global context inserted into the base scope
|
/// 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
|
/// 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) {
|
pub fn insert_any_root_context(&mut self, context: Box<dyn Any>) {
|
||||||
self.base_scope()
|
self.base_scope().context().provide_any_context(context);
|
||||||
.context()
|
|
||||||
.provide_any_context(context.into_inner());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Manually mark a scope as requiring a re-render
|
/// Manually mark a scope as requiring a re-render
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use crate::{
|
|||||||
webview::WebviewInstance,
|
webview::WebviewInstance,
|
||||||
};
|
};
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use dioxus_core::AnyProps;
|
use dioxus_core::ElementId;
|
||||||
use dioxus_core::{CrossPlatformConfig, ElementId};
|
use dioxus_core::VirtualDom;
|
||||||
use dioxus_html::{
|
use dioxus_html::{
|
||||||
native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData, HtmlEvent,
|
native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData, HtmlEvent,
|
||||||
PlatformEventData,
|
PlatformEventData,
|
||||||
@@ -29,10 +29,10 @@ use tao::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The single top-level object that manages all the running windows, assets, shortcuts, etc
|
/// 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
|
// 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
|
// 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>>,
|
pub(crate) cfg: Cell<Option<Config>>,
|
||||||
|
|
||||||
// Stuff we need mutable access to
|
// Stuff we need mutable access to
|
||||||
@@ -59,11 +59,8 @@ pub struct SharedContext {
|
|||||||
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: AnyProps> App<P> {
|
impl App {
|
||||||
pub fn new(
|
pub fn new(cfg: Config, virtual_dom: VirtualDom) -> (EventLoop<UserWindowEvent>, Self) {
|
||||||
cfg: Config,
|
|
||||||
dioxus_config: CrossPlatformConfig<P>,
|
|
||||||
) -> (EventLoop<UserWindowEvent>, Self) {
|
|
||||||
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
||||||
|
|
||||||
let app = Self {
|
let app = Self {
|
||||||
@@ -71,7 +68,7 @@ impl<P: AnyProps> App<P> {
|
|||||||
is_visible_before_start: true,
|
is_visible_before_start: true,
|
||||||
webviews: HashMap::new(),
|
webviews: HashMap::new(),
|
||||||
control_flow: ControlFlow::Wait,
|
control_flow: ControlFlow::Wait,
|
||||||
dioxus_config: Cell::new(Some(dioxus_config)),
|
unmounted_dom: Cell::new(Some(virtual_dom)),
|
||||||
cfg: Cell::new(Some(cfg)),
|
cfg: Cell::new(Some(cfg)),
|
||||||
shared: Rc::new(SharedContext {
|
shared: Rc::new(SharedContext {
|
||||||
event_handlers: WindowEventHandlers::default(),
|
event_handlers: WindowEventHandlers::default(),
|
||||||
@@ -166,12 +163,12 @@ impl<P: AnyProps> App<P> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_start_cause_init(&mut self) {
|
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();
|
let cfg = self.cfg.take().unwrap();
|
||||||
|
|
||||||
self.is_visible_before_start = cfg.window.window.visible;
|
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();
|
let id = webview.desktop_context.window.id();
|
||||||
self.webviews.insert(id, webview);
|
self.webviews.insert(id, webview);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use dioxus_core::prelude::{Component, Element};
|
|
||||||
use tao::window::{Icon, WindowBuilder, WindowId};
|
use tao::window::{Icon, WindowBuilder, WindowId};
|
||||||
use wry::{
|
use wry::{
|
||||||
http::{Request as HttpRequest, Response as HttpResponse},
|
http::{Request as HttpRequest, Response as HttpResponse},
|
||||||
|
|||||||
@@ -12,11 +12,9 @@ use dioxus_core::{
|
|||||||
prelude::{current_scope_id, ScopeId},
|
prelude::{current_scope_id, ScopeId},
|
||||||
use_hook, VirtualDom,
|
use_hook, VirtualDom,
|
||||||
};
|
};
|
||||||
use dioxus_interpreter_js::binary_protocol::Channel;
|
|
||||||
use dioxus_interpreter_js::MutationState;
|
use dioxus_interpreter_js::MutationState;
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use slab::Slab;
|
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::{
|
use tao::{
|
||||||
event::Event,
|
event::Event,
|
||||||
event_loop::EventLoopWindowTarget,
|
event_loop::EventLoopWindowTarget,
|
||||||
|
|||||||
@@ -1,15 +1,6 @@
|
|||||||
use dioxus_core::{AttributeValue, Template, TemplateAttribute, TemplateNode};
|
use std::{sync::Arc, sync::Mutex};
|
||||||
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::fmt::{Debug, Formatter};
|
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.
|
/// 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.
|
/// 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::{
|
use crate::{
|
||||||
app::App,
|
app::App,
|
||||||
ipc::{EventData, IpcMethod, UserWindowEvent},
|
ipc::{EventData, IpcMethod, UserWindowEvent},
|
||||||
Config,
|
|
||||||
};
|
};
|
||||||
use dioxus_core::*;
|
use dioxus_core::*;
|
||||||
|
use std::any::Any;
|
||||||
use tao::event::{Event, StartCause, WindowEvent};
|
use tao::event::{Event, StartCause, WindowEvent};
|
||||||
|
|
||||||
/// Launch the WebView and run the event loop, with configuration and root props.
|
/// 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
|
/// 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.
|
/// and is equivalent to calling launch_with_props with the tokio feature disabled.
|
||||||
pub fn launch_with_props_blocking<P: AnyProps>(
|
pub fn launch_with_props_blocking(virtual_dom: VirtualDom, desktop_config: Config) {
|
||||||
dioxus_cfg: CrossPlatformConfig<P>,
|
let (event_loop, mut app) = App::new(desktop_config, virtual_dom);
|
||||||
desktop_config: Config,
|
|
||||||
) {
|
|
||||||
let (event_loop, mut app) = App::new(desktop_config, dioxus_cfg);
|
|
||||||
|
|
||||||
event_loop.run(move |window_event, _, control_flow| {
|
event_loop.run(move |window_event, _, control_flow| {
|
||||||
app.tick(&window_event);
|
app.tick(&window_event);
|
||||||
@@ -50,23 +48,27 @@ pub fn launch_with_props_blocking<P: AnyProps>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The desktop renderer platform
|
/// Launches the WebView and runs the event loop, with configuration and root props.
|
||||||
pub struct DesktopPlatform;
|
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 {
|
for context in contexts {
|
||||||
type Config = Config;
|
virtual_dom.insert_any_root_context(context());
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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"))]
|
#[cfg(any(target_os = "ios", target_os = "android"))]
|
||||||
mod mobile_shortcut;
|
mod mobile_shortcut;
|
||||||
|
|
||||||
// The main entrypoint for this crate
|
/// The main entrypoint for this crate
|
||||||
pub use launch::*;
|
pub mod launch;
|
||||||
mod launch;
|
|
||||||
|
|
||||||
// Reexport tao and wry, might want to re-export other important things
|
// Reexport tao and wry, might want to re-export other important things
|
||||||
pub use tao;
|
pub use tao;
|
||||||
|
|||||||
+59
-108
@@ -5,83 +5,46 @@ use std::any::Any;
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use dioxus_core::VProps;
|
use dioxus_core::VProps;
|
||||||
use dioxus_core::{prelude::*, AnyProps};
|
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.
|
/// A builder for a fullstack app.
|
||||||
pub struct LaunchBuilder<P: AnyProps, Platform: PlatformBuilder<P> = CurrentPlatform> {
|
pub struct LaunchBuilder {
|
||||||
cross_platform_config: CrossPlatformConfig<P>,
|
cross_platform_config: fn() -> Element,
|
||||||
platform_config: Option<<Platform as PlatformBuilder<P>>::Config>,
|
#[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
|
// 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.
|
/// 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
|
pub fn new(component: fn() -> Element) -> Self {
|
||||||
where
|
|
||||||
Props: Default,
|
|
||||||
{
|
|
||||||
Self {
|
Self {
|
||||||
cross_platform_config: CrossPlatformConfig::new(VProps::new(
|
cross_platform_config: component,
|
||||||
component,
|
contexts: Vec::new(),
|
||||||
|_, _| true,
|
|
||||||
Default::default(),
|
|
||||||
"root",
|
|
||||||
)),
|
|
||||||
platform_config: None,
|
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.
|
#[cfg(feature = "fullstack")]
|
||||||
pub fn new_with_props(component: F, props: Props) -> Self {
|
/// Inject state into the root component's context.
|
||||||
Self {
|
pub fn context(mut self, state: impl Any + Clone + Send + 'static) -> Self {
|
||||||
cross_platform_config: CrossPlatformConfig::new(VProps::new(
|
self.contexts
|
||||||
component,
|
.push(Box::new(move || Box::new(state.clone())));
|
||||||
|_, _| true,
|
self
|
||||||
props,
|
|
||||||
"root",
|
|
||||||
)),
|
|
||||||
platform_config: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<P: AnyProps, Platform: PlatformBuilder<P>> LaunchBuilder<P, Platform> {
|
#[cfg(not(feature = "fullstack"))]
|
||||||
// /// Inject state into the root component's context.
|
/// Inject state into the root component's context.
|
||||||
// pub fn context(mut self, state: impl Any + Clone + 'static) -> Self {
|
pub fn context(mut self, state: impl Any + Clone + 'static) -> Self {
|
||||||
// self.cross_platform_config
|
self.contexts
|
||||||
// .push_context(BoxedContext::new(state));
|
.push(Box::new(move || Box::new(state.clone())));
|
||||||
// self
|
self
|
||||||
// }
|
}
|
||||||
|
|
||||||
/// Provide a platform-specific config to the builder.
|
/// Provide a platform-specific config to the builder.
|
||||||
pub fn cfg(
|
pub fn cfg(mut self, config: impl Into<Option<current_platform::Config>>) -> Self {
|
||||||
mut self,
|
|
||||||
config: impl Into<Option<<Platform as PlatformBuilder<P>>::Config>>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(config) = config.into() {
|
if let Some(config) = config.into() {
|
||||||
self.platform_config = Some(config);
|
self.platform_config = Some(config);
|
||||||
}
|
}
|
||||||
@@ -91,99 +54,87 @@ impl<P: AnyProps, Platform: PlatformBuilder<P>> LaunchBuilder<P, Platform> {
|
|||||||
#[allow(clippy::unit_arg)]
|
#[allow(clippy::unit_arg)]
|
||||||
/// Launch the app.
|
/// Launch the app.
|
||||||
pub fn launch(self) {
|
pub fn launch(self) {
|
||||||
Platform::launch(
|
current_platform::launch(
|
||||||
self.cross_platform_config,
|
self.cross_platform_config,
|
||||||
|
Default::default(),
|
||||||
self.platform_config.unwrap_or_default(),
|
self.platform_config.unwrap_or_default(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "web")]
|
#[cfg(feature = "web")]
|
||||||
impl<P: AnyProps> LaunchBuilder<P, dioxus_web::WebPlatform> {
|
impl LaunchBuilder {
|
||||||
/// Launch your web application.
|
/// Launch your web application.
|
||||||
pub fn launch_web(self) {
|
pub fn launch_web(self) {
|
||||||
dioxus_web::WebPlatform::launch(
|
dioxus_web::launch::launch(
|
||||||
self.cross_platform_config,
|
self.cross_platform_config,
|
||||||
self.platform_config.unwrap_or_default(),
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
impl<P: AnyProps> LaunchBuilder<P, dioxus_desktop::DesktopPlatform> {
|
impl LaunchBuilder {
|
||||||
/// Launch your desktop application.
|
/// Launch your desktop application.
|
||||||
pub fn launch_desktop(self) {
|
pub fn launch_desktop(self) {
|
||||||
dioxus_desktop::DesktopPlatform::launch(
|
dioxus_desktop::launch::launch(
|
||||||
self.cross_platform_config,
|
self.cross_platform_config,
|
||||||
self.platform_config.unwrap_or_default(),
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "fullstack")]
|
#[cfg(feature = "fullstack")]
|
||||||
impl<P: AnyProps + Clone + Send + Sync> LaunchBuilder<P, dioxus_fullstack::FullstackPlatform> {
|
impl LaunchBuilder {
|
||||||
/// Launch your fullstack application.
|
/// Launch your fullstack application.
|
||||||
pub fn launch_fullstack(self) {
|
pub fn launch_fullstack(self) {
|
||||||
dioxus_fullstack::FullstackPlatform::launch(
|
dioxus_fullstack::launch::launch(
|
||||||
self.cross_platform_config,
|
self.cross_platform_config,
|
||||||
self.platform_config.unwrap_or_default(),
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "fullstack")]
|
mod current_platform {
|
||||||
type CurrentPlatform = dioxus_fullstack::FullstackPlatform;
|
#[cfg(all(feature = "desktop", not(feature = "fullstack")))]
|
||||||
#[cfg(all(feature = "desktop", not(feature = "fullstack")))]
|
pub use dioxus_desktop::launch::*;
|
||||||
type CurrentPlatform = dioxus_desktop::DesktopPlatform;
|
#[cfg(feature = "fullstack")]
|
||||||
#[cfg(all(feature = "web", not(any(feature = "desktop", feature = "fullstack"))))]
|
pub use dioxus_fullstack::launch::*;
|
||||||
type CurrentPlatform = dioxus_web::WebPlatform;
|
#[cfg(all(feature = "web", not(any(feature = "desktop", feature = "fullstack"))))]
|
||||||
#[cfg(not(any(feature = "desktop", feature = "web", feature = "fullstack")))]
|
pub use dioxus_web::launch::*;
|
||||||
type CurrentPlatform = ();
|
#[cfg(not(any(feature = "desktop", feature = "web", feature = "fullstack")))]
|
||||||
|
type Config = ();
|
||||||
#[cfg(feature = "fullstack")]
|
#[cfg(not(any(feature = "desktop", feature = "web", feature = "fullstack")))]
|
||||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
pub fn launch(
|
||||||
pub fn launch<Props, Marker>(component: impl ComponentFunction<Props, Marker> + Send + Sync)
|
root: fn() -> Element,
|
||||||
where
|
contexts: Vec<Box<dyn CloneAny + Send + Sync>>,
|
||||||
Props: Default + Send + Sync + Clone + 'static,
|
platform_config: Config,
|
||||||
Marker: Send + Sync + 'static,
|
) {
|
||||||
{
|
}
|
||||||
LaunchBuilder::new(component).launch()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "fullstack"))]
|
|
||||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||||
pub fn launch<Props, Marker: 'static>(component: impl ComponentFunction<Props, Marker>)
|
pub fn launch(component: fn() -> Element) {
|
||||||
where
|
|
||||||
Props: Default + Clone + 'static,
|
|
||||||
{
|
|
||||||
LaunchBuilder::new(component).launch()
|
LaunchBuilder::new(component).launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "web", not(feature = "fullstack")))]
|
#[cfg(all(feature = "web", not(feature = "fullstack")))]
|
||||||
/// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
|
/// 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>)
|
pub fn launch_web(component: fn() -> Element) {
|
||||||
where
|
|
||||||
Props: Default + Clone + 'static,
|
|
||||||
{
|
|
||||||
LaunchBuilder::new(component).launch_web()
|
LaunchBuilder::new(component).launch_web()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "desktop", not(feature = "fullstack")))]
|
#[cfg(all(feature = "desktop", not(feature = "fullstack")))]
|
||||||
/// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
|
/// 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>)
|
pub fn launch_desktop(component: fn() -> Element) {
|
||||||
where
|
|
||||||
Props: Default + Clone + 'static,
|
|
||||||
{
|
|
||||||
LaunchBuilder::new(component).launch_desktop()
|
LaunchBuilder::new(component).launch_desktop()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "fullstack")]
|
#[cfg(feature = "fullstack")]
|
||||||
/// Launch your fullstack application without any additional configuration. See [`LaunchBuilder`] for more options.
|
/// Launch your fullstack application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||||
pub fn launch_fullstack<Props, Marker>(
|
pub fn launch_fullstack(component: fn() -> Element) {
|
||||||
component: impl ComponentFunction<Props, Marker> + Send + Sync,
|
|
||||||
) where
|
|
||||||
Props: Default + Send + Sync + Clone + 'static,
|
|
||||||
Marker: Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
LaunchBuilder::new(component).launch_fullstack()
|
LaunchBuilder::new(component).launch_fullstack()
|
||||||
}
|
}
|
||||||
@@ -6,15 +6,16 @@ use dioxus_lib::prelude::{
|
|||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The desktop renderer platform
|
pub mod launch {
|
||||||
pub struct FullstackPlatform;
|
use dioxus_lib::prelude::{dioxus_core::BoxedContext, Element, VirtualDom};
|
||||||
|
|
||||||
impl<Props: AnyProps + Clone + Send + Sync + 'static> dioxus_core::PlatformBuilder<Props>
|
pub type Config = crate::Config;
|
||||||
for FullstackPlatform
|
|
||||||
{
|
|
||||||
type Config = 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")]
|
#[cfg(feature = "ssr")]
|
||||||
tokio::runtime::Runtime::new()
|
tokio::runtime::Runtime::new()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -24,9 +25,9 @@ impl<Props: AnyProps + Clone + Send + Sync + 'static> dioxus_core::PlatformBuild
|
|||||||
#[cfg(not(feature = "ssr"))]
|
#[cfg(not(feature = "ssr"))]
|
||||||
{
|
{
|
||||||
#[cfg(feature = "web")]
|
#[cfg(feature = "web")]
|
||||||
platform_config.launch_web(config);
|
platform_config.launch_web(dom);
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
platform_config.launch_desktop(config);
|
platform_config.launch_desktop(dom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use crate::fs_cache::ValidCachedPath;
|
use crate::fs_cache::ValidCachedPath;
|
||||||
use dioxus_core::{AnyProps, CrossPlatformConfig, VirtualDom};
|
use dioxus_core::VirtualDom;
|
||||||
use rustc_hash::FxHasher;
|
use rustc_hash::FxHasher;
|
||||||
use std::{
|
use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
@@ -69,22 +69,22 @@ impl IncrementalRenderer {
|
|||||||
self.invalidate_after.is_some()
|
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,
|
&'a mut self,
|
||||||
route: String,
|
route: String,
|
||||||
dioxus_config: CrossPlatformConfig<P>,
|
mut virtual_dom: VirtualDom,
|
||||||
output: &'a mut (impl AsyncWrite + Unpin + Send),
|
output: &'a mut (impl AsyncWrite + Unpin + Send),
|
||||||
rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
|
rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
|
||||||
renderer: &'a R,
|
renderer: &'a R,
|
||||||
) -> Result<RenderFreshness, IncrementalRendererError> {
|
) -> Result<RenderFreshness, IncrementalRendererError> {
|
||||||
let mut html_buffer = WriteBuffer { buffer: Vec::new() };
|
let mut html_buffer = WriteBuffer { buffer: Vec::new() };
|
||||||
{
|
{
|
||||||
let mut vdom = dioxus_config.build_vdom();
|
virtual_dom.in_runtime(crate::eval::init_eval);
|
||||||
vdom.in_runtime(crate::eval::init_eval);
|
rebuild_with(&mut virtual_dom).await;
|
||||||
rebuild_with(&mut vdom).await;
|
|
||||||
|
|
||||||
renderer.render_before_body(&mut *html_buffer)?;
|
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)?;
|
renderer.render_after_body(&mut *html_buffer)?;
|
||||||
let html_buffer = html_buffer.buffer;
|
let html_buffer = html_buffer.buffer;
|
||||||
@@ -167,10 +167,10 @@ impl IncrementalRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Render a route or get it from cache.
|
/// 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,
|
&mut self,
|
||||||
route: String,
|
route: String,
|
||||||
dioxus_config: CrossPlatformConfig<P>,
|
virtual_dom: VirtualDom,
|
||||||
output: &mut (impl AsyncWrite + Unpin + std::marker::Send),
|
output: &mut (impl AsyncWrite + Unpin + std::marker::Send),
|
||||||
rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
|
rebuild_with: impl FnOnce(&mut VirtualDom) -> Pin<Box<dyn Future<Output = ()> + '_>>,
|
||||||
renderer: &R,
|
renderer: &R,
|
||||||
@@ -181,7 +181,7 @@ impl IncrementalRenderer {
|
|||||||
} else {
|
} else {
|
||||||
// if not, create it
|
// if not, create it
|
||||||
let freshness = self
|
let freshness = self
|
||||||
.render_and_cache(route, dioxus_config, output, rebuild_with, renderer)
|
.render_and_cache(route, virtual_dom, output, rebuild_with, renderer)
|
||||||
.await?;
|
.await?;
|
||||||
tracing::trace!("cache miss");
|
tracing::trace!("cache miss");
|
||||||
Ok(freshness)
|
Ok(freshness)
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ use std::rc::Rc;
|
|||||||
pub use crate::cfg::Config;
|
pub use crate::cfg::Config;
|
||||||
#[cfg(feature = "file_engine")]
|
#[cfg(feature = "file_engine")]
|
||||||
pub use crate::file_engine::WebFileEngineExt;
|
pub use crate::file_engine::WebFileEngineExt;
|
||||||
use dioxus_core::{AnyProps, CrossPlatformConfig};
|
use dioxus_core::VirtualDom;
|
||||||
use futures_util::{
|
use futures_util::{
|
||||||
future::{select, Either},
|
future::{select, Either},
|
||||||
pin_mut, FutureExt, StreamExt,
|
pin_mut, FutureExt, StreamExt,
|
||||||
@@ -99,13 +99,10 @@ mod rehydrate;
|
|||||||
/// wasm_bindgen_futures::spawn_local(app_fut);
|
/// wasm_bindgen_futures::spawn_local(app_fut);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn run_with_props<P: AnyProps>(
|
pub async fn run(virtual_dom: VirtualDom, web_config: Config) {
|
||||||
dioxus_config: CrossPlatformConfig<P>,
|
|
||||||
web_config: Config,
|
|
||||||
) {
|
|
||||||
tracing::info!("Starting up");
|
tracing::info!("Starting up");
|
||||||
|
|
||||||
let mut dom = dioxus_config.build_vdom();
|
let mut dom = virtual_dom;
|
||||||
|
|
||||||
#[cfg(feature = "eval")]
|
#[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 type Config = crate::Config;
|
||||||
pub struct WebPlatform;
|
|
||||||
|
|
||||||
impl<P: AnyProps> PlatformBuilder<P> for WebPlatform {
|
pub fn launch(
|
||||||
type Config = Config;
|
root: fn() -> Element,
|
||||||
|
contexts: Vec<Box<dyn Fn() -> Box<dyn Any> + Send>>,
|
||||||
fn launch(config: CrossPlatformConfig<P>, platform_config: Self::Config) {
|
platform_config: Config,
|
||||||
|
) {
|
||||||
wasm_bindgen_futures::spawn_local(async move {
|
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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user