diff --git a/examples/simple_desktop.rs b/examples/simple_desktop.rs index 74bfb28c6..6c8bf8d72 100644 --- a/examples/simple_desktop.rs +++ b/examples/simple_desktop.rs @@ -48,7 +48,7 @@ fn BlogList(cx: Scope) -> Element { fn BlogPost(cx: Scope) -> Element { let Some(id) = use_route(cx).segment("id") else { - return cx.render(rsx! { div { "No blog post id" } }) + return cx.render(rsx! { div { "No blog post id" } }); }; log::debug!("rendering blog post {}", id); diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index 57794b728..1cd6d787e 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -364,6 +364,7 @@ pub fn build_desktop(config: &CrateConfig, _is_serve: bool) -> Result { - crate::builder::build_desktop(&crate_config, true)?; - - match &crate_config.executable { - crate::ExecutableType::Binary(name) - | crate::ExecutableType::Lib(name) - | crate::ExecutableType::Example(name) => { - let mut file = crate_config.out_dir.join(name); - if cfg!(windows) { - file.set_extension("exe"); - } - Command::new(file.to_str().unwrap()) - .stdout(Stdio::inherit()) - .output()?; - } - } + server::desktop::startup(crate_config.clone()).await?; } } Ok(()) diff --git a/packages/cli/src/server/desktop/mod.rs b/packages/cli/src/server/desktop/mod.rs index 0a0c0f35f..6a2c57539 100644 --- a/packages/cli/src/server/desktop/mod.rs +++ b/packages/cli/src/server/desktop/mod.rs @@ -3,7 +3,7 @@ use crate::{ serve::Serve, server::{ output::{print_console_info, PrettierOptions, WebServerInfo}, - setup_file_watcher, setup_file_watcher_hot_reload, BuildManager, + setup_file_watcher, setup_file_watcher_hot_reload, }, BuildResult, CrateConfig, Result, }; @@ -72,7 +72,15 @@ pub async fn serve_default(config: CrateConfig) -> Result<()> { // We got to own watcher so that it exists for the duration of serve // Otherwise full reload won't work. - let _watcher = setup_file_watcher(crate::cfg::Platform::Desktop, &config, None, None).await?; + let _watcher = setup_file_watcher( + { + let config = config.clone(); + move || start_desktop(&config) + }, + &config, + None, + ) + .await?; // Print serve info print_console_info( @@ -107,15 +115,13 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> { } let file_map = Arc::new(Mutex::new(map)); - let build_manager = Arc::new(BuildManager { - platform: crate::cfg::Platform::Web, - config: config.clone(), - reload_tx: None, - }); let (hot_reload_tx, mut hot_reload_rx) = broadcast::channel(100); // States + // The open interprocess sockets + let channels = Arc::new(Mutex::new(Vec::new())); + // Setup file watcher // We got to own watcher so that it exists for the duration of serve // Otherwise hot reload won't work. @@ -123,7 +129,17 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> { &config, hot_reload_tx, file_map.clone(), - build_manager, + { + let config = config.clone(); + + let channels = channels.clone(); + move || { + for channel in &mut *channels.lock().unwrap() { + send_msg(HotReloadMsg::Shutdown, channel); + } + start_desktop(&config) + } + }, None, ) .await?; @@ -153,8 +169,6 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> { } } - let channels = Arc::new(Mutex::new(Vec::new())); - match LocalSocketListener::bind("@dioxusin") { Ok(local_socket_stream) => { let aborted = Arc::new(Mutex::new(false)); @@ -196,10 +210,6 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> { } }); - // for channel in &mut *channels.lock().unwrap() { - // send_msg(HotReloadMsg::Shutdown, channel); - // } - while let Ok(template) = hot_reload_rx.recv().await { let channels = &mut *channels.lock().unwrap(); let mut i = 0; diff --git a/packages/cli/src/server/mod.rs b/packages/cli/src/server/mod.rs index 389f5000b..8c421f269 100644 --- a/packages/cli/src/server/mod.rs +++ b/packages/cli/src/server/mod.rs @@ -39,18 +39,11 @@ pub mod desktop; pub mod web; /// Sets up a file watcher -async fn setup_file_watcher( - platform: Platform, +async fn setup_file_watcher Result + Send + 'static>( + build_with: F, config: &CrateConfig, - reload_tx: Option>, web_info: Option, ) -> Result { - let build_manager = BuildManager { - platform, - config: config.clone(), - reload_tx, - }; - let mut last_update_time = chrono::Local::now().timestamp(); // file watcher: check file change @@ -67,7 +60,7 @@ async fn setup_file_watcher( let config = watcher_config.clone(); if let Ok(e) = info { if chrono::Local::now().timestamp() > last_update_time { - match build_manager.rebuild() { + match build_with() { Ok(res) => { last_update_time = chrono::Local::now().timestamp(); @@ -108,11 +101,11 @@ async fn setup_file_watcher( // Todo: reduce duplication and merge with setup_file_watcher() /// Sets up a file watcher with hot reload -async fn setup_file_watcher_hot_reload( +async fn setup_file_watcher_hot_reload Result + Send + 'static>( config: &CrateConfig, hot_reload_tx: Sender>, file_map: Arc>>, - build_manager: Arc, + build_with: F, web_info: Option, ) -> Result { // file watcher: check file change @@ -138,7 +131,7 @@ async fn setup_file_watcher_hot_reload( for path in evt.paths.clone() { // if this is not a rust file, rebuild the whole project if path.extension().and_then(|p| p.to_str()) != Some("rs") { - match build_manager.rebuild() { + match build_with() { Ok(res) => { print_console_info( &config, @@ -164,7 +157,7 @@ async fn setup_file_watcher_hot_reload( messages.extend(msgs); } Ok(UpdateResult::NeedsRebuild) => { - match build_manager.rebuild() { + match build_with() { Ok(res) => { print_console_info( &config, @@ -209,35 +202,3 @@ async fn setup_file_watcher_hot_reload( Ok(watcher) } - -pub struct BuildManager { - platform: Platform, - config: CrateConfig, - reload_tx: Option>, -} - -impl BuildManager { - fn rebuild(&self) -> Result { - log::info!("🪁 Rebuild project"); - match self.platform { - Platform::Web => { - let result = builder::build(&self.config, true)?; - // change the websocket reload state to true; - // the page will auto-reload. - if self - .config - .dioxus_config - .web - .watcher - .reload_html - .unwrap_or(false) - { - let _ = Serve::regen_dev_page(&self.config); - } - let _ = self.reload_tx.as_ref().map(|tx| tx.send(())); - Ok(result) - } - Platform::Desktop => start_desktop(&self.config), - } - } -} diff --git a/packages/cli/src/server/web/hot_reload.rs b/packages/cli/src/server/web/hot_reload.rs index 167e712af..49cce38d4 100644 --- a/packages/cli/src/server/web/hot_reload.rs +++ b/packages/cli/src/server/web/hot_reload.rs @@ -10,12 +10,10 @@ use dioxus_html::HtmlCtx; use dioxus_rsx::hot_reload::FileMap; use tokio::sync::broadcast; -use super::BuildManager; use crate::CrateConfig; pub struct HotReloadState { pub messages: broadcast::Sender>, - pub build_manager: Arc, pub file_map: Arc>>, pub watcher_config: CrateConfig, } diff --git a/packages/cli/src/server/web/mod.rs b/packages/cli/src/server/web/mod.rs index c7661f028..e6a429788 100644 --- a/packages/cli/src/server/web/mod.rs +++ b/packages/cli/src/server/web/mod.rs @@ -3,7 +3,7 @@ use crate::{ serve::Serve, server::{ output::{print_console_info, PrettierOptions, WebServerInfo}, - setup_file_watcher, setup_file_watcher_hot_reload, BuildManager, + setup_file_watcher, setup_file_watcher_hot_reload, }, BuildResult, CrateConfig, Result, }; @@ -86,9 +86,12 @@ pub async fn serve_default( // We got to own watcher so that it exists for the duration of serve // Otherwise full reload won't work. let _watcher = setup_file_watcher( - crate::cfg::Platform::Web, + { + let config = config.clone(); + let reload_tx = reload_tx.clone(); + move || build(&config, &reload_tx) + }, &config, - Some(reload_tx.clone()), Some(WebServerInfo { ip: ip.clone(), port, @@ -148,18 +151,12 @@ pub async fn serve_hot_reload( } let file_map = Arc::new(Mutex::new(map)); - let build_manager = Arc::new(BuildManager { - platform: crate::cfg::Platform::Web, - config: config.clone(), - reload_tx: Some(reload_tx.clone()), - }); let hot_reload_tx = broadcast::channel(100).0; // States let hot_reload_state = Arc::new(HotReloadState { messages: hot_reload_tx.clone(), - build_manager: build_manager.clone(), file_map: file_map.clone(), watcher_config: config.clone(), }); @@ -175,7 +172,11 @@ pub async fn serve_hot_reload( &config, hot_reload_tx, file_map, - build_manager, + { + let config = config.clone(); + let reload_tx = reload_tx.clone(); + move || build(&config, &reload_tx) + }, Some(WebServerInfo { ip: ip.clone(), port, @@ -473,3 +474,20 @@ async fn ws_handler( reload_watcher.await.unwrap(); }) } + +fn build(config: &CrateConfig, reload_tx: &Sender<()>) -> Result { + let result = builder::build(&config, true)?; + // change the websocket reload state to true; + // the page will auto-reload. + if config + .dioxus_config + .web + .watcher + .reload_html + .unwrap_or(false) + { + let _ = Serve::regen_dev_page(&config); + } + let _ = reload_tx.send(()); + Ok(result) +} diff --git a/packages/fullstack/src/adapters/salvo_adapter.rs b/packages/fullstack/src/adapters/salvo_adapter.rs index 59b7c36ea..a31c1ea67 100644 --- a/packages/fullstack/src/adapters/salvo_adapter.rs +++ b/packages/fullstack/src/adapters/salvo_adapter.rs @@ -378,7 +378,7 @@ impl ServerFnHandler { .to_vec() .into(); let body = hyper::body::to_bytes(req.body_mut().unwrap()).await; - let Ok(body)=body else { + let Ok(body) = body else { handle_error(body.err().unwrap(), res); return; }; diff --git a/packages/html/src/events/form.rs b/packages/html/src/events/form.rs index 113c765c5..1fe59a640 100644 --- a/packages/html/src/events/form.rs +++ b/packages/html/src/events/form.rs @@ -56,10 +56,9 @@ where { use serde::Deserialize; - let Ok(file_engine) = - SerializedFileEngine::deserialize(deserializer) else{ - return Ok(None); - }; + let Ok(file_engine) = SerializedFileEngine::deserialize(deserializer) else { + return Ok(None); + }; let file_engine = std::sync::Arc::new(file_engine); Ok(Some(file_engine)) diff --git a/packages/rink/src/widgets/button.rs b/packages/rink/src/widgets/button.rs index e4d3754f1..9018a3e9a 100644 --- a/packages/rink/src/widgets/button.rs +++ b/packages/rink/src/widgets/button.rs @@ -82,7 +82,9 @@ impl Button { fn write_value(&self, rdom: &mut RealDom) { if let Some(mut text) = rdom.get_mut(self.text_id) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.value.clone(); } } @@ -111,7 +113,9 @@ impl CustomElement for Button { fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el .attributes @@ -146,7 +150,9 @@ impl CustomElement for Button { AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); } @@ -155,7 +161,9 @@ impl CustomElement for Button { AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/rink/src/widgets/checkbox.rs b/packages/rink/src/widgets/checkbox.rs index 24b3f6244..fab809ed2 100644 --- a/packages/rink/src/widgets/checkbox.rs +++ b/packages/rink/src/widgets/checkbox.rs @@ -94,14 +94,18 @@ impl CheckBox { fn write_value(&self, mut root: NodeMut) { let single_char = { let node_type = root.node_type_mut(); - let NodeTypeMut::Element( el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(el) = node_type else { + panic!("input must be an element") + }; Self::width(&el) == "1px" || Self::height(&el) == "1px" }; let rdom = root.real_dom_mut(); if let Some(mut text) = rdom.get_mut(self.text_id) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; let value = if single_char { if self.checked { "☑" @@ -156,7 +160,9 @@ impl CustomElement for CheckBox { fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el .attributes @@ -197,7 +203,9 @@ impl CustomElement for CheckBox { AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); self.update_checked_attr(&el); @@ -207,7 +215,9 @@ impl CustomElement for CheckBox { AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/rink/src/widgets/input.rs b/packages/rink/src/widgets/input.rs index c6a3e56b9..c1fb563d7 100644 --- a/packages/rink/src/widgets/input.rs +++ b/packages/rink/src/widgets/input.rs @@ -56,7 +56,9 @@ impl CustomElement for Input { } let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let input_type = el .attributes .get(&OwnedAttributeDiscription { diff --git a/packages/rink/src/widgets/slider.rs b/packages/rink/src/widgets/slider.rs index f97c12bf6..7080b6c12 100644 --- a/packages/rink/src/widgets/slider.rs +++ b/packages/rink/src/widgets/slider.rs @@ -163,7 +163,9 @@ impl Slider { if let Some(mut div) = rdom.get_mut(self.pre_cursor_div) { let node_type = div.node_type_mut(); - let NodeTypeMut::Element(mut element) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut element) = node_type else { + panic!("input must be an element") + }; element.set_attribute( OwnedAttributeDiscription { name: "width".to_string(), @@ -175,7 +177,9 @@ impl Slider { if let Some(mut div) = rdom.get_mut(self.post_cursor_div) { let node_type = div.node_type_mut(); - let NodeTypeMut::Element(mut element) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut element) = node_type else { + panic!("input must be an element") + }; element.set_attribute( OwnedAttributeDiscription { name: "width".to_string(), @@ -259,7 +263,9 @@ impl CustomElement for Slider { fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el.attributes.get(&OwnedAttributeDiscription { name: "value".to_string(), @@ -390,7 +396,9 @@ impl CustomElement for Slider { AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); self.update_max_attr(&el); @@ -403,7 +411,9 @@ impl CustomElement for Slider { AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/rink/src/widgets/text_like.rs b/packages/rink/src/widgets/text_like.rs index b5874c776..6521073d0 100644 --- a/packages/rink/src/widgets/text_like.rs +++ b/packages/rink/src/widgets/text_like.rs @@ -143,19 +143,25 @@ impl TextLike { if let Some(mut text) = rdom.get_mut(self.pre_cursor_text) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.controller.display_text(text_before_first_cursor); } if let Some(mut text) = rdom.get_mut(self.highlighted_text) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.controller.display_text(text_highlighted); } if let Some(mut text) = rdom.get_mut(self.post_cursor_text) { let node_type = text.node_type_mut(); - let NodeTypeMut::Text(mut text) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Text(mut text) = node_type else { + panic!("input must be an element") + }; *text.text_mut() = self.controller.display_text(text_after_second_cursor); } @@ -288,7 +294,9 @@ impl CustomElement for fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self { let node_type = root.node_type(); - let NodeType::Element(el) = &*node_type else { panic!("input must be an element") }; + let NodeType::Element(el) = &*node_type else { + panic!("input must be an element") + }; let value = el .attributes @@ -370,7 +378,9 @@ impl CustomElement for AttributeMask::All => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; self.update_value_attr(&el); self.update_size_attr(&mut el); self.update_max_width_attr(&el); @@ -381,7 +391,9 @@ impl CustomElement for AttributeMask::Some(attrs) => { { let node_type = root.node_type_mut(); - let NodeTypeMut::Element(mut el) = node_type else { panic!("input must be an element") }; + let NodeTypeMut::Element(mut el) = node_type else { + panic!("input must be an element") + }; if attrs.contains("width") || attrs.contains("height") { self.update_size_attr(&mut el); } diff --git a/packages/router/examples/simple_routes.rs b/packages/router/examples/simple_routes.rs index 9b94c7a9d..8c1a6fc76 100644 --- a/packages/router/examples/simple_routes.rs +++ b/packages/router/examples/simple_routes.rs @@ -38,7 +38,7 @@ fn BlogList(cx: Scope) -> Element { fn BlogPost(cx: Scope) -> Element { let Some(id) = use_route(cx).segment("id") else { - return cx.render(rsx! { div { "No blog post id" } }) + return cx.render(rsx! { div { "No blog post id" } }); }; log::trace!("rendering blog post {}", id);