|
@@ -5,98 +5,104 @@ use std::any::Any;
|
|
|
use crate::prelude::*;
|
|
|
use dioxus_core::prelude::*;
|
|
|
use dioxus_core::ComponentFunction;
|
|
|
-
|
|
|
-pub trait ClonableAny: Any {
|
|
|
- fn clone_box(&self) -> Box<dyn ClonableAny>;
|
|
|
-}
|
|
|
-
|
|
|
-impl<T: Any + Clone> ClonableAny for T {
|
|
|
- fn clone_box(&self) -> Box<dyn ClonableAny> {
|
|
|
- Box::new(self.clone())
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/// The platform-independent part of the config needed to launch an application.
|
|
|
-pub struct CrossPlatformConfig<F: ComponentFunction<P>, P> {
|
|
|
- /// The root component function.
|
|
|
- pub component: F,
|
|
|
- /// The props for the root component.
|
|
|
- pub props: P,
|
|
|
- /// The contexts to provide to the root component.
|
|
|
- pub root_contexts: Vec<Box<dyn ClonableAny>>,
|
|
|
-}
|
|
|
-
|
|
|
-pub trait PlatformBuilder<P> {
|
|
|
- type Config;
|
|
|
-
|
|
|
- /// Launch the app.
|
|
|
- fn launch<F: ComponentFunction<P>>(config: CrossPlatformConfig<F, P>, config: Self::Config);
|
|
|
-}
|
|
|
-
|
|
|
-impl<P> PlatformBuilder<P> for () {
|
|
|
- type Config = ();
|
|
|
-
|
|
|
- fn launch<F: ComponentFunction<P>>(config: CrossPlatformConfig<F, P>, _: ()) {}
|
|
|
-}
|
|
|
+use dioxus_core::{BoxedContext, CrossPlatformConfig, PlatformBuilder};
|
|
|
|
|
|
/// A builder for a fullstack app.
|
|
|
-pub struct LaunchBuilder<F: ComponentFunction<P>, P> {
|
|
|
- cross_platform_config: CrossPlatformConfig<F, P>,
|
|
|
+pub struct LaunchBuilder<
|
|
|
+ Component: ComponentFunction<Phantom, Props = Props>,
|
|
|
+ Props: Clone + 'static,
|
|
|
+ Phantom: 'static,
|
|
|
+> {
|
|
|
+ cross_platform_config: CrossPlatformConfig<Component, Props, Phantom>,
|
|
|
+ platform_config: Option<<CurrentPlatform as PlatformBuilder<Props>>::Config>,
|
|
|
}
|
|
|
|
|
|
-impl<F: ComponentFunction<P>, P> LaunchBuilder<F, P> {
|
|
|
+impl<
|
|
|
+ Component: ComponentFunction<Phantom, Props = Props>,
|
|
|
+ Props: Clone + 'static,
|
|
|
+ Phantom: 'static,
|
|
|
+ > LaunchBuilder<Component, Props, Phantom>
|
|
|
+{
|
|
|
/// Create a new builder for your application.
|
|
|
- pub fn new(component: F) -> Self
|
|
|
+ pub fn new(component: Component) -> Self
|
|
|
where
|
|
|
- P: Default,
|
|
|
+ Props: Default,
|
|
|
{
|
|
|
Self {
|
|
|
- cross_platform_config: CrossPlatformConfig {
|
|
|
+ cross_platform_config: CrossPlatformConfig::new(
|
|
|
component,
|
|
|
- props: Default::default(),
|
|
|
- root_contexts: vec![],
|
|
|
- },
|
|
|
+ Default::default(),
|
|
|
+ Default::default(),
|
|
|
+ ),
|
|
|
+ platform_config: None,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// Pass some props to your application.
|
|
|
- pub fn props(mut self, props: P) -> Self {
|
|
|
+ pub fn props(mut self, props: Props) -> Self {
|
|
|
self.cross_platform_config.props = props;
|
|
|
self
|
|
|
}
|
|
|
|
|
|
/// Inject state into the root component's context.
|
|
|
- pub fn context(mut self, state: impl ClonableAny + 'static) -> Self {
|
|
|
+ pub fn context(mut self, state: impl Any + Clone + 'static) -> Self {
|
|
|
self.cross_platform_config
|
|
|
.root_contexts
|
|
|
- .push(Box::new(state));
|
|
|
+ .push(BoxedContext::new(state));
|
|
|
self
|
|
|
}
|
|
|
|
|
|
/// Provide a platform-specific config to the builder.
|
|
|
- pub fn platform_config(
|
|
|
- self,
|
|
|
- config: Option<<CurrentPlatform as PlatformBuilder<P>>::Config>,
|
|
|
+ pub fn cfg(
|
|
|
+ mut self,
|
|
|
+ config: impl Into<Option<<CurrentPlatform as PlatformBuilder<Props>>::Config>>,
|
|
|
) -> Self {
|
|
|
+ if let Some(config) = config.into() {
|
|
|
+ self.platform_config = Some(config);
|
|
|
+ }
|
|
|
self
|
|
|
}
|
|
|
|
|
|
+ #[allow(clippy::unit_arg)]
|
|
|
/// Launch the app.
|
|
|
- pub fn launch(self) {}
|
|
|
-}
|
|
|
-
|
|
|
-#[cfg(feature = "router")]
|
|
|
-impl<R: Routable> LaunchBuilder<crate::router::FullstackRouterConfig<R>>
|
|
|
-where
|
|
|
- <R as std::str::FromStr>::Err: std::fmt::Display,
|
|
|
- R: Clone + serde::Serialize + serde::de::DeserializeOwned + Send + Sync + 'static,
|
|
|
-{
|
|
|
- /// Create a new launch builder for the given router.
|
|
|
- pub fn router() -> Self {
|
|
|
- let component = crate::router::RouteWithCfg::<R>;
|
|
|
- let props = crate::router::FullstackRouterConfig::default();
|
|
|
- Self::new_with_props(component, props)
|
|
|
+ pub fn launch(self) {
|
|
|
+ CurrentPlatform::launch(
|
|
|
+ self.cross_platform_config,
|
|
|
+ self.platform_config.unwrap_or_default(),
|
|
|
+ );
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// #[cfg(feature = "router")]
|
|
|
+// impl<R: Routable> LaunchBuilder<crate::router::FullstackRouterConfig<R>>
|
|
|
+// where
|
|
|
+// <R as std::str::FromStr>::Err: std::fmt::Display,
|
|
|
+// R: Clone + serde::Serialize + serde::de::DeserializeOwned + Send + Sync + 'static,
|
|
|
+// {
|
|
|
+// /// Create a new launch builder for the given router.
|
|
|
+// pub fn router() -> Self {
|
|
|
+// let component = crate::router::RouteWithCfg::<R>;
|
|
|
+// let props = crate::router::FullstackRouterConfig::default();
|
|
|
+// Self::new_with_props(component, props)
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+#[cfg(feature = "desktop")]
|
|
|
+type CurrentPlatform = dioxus_desktop::DesktopPlatform;
|
|
|
+#[cfg(feature = "web")]
|
|
|
+type CurrentPlatform = dioxus_web::WebPlatform;
|
|
|
+#[cfg(not(any(feature = "desktop", feature = "web")))]
|
|
|
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,
|
|
|
+{
|
|
|
+ LaunchBuilder::new(component).launch()
|
|
|
+}
|