Provide option to do full rebuilds when nessisary
This commit is contained in:
1 parent
3c229b38bc
commit
b3d119b815
6 files changed
+217
-95
No files matched your search
@@ -8,8 +8,8 @@ use crate::events::IpcMessage;
|
|||||||
use crate::Config;
|
use crate::Config;
|
||||||
use crate::WebviewHandler;
|
use crate::WebviewHandler;
|
||||||
use dioxus_core::ScopeState;
|
use dioxus_core::ScopeState;
|
||||||
use dioxus_core::Template;
|
|
||||||
use dioxus_core::VirtualDom;
|
use dioxus_core::VirtualDom;
|
||||||
|
use dioxus_hot_reload::HotReloadMsg;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use wry::application::event_loop::EventLoopProxy;
|
use wry::application::event_loop::EventLoopProxy;
|
||||||
use wry::application::event_loop::EventLoopWindowTarget;
|
use wry::application::event_loop::EventLoopWindowTarget;
|
||||||
@@ -263,7 +263,7 @@ pub enum EventData {
|
|||||||
|
|
||||||
Ipc(IpcMessage),
|
Ipc(IpcMessage),
|
||||||
|
|
||||||
TemplateUpdated(Template<'static>),
|
HotReloadEvent(HotReloadMsg),
|
||||||
|
|
||||||
NewWindow,
|
NewWindow,
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||||||
let proxy = proxy.clone();
|
let proxy = proxy.clone();
|
||||||
dioxus_hot_reload::connect(move |template| {
|
dioxus_hot_reload::connect(move |template| {
|
||||||
let _ = proxy.send_event(UserWindowEvent(
|
let _ = proxy.send_event(UserWindowEvent(
|
||||||
EventData::TemplateUpdated(template),
|
EventData::HotReloadEvent(template),
|
||||||
unsafe { WindowId::dummy() },
|
unsafe { WindowId::dummy() },
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
@@ -177,13 +177,18 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Event::UserEvent(event) => match event.0 {
|
Event::UserEvent(event) => match event.0 {
|
||||||
EventData::TemplateUpdated(template) => {
|
EventData::HotReloadEvent(msg) => match msg {
|
||||||
for webview in webviews.values_mut() {
|
dioxus_hot_reload::HotReloadMsg::UpdateTemplate(template) => {
|
||||||
webview.dom.replace_template(template);
|
for webview in webviews.values_mut() {
|
||||||
|
webview.dom.replace_template(template);
|
||||||
|
|
||||||
poll_vdom(webview);
|
poll_vdom(webview);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
dioxus_hot_reload::HotReloadMsg::Shutdown => {
|
||||||
|
*control_flow = ControlFlow::Exit;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
EventData::CloseWindow => {
|
EventData::CloseWindow => {
|
||||||
webviews.remove(&event.1);
|
webviews.remove(&event.1);
|
||||||
|
|||||||
@@ -14,3 +14,6 @@ interprocess = { version = "1.2.1" }
|
|||||||
notify = "5.0.0"
|
notify = "5.0.0"
|
||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
serde_json = "1.0.91"
|
serde_json = "1.0.91"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
execute = "0.2.11"
|
||||||
|
once_cell = "1.17.0"
|
||||||
+175
-76
@@ -15,42 +15,141 @@ use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
|||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub use dioxus_html::HtmlCtx;
|
pub use dioxus_html::HtmlCtx;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Initialize the hot reloading listener on the given path
|
/// A message the hot reloading server sends to the client
|
||||||
pub fn init<Ctx: HotReloadingContext + Send + 'static>(
|
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
|
||||||
|
pub enum HotReloadMsg {
|
||||||
|
/// A template has been updated
|
||||||
|
#[serde(borrow = "'static")]
|
||||||
|
UpdateTemplate(Template<'static>),
|
||||||
|
/// The program needs to be recompiled, and the client should shut down
|
||||||
|
Shutdown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Config<Ctx: HotReloadingContext = HtmlCtx> {
|
||||||
root_path: &'static str,
|
root_path: &'static str,
|
||||||
listening_paths: &'static [&'static str],
|
listening_paths: &'static [&'static str],
|
||||||
|
excluded_paths: &'static [&'static str],
|
||||||
log: bool,
|
log: bool,
|
||||||
) {
|
rebuild_with: Option<&'static str>,
|
||||||
|
phantom: std::marker::PhantomData<Ctx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ctx: HotReloadingContext> Default for Config<Ctx> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
root_path: "",
|
||||||
|
listening_paths: &[""],
|
||||||
|
excluded_paths: &["./target"],
|
||||||
|
log: true,
|
||||||
|
rebuild_with: None,
|
||||||
|
phantom: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config<HtmlCtx> {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
root_path: "",
|
||||||
|
listening_paths: &[""],
|
||||||
|
excluded_paths: &["./target"],
|
||||||
|
log: true,
|
||||||
|
rebuild_with: None,
|
||||||
|
phantom: std::marker::PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ctx: HotReloadingContext> Config<Ctx> {
|
||||||
|
pub const fn root(self, path: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
root_path: path,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn listening_paths(self, paths: &'static [&'static str]) -> Self {
|
||||||
|
Self {
|
||||||
|
listening_paths: paths,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn log(self, log: bool) -> Self {
|
||||||
|
Self { log, ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn rebuild_with(self, rebuild_with: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
rebuild_with: Some(rebuild_with),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn excluded_paths(self, paths: &'static [&'static str]) -> Self {
|
||||||
|
Self {
|
||||||
|
excluded_paths: paths,
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the hot reloading listener
|
||||||
|
pub fn init<Ctx: HotReloadingContext + Send + 'static>(cfg: Config<Ctx>) {
|
||||||
|
let Config {
|
||||||
|
root_path,
|
||||||
|
listening_paths,
|
||||||
|
log,
|
||||||
|
rebuild_with,
|
||||||
|
excluded_paths,
|
||||||
|
phantom: _,
|
||||||
|
} = cfg;
|
||||||
|
|
||||||
if let Ok(crate_dir) = PathBuf::from_str(root_path) {
|
if let Ok(crate_dir) = PathBuf::from_str(root_path) {
|
||||||
let temp_file = std::env::temp_dir().join("@dioxusin");
|
let temp_file = std::env::temp_dir().join("@dioxusin");
|
||||||
let channels = Arc::new(Mutex::new(Vec::new()));
|
let channels = Arc::new(Mutex::new(Vec::new()));
|
||||||
let file_map = Arc::new(Mutex::new(FileMap::<Ctx>::new(crate_dir.clone())));
|
let file_map = Arc::new(Mutex::new(FileMap::<Ctx>::new(crate_dir.clone())));
|
||||||
if let Ok(local_socket_stream) = LocalSocketListener::bind(temp_file.as_path()) {
|
if let Ok(local_socket_stream) = LocalSocketListener::bind(temp_file.as_path()) {
|
||||||
|
let aborted = Arc::new(Mutex::new(false));
|
||||||
|
|
||||||
// listen for connections
|
// listen for connections
|
||||||
std::thread::spawn({
|
std::thread::spawn({
|
||||||
let file_map = file_map.clone();
|
let file_map = file_map.clone();
|
||||||
let channels = channels.clone();
|
let channels = channels.clone();
|
||||||
|
let aborted = aborted.clone();
|
||||||
|
let _ = local_socket_stream.set_nonblocking(true);
|
||||||
move || {
|
move || {
|
||||||
for mut connection in local_socket_stream.incoming().flatten() {
|
loop {
|
||||||
// send any templates than have changed before the socket connected
|
if let Ok(mut connection) = local_socket_stream.accept() {
|
||||||
let templates: Vec<_> = {
|
// send any templates than have changed before the socket connected
|
||||||
file_map
|
let templates: Vec<_> = {
|
||||||
.lock()
|
file_map
|
||||||
.unwrap()
|
.lock()
|
||||||
.map
|
.unwrap()
|
||||||
.values()
|
.map
|
||||||
.filter_map(|(_, template_slot)| *template_slot)
|
.values()
|
||||||
.collect()
|
.filter_map(|(_, template_slot)| *template_slot)
|
||||||
};
|
.collect()
|
||||||
for template in templates {
|
};
|
||||||
if !send_template(template, &mut connection) {
|
for template in templates {
|
||||||
continue;
|
if !send_msg(
|
||||||
|
HotReloadMsg::UpdateTemplate(template),
|
||||||
|
&mut connection,
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channels.lock().unwrap().push(connection);
|
||||||
|
if log {
|
||||||
|
println!("Connected to hot reloading 🚀");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
channels.lock().unwrap().push(connection);
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
||||||
if log {
|
if aborted.lock().unwrap().clone() {
|
||||||
println!("Connected to hot reloading 🚀");
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,37 +164,42 @@ pub fn init<Ctx: HotReloadingContext + Send + 'static>(
|
|||||||
let mut watcher = RecommendedWatcher::new(tx, notify::Config::default()).unwrap();
|
let mut watcher = RecommendedWatcher::new(tx, notify::Config::default()).unwrap();
|
||||||
|
|
||||||
for path in listening_paths {
|
for path in listening_paths {
|
||||||
match PathBuf::from_str(path) {
|
let full_path = crate_dir.join(path);
|
||||||
Ok(path) => {
|
if let Err(err) = watcher.watch(&full_path, RecursiveMode::Recursive) {
|
||||||
let full_path = crate_dir.join(path);
|
if log {
|
||||||
if let Err(err) = watcher.watch(&full_path, RecursiveMode::Recursive) {
|
println!(
|
||||||
if log {
|
"hot reloading failed to start watching {full_path:?}:\n{err:?}",
|
||||||
println!(
|
);
|
||||||
"hot reloading failed to start watching {full_path:?}:\n{err:?}",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
if log {
|
|
||||||
println!("hot reloading failed to create path:\n{:?}", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let excluded_paths = excluded_paths
|
||||||
|
.iter()
|
||||||
|
.map(|path| crate_dir.join(PathBuf::from(path)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
for evt in rx {
|
for evt in rx {
|
||||||
// Give time for the change to take effect before reading the file
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(100));
|
|
||||||
if chrono::Local::now().timestamp() > last_update_time {
|
if chrono::Local::now().timestamp() > last_update_time {
|
||||||
if let Ok(evt) = evt {
|
if let Ok(evt) = evt {
|
||||||
let mut channels = channels.lock().unwrap();
|
let real_paths = evt
|
||||||
for path in &evt.paths {
|
.paths
|
||||||
// skip non rust files
|
.iter()
|
||||||
if path.extension().and_then(|p| p.to_str()) != Some("rs") {
|
.filter(|path| {
|
||||||
continue;
|
// skip non rust files
|
||||||
}
|
path.extension().and_then(|p| p.to_str()) == Some("rs") &&
|
||||||
|
// skip excluded paths
|
||||||
|
!excluded_paths.iter().any(|p| path.starts_with(p))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Give time for the change to take effect before reading the file
|
||||||
|
if !real_paths.is_empty() {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut channels = channels.lock().unwrap();
|
||||||
|
for path in real_paths {
|
||||||
// find changes to the rsx in the file
|
// find changes to the rsx in the file
|
||||||
match file_map
|
match file_map
|
||||||
.lock()
|
.lock()
|
||||||
@@ -107,7 +211,10 @@ pub fn init<Ctx: HotReloadingContext + Send + 'static>(
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < channels.len() {
|
while i < channels.len() {
|
||||||
let channel = &mut channels[i];
|
let channel = &mut channels[i];
|
||||||
if send_template(msg, channel) {
|
if send_msg(
|
||||||
|
HotReloadMsg::UpdateTemplate(msg),
|
||||||
|
channel,
|
||||||
|
) {
|
||||||
i += 1;
|
i += 1;
|
||||||
} else {
|
} else {
|
||||||
channels.remove(i);
|
channels.remove(i);
|
||||||
@@ -116,11 +223,23 @@ pub fn init<Ctx: HotReloadingContext + Send + 'static>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateResult::NeedsRebuild => {
|
UpdateResult::NeedsRebuild => {
|
||||||
if log {
|
if let Some(rebuild_command) = rebuild_with {
|
||||||
println!(
|
*aborted.lock().unwrap() = true;
|
||||||
"Rebuild needed... shutting down hot reloading.\nManually rebuild the application to view futher changes."
|
if log {
|
||||||
);
|
println!("Rebuilding the application...");
|
||||||
|
}
|
||||||
|
execute::shell(rebuild_command).spawn().expect("Failed to rebuild the application. Is cargo installed?");
|
||||||
|
for channel in &mut *channels {
|
||||||
|
send_msg(HotReloadMsg::Shutdown, channel);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if log {
|
||||||
|
println!(
|
||||||
|
"Rebuild needed... shutting down hot reloading.\nManually rebuild the application to view futher changes."
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,8 +253,8 @@ pub fn init<Ctx: HotReloadingContext + Send + 'static>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_template(template: Template<'static>, channel: &mut impl Write) -> bool {
|
fn send_msg(msg: HotReloadMsg, channel: &mut impl Write) -> bool {
|
||||||
if let Ok(msg) = serde_json::to_string(&template) {
|
if let Ok(msg) = serde_json::to_string(&msg) {
|
||||||
if channel.write_all(msg.as_bytes()).is_err() {
|
if channel.write_all(msg.as_bytes()).is_err() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -149,7 +268,7 @@ fn send_template(template: Template<'static>, channel: &mut impl Write) -> bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Connect to the hot reloading listener. The callback provided will be called every time a template change is detected
|
/// Connect to the hot reloading listener. The callback provided will be called every time a template change is detected
|
||||||
pub fn connect(mut f: impl FnMut(Template<'static>) + Send + 'static) {
|
pub fn connect(mut f: impl FnMut(HotReloadMsg) + Send + 'static) {
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let temp_file = std::env::temp_dir().join("@dioxusin");
|
let temp_file = std::env::temp_dir().join("@dioxusin");
|
||||||
if let Ok(socket) = LocalSocketStream::connect(temp_file.as_path()) {
|
if let Ok(socket) = LocalSocketStream::connect(temp_file.as_path()) {
|
||||||
@@ -158,7 +277,7 @@ pub fn connect(mut f: impl FnMut(Template<'static>) + Send + 'static) {
|
|||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
match buf_reader.read_line(&mut buf) {
|
match buf_reader.read_line(&mut buf) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let template: Template<'static> =
|
let template: HotReloadMsg =
|
||||||
serde_json::from_str(Box::leak(buf.into_boxed_str())).unwrap();
|
serde_json::from_str(Box::leak(buf.into_boxed_str())).unwrap();
|
||||||
f(template);
|
f(template);
|
||||||
}
|
}
|
||||||
@@ -179,33 +298,13 @@ pub fn connect(mut f: impl FnMut(Template<'static>) + Send + 'static) {
|
|||||||
/// If no paths are passed, it will listen on the src and examples folders.
|
/// If no paths are passed, it will listen on the src and examples folders.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! hot_reload_init {
|
macro_rules! hot_reload_init {
|
||||||
($(@ $ctx:ident)? $($t: ident)*) => {
|
() => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dioxus_hot_reload::init::<hot_reload_init!(@ctx: $($ctx)?)>(core::env!("CARGO_MANIFEST_DIR"), &["src", "examples"], hot_reload_init!(@log: $($t)*))
|
dioxus_hot_reload::init(dioxus_hot_reload::Config::new().root(env!("CARGO_MANIFEST_DIR")));
|
||||||
};
|
};
|
||||||
|
|
||||||
($(@ $ctx:ident)? $($paths: literal),* $(,)? $($t: ident)*) => {
|
($cfg: expr) => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dioxus_hot_reload::init::<hot_reload_init!(@ctx: $($ctx)?)>(core::env!("CARGO_MANIFEST_DIR"), &[$($paths),*], hot_reload_init!(@log: $($t)*))
|
dioxus_hot_reload::init($cfg.root(env!("CARGO_MANIFEST_DIR")));
|
||||||
};
|
|
||||||
|
|
||||||
(@log:) => {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
(@log: enable logging) => {
|
|
||||||
true
|
|
||||||
};
|
|
||||||
|
|
||||||
(@log: disable logging) => {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
(@ctx: $ctx: ident) => {
|
|
||||||
$ctx
|
|
||||||
};
|
|
||||||
|
|
||||||
(@ctx: ) => {
|
|
||||||
dioxus_hot_reload::HtmlCtx
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -157,9 +157,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_template = hot_reload_wait => {
|
msg = hot_reload_wait => {
|
||||||
if let Some(new_template) = new_template {
|
if let Some(msg) = msg {
|
||||||
vdom.replace_template(new_template);
|
match msg{
|
||||||
|
dioxus_hot_reload::HotReloadMsg::UpdateTemplate(new_template) => {
|
||||||
|
vdom.replace_template(new_template);
|
||||||
|
}
|
||||||
|
dioxus_hot_reload::HotReloadMsg::Shutdown => {
|
||||||
|
std::process::exit(0);
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-8
@@ -6,6 +6,7 @@ use crossterm::{
|
|||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
};
|
};
|
||||||
use dioxus_core::*;
|
use dioxus_core::*;
|
||||||
|
use dioxus_hot_reload::HotReloadMsg;
|
||||||
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap};
|
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap};
|
||||||
use focus::FocusState;
|
use focus::FocusState;
|
||||||
use futures::{
|
use futures::{
|
||||||
@@ -147,9 +148,9 @@ fn render_vdom(
|
|||||||
.block_on(async {
|
.block_on(async {
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||||
let mut hot_reload_rx = {
|
let mut hot_reload_rx = {
|
||||||
let (hot_reload_tx, hot_reload_rx) = unbounded_channel::<Template<'static>>();
|
let (hot_reload_tx, hot_reload_rx) = unbounded_channel::<HotReloadMsg>();
|
||||||
dioxus_hot_reload::connect(move |template| {
|
dioxus_hot_reload::connect(move |msg| {
|
||||||
let _ = hot_reload_tx.send(template);
|
let _ = hot_reload_tx.send(msg);
|
||||||
});
|
});
|
||||||
hot_reload_rx
|
hot_reload_rx
|
||||||
};
|
};
|
||||||
@@ -232,7 +233,7 @@ fn render_vdom(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_templete = None;
|
let mut hot_reload_msg = None;
|
||||||
{
|
{
|
||||||
let wait = vdom.wait_for_work();
|
let wait = vdom.wait_for_work();
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||||
@@ -267,15 +268,22 @@ fn render_vdom(
|
|||||||
register_event(evt);
|
register_event(evt);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Some(template) = hot_reload_wait => {
|
Some(msg) = hot_reload_wait => {
|
||||||
new_templete = Some(template);
|
hot_reload_msg = Some(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we have a new template, replace the old one
|
// if we have a new template, replace the old one
|
||||||
if let Some(template) = new_templete {
|
if let Some(msg) = hot_reload_msg {
|
||||||
vdom.replace_template(template);
|
match msg {
|
||||||
|
HotReloadMsg::UpdateTemplate(template) => {
|
||||||
|
vdom.replace_template(template);
|
||||||
|
}
|
||||||
|
HotReloadMsg::Shutdown => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user