diff --git a/Cargo.lock b/Cargo.lock index 2a61c00cc..1c129eb7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2375,6 +2375,7 @@ dependencies = [ name = "dioxus-core" version = "0.5.2" dependencies = [ + "const_format", "dioxus", "dioxus-html", "dioxus-ssr", diff --git a/Cargo.toml b/Cargo.toml index 09e732845..ff2061dc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ prettyplease = { version = "0.2.16", features = ["verbatim"] } manganis-cli-support = { git = "https://github.com/DogeDark/dioxus-collect-assets/", features = ["html"] } manganis = { version = "0.2.1" } interprocess = { version = "1.2.2", package = "interprocess-docfix" } +const_format = "0.2.32" lru = "0.12.2" async-trait = "0.1.77" diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index a3e60f89f..ca6cb0954 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -23,6 +23,7 @@ tracing = { workspace = true } serde = { version = "1", features = ["derive"], optional = true } generational-box = { workspace = true } rustversion = "1.0.17" +const_format = { workspace = true } [dev-dependencies] tokio = { workspace = true, features = ["full"] } diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index abc39a090..fed25c34c 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -91,3 +91,5 @@ pub mod prelude { TemplateAttribute, TemplateNode, VNode, VNodeInner, VirtualDom, }; } + +pub use const_format; diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index c3aeb4107..c6e100eb7 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -584,8 +584,9 @@ impl VirtualDom { // Recurse into the dynamic nodes of the existing mounted node to see if the template is alive in the tree fn check_node_for_templates(node: &crate::VNode, template: Template) -> bool { let this_template_name = node.template.get().name.rsplit_once(':').unwrap().0; + let other_template_name = template.name.rsplit_once(':').unwrap().0; - if this_template_name == template.name.rsplit_once(':').unwrap().0 { + if this_template_name == other_template_name { return true; } diff --git a/packages/hot-reload/src/websocket.rs b/packages/hot-reload/src/websocket.rs index 58ea7a48a..033bfe71a 100644 --- a/packages/hot-reload/src/websocket.rs +++ b/packages/hot-reload/src/websocket.rs @@ -107,16 +107,20 @@ async fn ws_handler( ws.on_upgrade(move |socket| ws_reload_handler(socket, state)) } -async fn ws_reload_handler(mut socket: WebSocket, state: HotReloadReceiver) { +/// Handles full-reloads (e.g. page refresh). +async fn ws_reload_handler(mut socket: WebSocket, mut state: HotReloadReceiver) { let mut rx = state.reload.subscribe(); loop { rx.recv().await.unwrap(); - let _ = socket.send(Message::Text(String::from("reload"))).await; + // We need to clear the cached templates because we are doing a "fresh" build + // and the templates may force the page to a state before the full reload. + state.clear_all_modified_templates(); // ignore the error - println!("forcing reload"); + let _ = socket.send(Message::Text(String::from("reload"))).await; + tracing::info!("forcing reload"); // flush the errors after recompling rx = rx.resubscribe(); @@ -167,6 +171,11 @@ impl HotReloadReceiver { .collect() } + /// Clears the cache of modified templates. + pub fn clear_all_modified_templates(&mut self) { + self.template_updates.lock().unwrap().clear(); + } + /// Send a hot reloading message to the client pub fn send_message(&self, msg: HotReloadMsg) { // Before we send the message, update the list of changed templates diff --git a/packages/rsx/src/hot_reload/hot_reloading_file_map.rs b/packages/rsx/src/hot_reload/hot_reloading_file_map.rs index 6a213cdc1..c0fe960f8 100644 --- a/packages/rsx/src/hot_reload/hot_reloading_file_map.rs +++ b/packages/rsx/src/hot_reload/hot_reloading_file_map.rs @@ -305,10 +305,7 @@ pub fn template_location(old_start: proc_macro2::LineColumn, file: &Path) -> Str let line = old_start.line; let column = old_start.column + 1; - #[cfg(not(target_os = "windows"))] - let path = file.to_string_lossy().to_string(); - - #[cfg(target_os = "windows")] + // Always ensure the path components are separated by `/`. let path = file .components() .map(|c| c.as_os_str().to_string_lossy()) diff --git a/packages/rsx/src/renderer.rs b/packages/rsx/src/renderer.rs index f87d8a353..0b3415847 100644 --- a/packages/rsx/src/renderer.rs +++ b/packages/rsx/src/renderer.rs @@ -79,16 +79,13 @@ impl<'a> TemplateRenderer<'a> { // Get the root:column:id tag we'll use as the ID of the template let root_col = self.get_root_col_id(); + // Replace `\\` to `/` and then replace `\` to `/` quote! { - concat!( - file!(), - ":", - line!(), - ":", - column!(), - ":", - #root_col - ) + { + const PATH: &str = dioxus_core::const_format::str_replace!(file!(), "\\\\", "/"); + const NORMAL: &str = dioxus_core::const_format::str_replace!(PATH, '\\', "/"); + dioxus_core::const_format::concatcp!(NORMAL, ':', line!(), ':', column!(), ':', #root_col) + } } } }