mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Remove phantom markers and just default to Rc<dyn Fn(props) -> Element> where it makes sense
This commit is contained in:
parent
397015df31
commit
c94af9538b
9 changed files with 108 additions and 234 deletions
|
@ -1,5 +1,5 @@
|
|||
use crate::{nodes::RenderReturn, properties::ComponentFunction};
|
||||
use std::{any::Any, marker::PhantomData, ops::Deref, panic::AssertUnwindSafe};
|
||||
use crate::{nodes::RenderReturn, Component};
|
||||
use std::{any::Any, ops::Deref, panic::AssertUnwindSafe};
|
||||
|
||||
/// A boxed version of AnyProps that can be cloned
|
||||
pub(crate) struct BoxedAnyProps {
|
||||
|
@ -38,17 +38,16 @@ pub(crate) trait AnyProps {
|
|||
fn duplicate(&self) -> Box<dyn AnyProps>;
|
||||
}
|
||||
|
||||
pub(crate) struct VProps<P: 'static, F: ComponentFunction<Phantom, Props = P>, Phantom: 'static> {
|
||||
pub render_fn: F,
|
||||
pub(crate) struct VProps<P: 'static> {
|
||||
pub render_fn: Component<P>,
|
||||
pub memo: fn(&P, &P) -> bool,
|
||||
pub props: P,
|
||||
pub name: &'static str,
|
||||
phantom: PhantomData<Phantom>,
|
||||
}
|
||||
|
||||
impl<P: 'static, F: ComponentFunction<Phantom, Props = P>, Phantom: 'static> VProps<P, F, Phantom> {
|
||||
impl<P: 'static> VProps<P> {
|
||||
pub(crate) fn new(
|
||||
render_fn: F,
|
||||
render_fn: Component<P>,
|
||||
memo: fn(&P, &P) -> bool,
|
||||
props: P,
|
||||
name: &'static str,
|
||||
|
@ -58,14 +57,11 @@ impl<P: 'static, F: ComponentFunction<Phantom, Props = P>, Phantom: 'static> VPr
|
|||
memo,
|
||||
props,
|
||||
name,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Clone + 'static, F: ComponentFunction<Phantom, Props = P>, Phantom> AnyProps
|
||||
for VProps<P, F, Phantom>
|
||||
{
|
||||
impl<P: Clone + 'static> AnyProps for VProps<P> {
|
||||
fn memoize(&self, other: &dyn Any) -> bool {
|
||||
match other.downcast_ref::<P>() {
|
||||
Some(other) => (self.memo)(&self.props, other),
|
||||
|
@ -80,7 +76,7 @@ impl<P: Clone + 'static, F: ComponentFunction<Phantom, Props = P>, Phantom> AnyP
|
|||
fn render(&self) -> RenderReturn {
|
||||
let res = std::panic::catch_unwind(AssertUnwindSafe(move || {
|
||||
// Call the render function directly
|
||||
self.render_fn.call(self.props.clone())
|
||||
(self.render_fn)(self.props.clone())
|
||||
}));
|
||||
|
||||
match res {
|
||||
|
@ -100,7 +96,6 @@ impl<P: Clone + 'static, F: ComponentFunction<Phantom, Props = P>, Phantom> AnyP
|
|||
memo: self.memo,
|
||||
props: self.props.clone(),
|
||||
name: self.name,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,12 +70,12 @@ pub(crate) mod innerlude {
|
|||
/// Example {}
|
||||
/// )
|
||||
/// ```
|
||||
pub type Component<P = ()> = fn(P) -> Element;
|
||||
pub type Component<P = ()> = std::rc::Rc<dyn Fn(P) -> Element>;
|
||||
}
|
||||
|
||||
pub use crate::innerlude::{
|
||||
fc_to_builder, generation, schedule_update, schedule_update_any, use_hook, vdom_is_rendering,
|
||||
AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component, ComponentFunction,
|
||||
AnyValue, Attribute, AttributeValue, BoxedContext, CapturedError, Component,
|
||||
CrossPlatformConfig, DynamicNode, Element, ElementId, Event, Fragment, HasAttributes,
|
||||
IntoDynNode, Mutation, Mutations, NoOpMutations, PlatformBuilder, Properties, RenderReturn,
|
||||
ScopeId, ScopeState, Task, Template, TemplateAttribute, TemplateNode, VComponent, VNode,
|
||||
|
@ -90,9 +90,9 @@ pub mod prelude {
|
|||
consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, generation,
|
||||
has_context, needs_update, parent_scope, provide_context, provide_root_context,
|
||||
remove_future, schedule_update, schedule_update_any, spawn, spawn_forever, suspend,
|
||||
try_consume_context, use_error_boundary, use_hook, AnyValue, Attribute, Component, Element,
|
||||
ErrorBoundary, Event, EventHandler, Fragment, HasAttributes, IntoAttributeValue,
|
||||
IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId, ScopeState, Task, Template,
|
||||
TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner, VirtualDom,
|
||||
try_consume_context, use_error_boundary, use_hook, AnyValue, Attribute, Component,
|
||||
ComponentFn, Element, ErrorBoundary, Event, EventHandler, Fragment, HasAttributes,
|
||||
IntoAttributeValue, IntoDynNode, Properties, Runtime, RuntimeGuard, ScopeId, ScopeState,
|
||||
Task, Template, TemplateAttribute, TemplateNode, Throw, VNode, VNodeInner, VirtualDom,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use crate::innerlude::{ElementRef, EventHandler, MountId};
|
||||
use crate::properties::ComponentFunction;
|
||||
use crate::{
|
||||
any_props::{BoxedAnyProps, VProps},
|
||||
innerlude::ScopeState,
|
||||
};
|
||||
use crate::{arena::ElementId, Element, Event};
|
||||
use crate::{
|
||||
innerlude::{ElementRef, EventHandler, MountId},
|
||||
properties::ComponentFn,
|
||||
};
|
||||
use crate::{Properties, VirtualDom};
|
||||
use core::panic;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::vec;
|
||||
use std::{
|
||||
|
@ -15,6 +16,7 @@ use std::{
|
|||
cell::Cell,
|
||||
fmt::{Arguments, Debug},
|
||||
};
|
||||
use std::{ffi::c_void, ops::Deref};
|
||||
|
||||
pub type TemplateId = &'static str;
|
||||
|
||||
|
@ -511,7 +513,7 @@ pub struct VComponent {
|
|||
/// The function pointer of the component, known at compile time
|
||||
///
|
||||
/// It is possible that components get folded at compile time, so these shouldn't be really used as a key
|
||||
pub(crate) render_fn: TypeId,
|
||||
pub(crate) render_fn: *const c_void,
|
||||
|
||||
pub(crate) props: BoxedAnyProps,
|
||||
}
|
||||
|
@ -531,22 +533,19 @@ impl VComponent {
|
|||
/// fn(Props) -> Element;
|
||||
/// async fn(Scope<Props<'_>>) -> Element;
|
||||
/// ```
|
||||
pub fn new<F: ComponentFunction<P> + 'static, P: 'static>(
|
||||
component: F,
|
||||
props: F::Props,
|
||||
fn_name: &'static str,
|
||||
) -> Self
|
||||
pub fn new<P, M>(component: impl ComponentFn<P, M>, props: P, fn_name: &'static str) -> Self
|
||||
where
|
||||
// The properties must be valid until the next bump frame
|
||||
F::Props: Properties + 'static,
|
||||
P: Properties + 'static,
|
||||
{
|
||||
let render_fn_id = TypeId::of::<F>();
|
||||
let vcomp = VProps::new(component, F::Props::memoize, props, fn_name);
|
||||
let component = Rc::new(component).as_component();
|
||||
let render_fn = component.as_ref() as *const _ as *const c_void;
|
||||
let vcomp = VProps::new(component, <P as Properties>::memoize, props, fn_name);
|
||||
|
||||
VComponent {
|
||||
name: fn_name,
|
||||
render_fn: render_fn_id,
|
||||
props: BoxedAnyProps::new(vcomp),
|
||||
render_fn,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{any::Any, marker::PhantomData};
|
||||
use std::any::Any;
|
||||
|
||||
use crate::{ComponentFunction, VirtualDom};
|
||||
use crate::{properties::ComponentFn, Component, VirtualDom};
|
||||
|
||||
/// A boxed object that can be injected into a component's context.
|
||||
pub struct BoxedContext(Box<dyn ClonableAny>);
|
||||
|
@ -40,33 +40,26 @@ impl<T: Any + Clone> ClonableAny for T {
|
|||
}
|
||||
|
||||
/// The platform-independent part of the config needed to launch an application.
|
||||
pub struct CrossPlatformConfig<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> {
|
||||
pub struct CrossPlatformConfig<Props: Clone + 'static> {
|
||||
/// The root component function.
|
||||
pub component: Component,
|
||||
pub component: Component<Props>,
|
||||
/// The props for the root component.
|
||||
pub props: Props,
|
||||
/// The contexts to provide to the root component.
|
||||
pub root_contexts: Vec<BoxedContext>,
|
||||
_phantom: PhantomData<Phantom>,
|
||||
}
|
||||
|
||||
impl<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> CrossPlatformConfig<Component, Props, Phantom>
|
||||
{
|
||||
impl<Props: Clone + 'static> CrossPlatformConfig<Props> {
|
||||
/// Create a new cross-platform config.
|
||||
pub fn new(component: Component, props: Props, root_contexts: Vec<BoxedContext>) -> Self {
|
||||
pub fn new<M>(
|
||||
component: impl ComponentFn<Props, M>,
|
||||
props: Props,
|
||||
root_contexts: Vec<BoxedContext>,
|
||||
) -> Self {
|
||||
Self {
|
||||
component,
|
||||
component: ComponentFn::as_component(std::rc::Rc::new(component)),
|
||||
props,
|
||||
root_contexts,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,19 +81,13 @@ pub trait PlatformBuilder<Props: Clone + 'static> {
|
|||
type Config: Default;
|
||||
|
||||
/// Launch the app.
|
||||
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||
config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||
platform_config: Self::Config,
|
||||
);
|
||||
fn launch(config: CrossPlatformConfig<Props>, platform_config: Self::Config);
|
||||
}
|
||||
|
||||
impl<Props: Clone + 'static> PlatformBuilder<Props> for () {
|
||||
type Config = ();
|
||||
|
||||
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||
_: CrossPlatformConfig<Component, Props, Phantom>,
|
||||
_: Self::Config,
|
||||
) {
|
||||
fn launch(_: CrossPlatformConfig<Props>, _: Self::Config) {
|
||||
panic!("No platform is currently enabled. Please enable a platform feature for the dioxus crate.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::innerlude::*;
|
||||
|
||||
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
|
||||
|
@ -29,11 +31,7 @@ pub trait Properties: Clone + Sized + 'static {
|
|||
/// Create a builder for this component.
|
||||
fn builder() -> Self::Builder;
|
||||
|
||||
/// Memoization can only happen if the props are valid for the 'static lifetime
|
||||
///
|
||||
/// # Safety
|
||||
/// The user must know if their props are static, but if they make a mistake, UB happens
|
||||
/// Therefore it's unsafe to memoize.
|
||||
/// Compare two props to see if they are memoizable.
|
||||
fn memoize(&self, other: &Self) -> bool;
|
||||
}
|
||||
|
||||
|
@ -56,98 +54,51 @@ impl EmptyBuilder {
|
|||
|
||||
/// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern
|
||||
/// to initialize a component's props.
|
||||
pub fn fc_to_builder<F: ComponentFunction<P>, P>(
|
||||
_: F,
|
||||
) -> <<F as ComponentFunction<P>>::Props as Properties>::Builder
|
||||
pub fn fc_to_builder<P, M>(_: impl ComponentFn<P, M>) -> <P as Properties>::Builder
|
||||
where
|
||||
F::Props: Properties,
|
||||
P: Properties,
|
||||
{
|
||||
F::Props::builder()
|
||||
P::builder()
|
||||
}
|
||||
|
||||
/// Every component used in rsx must implement the `ComponentFunction` trait. This trait tells dioxus how your component should be rendered.
|
||||
///
|
||||
/// Dioxus automatically implements this trait for any function that either takes no arguments or a single props argument and returns an Element.
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// For components that take no props:
|
||||
///
|
||||
/// ```rust
|
||||
/// fn app() -> Element {
|
||||
/// rsx! {
|
||||
/// div {}
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For props that take a props struct:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[derive(Props, PartialEq, Clone)]
|
||||
/// struct MyProps {
|
||||
/// data: String
|
||||
/// }
|
||||
///
|
||||
/// fn app(props: MyProps) -> Element {
|
||||
/// rsx! {
|
||||
/// div {
|
||||
/// "{props.data}"
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Or you can use the #[component] macro to automatically implement create the props struct:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[component]
|
||||
/// fn app(data: String) -> Element {
|
||||
/// rsx! {
|
||||
/// div {
|
||||
/// "{data}"
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// > Note: If you get an error about the `ComponentFunction` trait not being implemented: make sure your props implements the `Properties` trait or if you would like to declare your props inline, make sure you use the #[component] macro on your function.
|
||||
pub trait ComponentFunction<P>: Clone + 'static {
|
||||
/// The props type for this component.
|
||||
type Props: 'static;
|
||||
|
||||
/// Run the component function with the given props.
|
||||
fn call(&self, props: Self::Props) -> Element;
|
||||
/// Any component that implements the `ComponentFn` trait can be used as a component.
|
||||
pub trait ComponentFn<Props, Marker> {
|
||||
/// Convert the component to a function that takes props and returns an element.
|
||||
fn as_component(self: Rc<Self>) -> Component<Props>;
|
||||
}
|
||||
|
||||
impl<T: 'static, F: Fn(T) -> Element + Clone + 'static> ComponentFunction<(T,)> for F {
|
||||
type Props = T;
|
||||
|
||||
fn call(&self, props: T) -> Element {
|
||||
self(props)
|
||||
/// Accept pre-formed component render functions as components
|
||||
impl<P> ComponentFn<P, ()> for Component<P> {
|
||||
fn as_component(self: Rc<Self>) -> Component<P> {
|
||||
self.as_ref().clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct ZeroElementMarker;
|
||||
impl<F: Fn() -> Element + Clone + 'static> ComponentFunction<ZeroElementMarker> for F {
|
||||
type Props = ();
|
||||
/// Accept any callbacks that take props
|
||||
impl<F: Fn(P) -> Element + 'static, P> ComponentFn<P, ()> for F {
|
||||
fn as_component(self: Rc<Self>) -> Component<P> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn call(&self, _: ()) -> Element {
|
||||
self()
|
||||
/// Accept any callbacks that take no props
|
||||
pub struct EmptyMarker;
|
||||
impl<F: Fn() -> Element + 'static> ComponentFn<(), EmptyMarker> for F {
|
||||
fn as_component(self: Rc<Self>) -> Rc<dyn Fn(()) -> Element> {
|
||||
Rc::new(move |_| self())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_builder() {
|
||||
fn app() -> Element {
|
||||
unimplemented!()
|
||||
fn it_works_maybe() {
|
||||
fn test(_: ()) -> Element {
|
||||
todo!()
|
||||
}
|
||||
fn app2(_: ()) -> Element {
|
||||
unimplemented!()
|
||||
fn test2() -> Element {
|
||||
todo!()
|
||||
}
|
||||
let builder = fc_to_builder(app);
|
||||
builder.build();
|
||||
let builder = fc_to_builder(app2);
|
||||
builder.build();
|
||||
|
||||
let callable: Rc<dyn ComponentFn<(), ()>> = Rc::new(test) as Rc<dyn ComponentFn<_, _>>;
|
||||
let callable2: Rc<dyn ComponentFn<(), EmptyMarker>> =
|
||||
Rc::new(test2) as Rc<dyn ComponentFn<_, _>>;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::{
|
|||
},
|
||||
nodes::RenderReturn,
|
||||
nodes::{Template, TemplateId},
|
||||
properties::ComponentFn,
|
||||
runtime::{Runtime, RuntimeGuard},
|
||||
scopes::ScopeId,
|
||||
AttributeValue, BoxedContext, Element, Event, Mutations,
|
||||
|
@ -227,7 +228,7 @@ impl VirtualDom {
|
|||
///
|
||||
/// Note: the VirtualDom is not progressed, you must either "run_with_deadline" or use "rebuild" to progress it.
|
||||
pub fn new(app: fn() -> Element) -> Self {
|
||||
Self::new_with_props(app, ())
|
||||
Self::new_with_props(move || app(), ())
|
||||
}
|
||||
|
||||
/// Create a new virtualdom and build it immediately
|
||||
|
@ -267,12 +268,8 @@ impl VirtualDom {
|
|||
/// let mut dom = VirtualDom::new_with_props(Example, SomeProps { name: "jane" });
|
||||
/// let mutations = dom.rebuild();
|
||||
/// ```
|
||||
pub fn new_with_props<
|
||||
F: crate::ComponentFunction<Phantom, Props = P>,
|
||||
P: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
>(
|
||||
root: F,
|
||||
pub fn new_with_props<P: Clone + 'static, M>(
|
||||
root: impl ComponentFn<P, M>,
|
||||
root_props: P,
|
||||
) -> Self {
|
||||
let (tx, rx) = futures_channel::mpsc::unbounded();
|
||||
|
@ -290,7 +287,12 @@ impl VirtualDom {
|
|||
};
|
||||
|
||||
let root = dom.new_scope(
|
||||
BoxedAnyProps::new(VProps::new(root, |_, _| true, root_props, "root")),
|
||||
BoxedAnyProps::new(VProps::new(
|
||||
Rc::new(root).as_component(),
|
||||
|_, _| true,
|
||||
root_props,
|
||||
"root",
|
||||
)),
|
||||
"app",
|
||||
);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
webview::WebviewInstance,
|
||||
};
|
||||
use crossbeam_channel::Receiver;
|
||||
use dioxus_core::{ComponentFunction, CrossPlatformConfig, ElementId};
|
||||
use dioxus_core::{CrossPlatformConfig, ElementId};
|
||||
use dioxus_html::{
|
||||
native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData, HtmlEvent,
|
||||
PlatformEventData,
|
||||
|
@ -29,14 +29,10 @@ use tao::{
|
|||
};
|
||||
|
||||
/// The single top-level object that manages all the running windows, assets, shortcuts, etc
|
||||
pub(crate) struct App<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> {
|
||||
pub(crate) struct App<Props: Clone + 'static> {
|
||||
// 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<Component, Props, Phantom>>>,
|
||||
pub(crate) dioxus_config: Cell<Option<CrossPlatformConfig<Props>>>,
|
||||
pub(crate) cfg: Cell<Option<Config>>,
|
||||
|
||||
// Stuff we need mutable access to
|
||||
|
@ -49,8 +45,6 @@ pub(crate) struct App<
|
|||
///
|
||||
/// This includes stuff like the event handlers, shortcuts, etc as well as ways to modify *other* windows
|
||||
pub(crate) shared: Rc<SharedContext>,
|
||||
|
||||
phantom: PhantomData<Phantom>,
|
||||
}
|
||||
|
||||
/// A bundle of state shared between all the windows, providing a way for us to communicate with running webview.
|
||||
|
@ -65,15 +59,10 @@ pub struct SharedContext {
|
|||
pub(crate) target: EventLoopWindowTarget<UserWindowEvent>,
|
||||
}
|
||||
|
||||
impl<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> App<Component, Props, Phantom>
|
||||
{
|
||||
impl<Props: Clone + 'static> App<Props> {
|
||||
pub fn new(
|
||||
cfg: Config,
|
||||
dioxus_config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||
dioxus_config: CrossPlatformConfig<Props>,
|
||||
) -> (EventLoop<UserWindowEvent>, Self) {
|
||||
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
||||
|
||||
|
@ -92,7 +81,6 @@ impl<
|
|||
proxy: event_loop.create_proxy(),
|
||||
target: event_loop.clone(),
|
||||
}),
|
||||
phantom: PhantomData,
|
||||
};
|
||||
|
||||
// Set the event converter
|
||||
|
|
|
@ -10,12 +10,8 @@ use tao::event::{Event, StartCause, WindowEvent};
|
|||
///
|
||||
/// 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<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
>(
|
||||
dioxus_cfg: CrossPlatformConfig<Component, Props, Phantom>,
|
||||
pub fn launch_with_props_blocking<Props: Clone + 'static>(
|
||||
dioxus_cfg: CrossPlatformConfig<Props>,
|
||||
desktop_config: Config,
|
||||
) {
|
||||
let (event_loop, mut app) = App::new(desktop_config, dioxus_cfg);
|
||||
|
@ -60,10 +56,7 @@ pub struct DesktopPlatform;
|
|||
impl<Props: Clone + 'static> PlatformBuilder<Props> for DesktopPlatform {
|
||||
type Config = Config;
|
||||
|
||||
fn launch<Component: ComponentFunction<Phantom, Props = Props>, Phantom: 'static>(
|
||||
config: dioxus_core::CrossPlatformConfig<Component, Props, Phantom>,
|
||||
platform_config: Self::Config,
|
||||
) {
|
||||
fn launch(config: dioxus_core::CrossPlatformConfig<Props>, platform_config: Self::Config) {
|
||||
#[cfg(feature = "tokio")]
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
|
|
|
@ -4,29 +4,19 @@ use std::any::Any;
|
|||
|
||||
use crate::prelude::*;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_core::ComponentFunction;
|
||||
use dioxus_core::{BoxedContext, CrossPlatformConfig, PlatformBuilder};
|
||||
|
||||
/// A builder for a fullstack app.
|
||||
pub struct LaunchBuilder<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
Platform: PlatformBuilder<Props> = CurrentPlatform,
|
||||
> {
|
||||
cross_platform_config: CrossPlatformConfig<Component, Props, Phantom>,
|
||||
pub struct LaunchBuilder<Props: Clone + 'static, Platform: PlatformBuilder<Props> = CurrentPlatform>
|
||||
{
|
||||
cross_platform_config: CrossPlatformConfig<Props>,
|
||||
platform_config: Option<<Platform as PlatformBuilder<Props>>::Config>,
|
||||
}
|
||||
|
||||
// Default platform builder
|
||||
impl<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> LaunchBuilder<Component, Props, Phantom>
|
||||
{
|
||||
impl<Props: Clone + 'static> LaunchBuilder<Props> {
|
||||
/// 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: Component) -> Self
|
||||
pub fn new<M>(component: impl ComponentFn<Props, M>) -> Self
|
||||
where
|
||||
Props: Default,
|
||||
{
|
||||
|
@ -41,13 +31,7 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
Platform: PlatformBuilder<Props>,
|
||||
> LaunchBuilder<Component, Props, Phantom, Platform>
|
||||
{
|
||||
impl<Props: Clone + 'static, Platform: PlatformBuilder<Props>> LaunchBuilder<Props, Platform> {
|
||||
/// Pass some props to your application.
|
||||
pub fn props(mut self, props: Props) -> Self {
|
||||
self.cross_platform_config.props = props;
|
||||
|
@ -84,12 +68,7 @@ impl<
|
|||
}
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
impl<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> LaunchBuilder<Component, Props, Phantom, dioxus_web::WebPlatform>
|
||||
{
|
||||
impl<Props: Clone + 'static> LaunchBuilder<Props, dioxus_web::WebPlatform> {
|
||||
/// Launch your web application.
|
||||
pub fn launch_web(self) {
|
||||
dioxus_web::WebPlatform::launch(
|
||||
|
@ -100,12 +79,7 @@ impl<
|
|||
}
|
||||
|
||||
#[cfg(feature = "desktop")]
|
||||
impl<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
> LaunchBuilder<Component, Props, Phantom, dioxus_desktop::DesktopPlatform>
|
||||
{
|
||||
impl<Props: Clone + 'static> LaunchBuilder<Props, dioxus_desktop::DesktopPlatform> {
|
||||
/// Launch your desktop application.
|
||||
pub fn launch_desktop(self) {
|
||||
dioxus_desktop::DesktopPlatform::launch(
|
||||
|
@ -123,42 +97,27 @@ type CurrentPlatform = dioxus_web::WebPlatform;
|
|||
type CurrentPlatform = ();
|
||||
|
||||
/// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
>(
|
||||
component: Component,
|
||||
) where
|
||||
Props: Default,
|
||||
pub fn launch<Props, Marker>(component: impl ComponentFn<Props, Marker>)
|
||||
where
|
||||
Props: Default + Clone + 'static,
|
||||
{
|
||||
LaunchBuilder::new(component).launch()
|
||||
}
|
||||
|
||||
#[cfg(feature = "web")]
|
||||
/// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch_web<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
>(
|
||||
component: Component,
|
||||
) where
|
||||
Props: Default,
|
||||
pub fn launch_web<Props, Marker>(component: impl ComponentFn<Props, Marker>)
|
||||
where
|
||||
Props: Default + Clone + 'static,
|
||||
{
|
||||
LaunchBuilder::new(component).launch_web()
|
||||
}
|
||||
|
||||
#[cfg(feature = "desktop")]
|
||||
/// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
|
||||
pub fn launch_desktop<
|
||||
Component: ComponentFunction<Phantom, Props = Props>,
|
||||
Props: Clone + 'static,
|
||||
Phantom: 'static,
|
||||
>(
|
||||
component: Component,
|
||||
) where
|
||||
Props: Default,
|
||||
pub fn launch_desktop<Props, Marker>(component: impl ComponentFn<Props, Marker>)
|
||||
where
|
||||
Props: Default + Clone + 'static,
|
||||
{
|
||||
LaunchBuilder::new(component).launch_desktop()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue