launch.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //! Launch helper macros for fullstack apps
  2. #![allow(clippy::new_without_default)]
  3. #![allow(unused)]
  4. use std::any::Any;
  5. use crate::prelude::*;
  6. /// A builder for a fullstack app.
  7. #[must_use]
  8. pub struct LaunchBuilder<Cfg: 'static = (), ContextFn: ?Sized = ValidContext> {
  9. launch_fn: LaunchFn<Cfg, ContextFn>,
  10. contexts: Vec<Box<ContextFn>>,
  11. platform_config: Option<Box<dyn Any>>,
  12. }
  13. pub type LaunchFn<Cfg, Context> = fn(fn() -> Element, Vec<Box<Context>>, Cfg);
  14. #[cfg(any(feature = "fullstack", feature = "liveview"))]
  15. type ValidContext = SendContext;
  16. #[cfg(not(any(feature = "fullstack", feature = "liveview")))]
  17. type ValidContext = UnsendContext;
  18. type SendContext = dyn Fn() -> Box<dyn Any> + Send + Sync + 'static;
  19. type UnsendContext = dyn Fn() -> Box<dyn Any> + 'static;
  20. impl LaunchBuilder {
  21. /// 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.
  22. pub fn new() -> LaunchBuilder<current_platform::Config, ValidContext> {
  23. LaunchBuilder {
  24. launch_fn: current_platform::launch,
  25. contexts: Vec::new(),
  26. platform_config: None,
  27. }
  28. }
  29. /// Launch your web application.
  30. #[cfg(feature = "web")]
  31. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "web")))]
  32. pub fn web() -> LaunchBuilder<dioxus_web::Config, UnsendContext> {
  33. LaunchBuilder {
  34. launch_fn: dioxus_web::launch::launch,
  35. contexts: Vec::new(),
  36. platform_config: None,
  37. }
  38. }
  39. /// Launch your desktop application.
  40. #[cfg(feature = "desktop")]
  41. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "desktop")))]
  42. pub fn desktop() -> LaunchBuilder<dioxus_desktop::Config, UnsendContext> {
  43. LaunchBuilder {
  44. launch_fn: dioxus_desktop::launch::launch,
  45. contexts: Vec::new(),
  46. platform_config: None,
  47. }
  48. }
  49. /// Launch your fullstack application.
  50. #[cfg(feature = "fullstack")]
  51. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "fullstack")))]
  52. pub fn fullstack() -> LaunchBuilder<dioxus_fullstack::Config, SendContext> {
  53. LaunchBuilder {
  54. launch_fn: dioxus_fullstack::launch::launch,
  55. contexts: Vec::new(),
  56. platform_config: None,
  57. }
  58. }
  59. /// Launch your fullstack application.
  60. #[cfg(feature = "mobile")]
  61. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "mobile")))]
  62. pub fn mobile() -> LaunchBuilder<dioxus_mobile::Config, UnsendContext> {
  63. LaunchBuilder {
  64. launch_fn: dioxus_mobile::launch::launch,
  65. contexts: Vec::new(),
  66. platform_config: None,
  67. }
  68. }
  69. #[cfg(feature = "tui")]
  70. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "tui")))]
  71. /// Launch your tui application
  72. pub fn tui() -> LaunchBuilder<dioxus_tui::Config, UnsendContext> {
  73. LaunchBuilder {
  74. launch_fn: dioxus_tui::launch::launch,
  75. contexts: Vec::new(),
  76. platform_config: None,
  77. }
  78. }
  79. /// Provide a custom launch function for your application.
  80. ///
  81. /// Useful for third party renderers to tap into the launch builder API without having to reimplement it.
  82. pub fn custom<Cfg, List>(launch_fn: LaunchFn<Cfg, List>) -> LaunchBuilder<Cfg, List> {
  83. LaunchBuilder {
  84. launch_fn,
  85. contexts: vec![],
  86. platform_config: None,
  87. }
  88. }
  89. }
  90. // Fullstack platform builder
  91. impl<Cfg> LaunchBuilder<Cfg, UnsendContext> {
  92. /// Inject state into the root component's context that is created on the thread that the app is launched on.
  93. pub fn with_context_provider(mut self, state: impl Fn() -> Box<dyn Any> + 'static) -> Self {
  94. self.contexts.push(Box::new(state) as Box<UnsendContext>);
  95. self
  96. }
  97. /// Inject state into the root component's context.
  98. pub fn with_context(mut self, state: impl Any + Clone + 'static) -> Self {
  99. self.contexts
  100. .push(Box::new(move || Box::new(state.clone())));
  101. self
  102. }
  103. }
  104. impl<Cfg> LaunchBuilder<Cfg, SendContext> {
  105. /// Inject state into the root component's context that is created on the thread that the app is launched on.
  106. pub fn with_context_provider(
  107. mut self,
  108. state: impl Fn() -> Box<dyn Any> + Send + Sync + 'static,
  109. ) -> Self {
  110. self.contexts.push(Box::new(state) as Box<SendContext>);
  111. self
  112. }
  113. /// Inject state into the root component's context.
  114. pub fn with_context(mut self, state: impl Any + Clone + Send + Sync + 'static) -> Self {
  115. self.contexts
  116. .push(Box::new(move || Box::new(state.clone())));
  117. self
  118. }
  119. }
  120. impl<Cfg: Default + 'static, ContextFn: ?Sized> LaunchBuilder<Cfg, ContextFn> {
  121. /// Provide a platform-specific config to the builder.
  122. pub fn with_cfg<CG: 'static>(mut self, config: impl Into<Option<CG>>) -> Self {
  123. if let Some(config) = config.into() {
  124. self.platform_config = Some(Box::new(config));
  125. }
  126. self
  127. }
  128. /// Launch your application.
  129. pub fn launch(self, app: fn() -> Element) {
  130. let cfg: Box<Cfg> = self
  131. .platform_config
  132. .and_then(|c| c.downcast().ok())
  133. .unwrap_or_default();
  134. (self.launch_fn)(app, self.contexts, *cfg)
  135. }
  136. }
  137. mod current_platform {
  138. #[cfg(all(feature = "desktop", not(feature = "fullstack")))]
  139. pub use dioxus_desktop::launch::*;
  140. #[cfg(feature = "fullstack")]
  141. pub use dioxus_fullstack::launch::*;
  142. #[cfg(all(feature = "web", not(any(feature = "desktop", feature = "fullstack"))))]
  143. pub use dioxus_web::launch::*;
  144. #[cfg(all(
  145. feature = "liveview",
  146. not(any(feature = "web", feature = "desktop", feature = "fullstack"))
  147. ))]
  148. pub use dioxus_liveview::launch::*;
  149. #[cfg(all(
  150. feature = "tui",
  151. not(any(
  152. feature = "liveview",
  153. feature = "web",
  154. feature = "desktop",
  155. feature = "fullstack"
  156. ))
  157. ))]
  158. pub use dioxus_tui::launch::*;
  159. #[cfg(not(any(
  160. feature = "liveview",
  161. feature = "desktop",
  162. feature = "web",
  163. feature = "tui",
  164. feature = "fullstack"
  165. )))]
  166. pub type Config = ();
  167. #[cfg(not(any(
  168. feature = "liveview",
  169. feature = "desktop",
  170. feature = "web",
  171. feature = "tui",
  172. feature = "fullstack"
  173. )))]
  174. pub fn launch(
  175. root: fn() -> dioxus_core::Element,
  176. contexts: Vec<Box<super::ValidContext>>,
  177. platform_config: (),
  178. ) {
  179. }
  180. }
  181. /// Launch your application without any additional configuration. See [`LaunchBuilder`] for more options.
  182. pub fn launch(app: fn() -> Element) {
  183. LaunchBuilder::new().launch(app)
  184. }
  185. #[cfg(feature = "web")]
  186. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "web")))]
  187. /// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options.
  188. pub fn launch_web(app: fn() -> Element) {
  189. LaunchBuilder::web().launch(app)
  190. }
  191. #[cfg(feature = "desktop")]
  192. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "desktop")))]
  193. /// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options.
  194. pub fn launch_desktop(app: fn() -> Element) {
  195. LaunchBuilder::desktop().launch(app)
  196. }
  197. #[cfg(feature = "fullstack")]
  198. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "fullstack")))]
  199. /// Launch your fullstack application without any additional configuration. See [`LaunchBuilder`] for more options.
  200. pub fn launch_fullstack(app: fn() -> Element) {
  201. LaunchBuilder::fullstack().launch(app)
  202. }
  203. #[cfg(feature = "tui")]
  204. #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "tui")))]
  205. /// Launch your tui application without any additional configuration. See [`LaunchBuilder`] for more options.
  206. pub fn launch_tui(app: fn() -> Element) {
  207. LaunchBuilder::tui().launch(app)
  208. }