diff --git a/packages/cli/src/server/desktop/mod.rs b/packages/cli/src/server/desktop/mod.rs index c574fccb4..6e3cc4f5f 100644 --- a/packages/cli/src/server/desktop/mod.rs +++ b/packages/cli/src/server/desktop/mod.rs @@ -14,7 +14,7 @@ use interprocess::local_socket::LocalSocketListener; use std::{ fs::create_dir_all, process::{Child, Command}, - sync::{Arc, Mutex, RwLock}, + sync::{Arc, RwLock}, }; use tokio::sync::broadcast::{self}; @@ -75,6 +75,22 @@ async fn serve( serve: &ConfigOptsServe, hot_reload_state: Option, ) -> Result<()> { + let hot_reload: tokio::task::JoinHandle> = tokio::spawn({ + let hot_reload_state = hot_reload_state.clone(); + async move { + match hot_reload_state { + Some(hot_reload_state) => { + // The open interprocess sockets + start_desktop_hot_reload(hot_reload_state).await?; + } + None => { + std::future::pending::<()>().await; + } + } + Ok(()) + } + }); + let platform = RwLock::new(P::start(&config, serve)?); tracing::info!("🚀 Starting development server..."); @@ -88,19 +104,11 @@ async fn serve( }, &config, None, - hot_reload_state.clone(), + hot_reload_state, ) .await?; - match hot_reload_state { - Some(hot_reload_state) => { - // The open interprocess sockets - start_desktop_hot_reload(hot_reload_state).await?; - } - None => { - std::future::pending::<()>().await; - } - } + hot_reload.await.unwrap()?; Ok(()) } @@ -115,7 +123,12 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() let _ = create_dir_all(target_dir); // `_all` is for good measure and future-proofness. let path = target_dir.join("dioxusin"); clear_paths(&path); - match LocalSocketListener::bind(path) { + let listener = if cfg!(windows) { + LocalSocketListener::bind("@dioxusin") + } else { + LocalSocketListener::bind(path) + }; + match listener { Ok(local_socket_stream) => { let aborted = Arc::new(Mutex::new(false)); // States diff --git a/packages/desktop/Cargo.toml b/packages/desktop/Cargo.toml index 61932dd28..aaa148823 100644 --- a/packages/desktop/Cargo.toml +++ b/packages/desktop/Cargo.toml @@ -49,6 +49,8 @@ futures-util = { workspace = true } urlencoding = "2.1.2" async-trait = "0.1.68" tao = { version = "0.26.1", features = ["rwh_05"] } + +[target.'cfg(unix)'.dependencies] signal-hook = "0.3.17" [target.'cfg(any(target_os = "windows",target_os = "macos",target_os = "linux",target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))'.dependencies] diff --git a/packages/desktop/src/app.rs b/packages/desktop/src/app.rs index 37ec93cd8..6efbf2c08 100644 --- a/packages/desktop/src/app.rs +++ b/packages/desktop/src/app.rs @@ -474,22 +474,26 @@ impl App { /// Whenever sigkill is sent, we shut down the app and save the window state #[cfg(debug_assertions)] fn connect_preserve_window_state_handler(&self) { - // Wire up the trap - let target = self.shared.proxy.clone(); - std::thread::spawn(move || { - use signal_hook::consts::{SIGINT, SIGTERM}; - let sigkill = signal_hook::iterator::Signals::new([SIGTERM, SIGINT]); - if let Ok(mut sigkill) = sigkill { - for _ in sigkill.forever() { - if target.send_event(UserWindowEvent::Shutdown).is_err() { - std::process::exit(0); - } + // TODO: make this work on windows + #[cfg(unix)] + { + // Wire up the trap + let target = self.shared.proxy.clone(); + std::thread::spawn(move || { + use signal_hook::consts::{SIGINT, SIGTERM}; + let sigkill = signal_hook::iterator::Signals::new([SIGTERM, SIGINT]); + if let Ok(mut sigkill) = sigkill { + for _ in sigkill.forever() { + if target.send_event(UserWindowEvent::Shutdown).is_err() { + std::process::exit(0); + } - // give it a moment for the event to be processed - std::thread::sleep(std::time::Duration::from_secs(1)); + // give it a moment for the event to be processed + std::thread::sleep(std::time::Duration::from_secs(1)); + } } - } - }); + }); + } } } diff --git a/packages/hot-reload/src/file_watcher.rs b/packages/hot-reload/src/file_watcher.rs index ce4a7c8d8..d7652b757 100644 --- a/packages/hot-reload/src/file_watcher.rs +++ b/packages/hot-reload/src/file_watcher.rs @@ -173,7 +173,13 @@ pub fn init(cfg: Config) { } } - let local_socket_stream = match LocalSocketListener::bind(hot_reload_socket_path) { + let listener = if cfg!(windows) { + LocalSocketListener::bind("@dioxusin") + } else { + LocalSocketListener::bind(hot_reload_socket_path) + }; + + let local_socket_stream = match listener { Ok(local_socket_stream) => local_socket_stream, Err(err) => { println!("failed to connect to hot reloading\n{err}"); diff --git a/packages/hot-reload/src/lib.rs b/packages/hot-reload/src/lib.rs index 021843b66..b7a0866af 100644 --- a/packages/hot-reload/src/lib.rs +++ b/packages/hot-reload/src/lib.rs @@ -30,41 +30,49 @@ pub enum HotReloadMsg { /// Connect to the hot reloading listener. The callback provided will be called every time a template change is detected pub fn connect(callback: impl FnMut(HotReloadMsg) + Send + 'static) { - // FIXME: this is falling back onto the current directory when not running under cargo, which is how the CLI runs this. - // This needs to be fixed. - let _manifest_dir = std::env::var("CARGO_MANIFEST_DIR"); + if cfg!(windows) { + connect_at(PathBuf::from("@dioxusin"), callback); + } else { + // FIXME: this is falling back onto the current directory when not running under cargo, which is how the CLI runs this. + // This needs to be fixed. + let _manifest_dir = std::env::var("CARGO_MANIFEST_DIR"); - // get the cargo manifest directory, where the target dir lives - let mut path = match _manifest_dir { - Ok(manifest_dir) => PathBuf::from(manifest_dir), - Err(_) => std::env::current_dir().unwrap(), - }; + // get the cargo manifest directory, where the target dir lives + let mut path = match _manifest_dir { + Ok(manifest_dir) => PathBuf::from(manifest_dir), + Err(_) => std::env::current_dir().unwrap(), + }; - // walk the path until we a find a socket named `dioxusin` inside that folder's target directory - loop { - let maybe = path.join("target").join("dioxusin"); + // walk the path until we a find a socket named `dioxusin` inside that folder's target directory + loop { + let maybe = path.join("target").join("dioxusin"); - if maybe.exists() { - path = maybe; - break; + if maybe.exists() { + path = maybe; + break; + } + + // It's likely we're running under just cargo and not dx + path = match path.parent() { + Some(parent) => parent.to_path_buf(), + None => return, + }; } - // It's likely we're running under just cargo and not dx - path = match path.parent() { - Some(parent) => parent.to_path_buf(), - None => return, - }; + println!("connecting to {:?}", path); + connect_at(path, callback); } - - println!("connecting to {:?}", path); - - connect_at(path, callback); } pub fn connect_at(socket: PathBuf, mut callback: impl FnMut(HotReloadMsg) + Send + 'static) { std::thread::spawn(move || { // There might be a socket since the we're not running under the hot reloading server - let Ok(socket) = LocalSocketStream::connect(socket.clone()) else { + let stream = if cfg!(windows) { + LocalSocketStream::connect("@dioxusin") + } else { + LocalSocketStream::connect(socket.clone()) + }; + let Ok(socket) = stream else { println!( "could not find hot reloading server at {:?}, make sure it's running", socket