1use std::{
2 io::{BufRead, BufReader},
3 path::PathBuf,
4};
5
6use dioxus_core::Template;
7#[cfg(feature = "file_watcher")]
8pub use dioxus_html::HtmlCtx;
9use interprocess::local_socket::LocalSocketStream;
10use serde::{Deserialize, Serialize};
11
12#[cfg(feature = "custom_file_watcher")]
13mod file_watcher;
14#[cfg(feature = "custom_file_watcher")]
15pub use file_watcher::*;
16
17#[derive(Debug, Serialize, Deserialize, Clone)]
19#[serde(bound(deserialize = "'de: 'static"))]
20pub enum HotReloadMsg {
21 UpdateTemplate(Template),
23
24 UpdateAsset(PathBuf),
26
27 Shutdown,
29}
30
31pub fn connect(callback: impl FnMut(HotReloadMsg) + Send + 'static) {
33 if cfg!(windows) {
34 connect_at(PathBuf::from("@dioxusin"), callback);
35 } else {
36 let _manifest_dir = std::env::var("CARGO_MANIFEST_DIR");
39
40 let mut path = match _manifest_dir {
42 Ok(manifest_dir) => PathBuf::from(manifest_dir),
43 Err(_) => std::env::current_dir().unwrap(),
44 };
45
46 loop {
48 let maybe = path.join("target").join("dioxusin");
49
50 if maybe.exists() {
51 path = maybe;
52 break;
53 }
54
55 path = match path.parent() {
57 Some(parent) => parent.to_path_buf(),
58 None => return,
59 };
60 }
61
62 println!("connecting to {:?}", path);
63 connect_at(path, callback);
64 }
65}
66
67pub fn connect_at(socket: PathBuf, mut callback: impl FnMut(HotReloadMsg) + Send + 'static) {
68 std::thread::spawn(move || {
69 let stream = if cfg!(windows) {
71 LocalSocketStream::connect("@dioxusin")
72 } else {
73 LocalSocketStream::connect(socket.clone())
74 };
75 let Ok(socket) = stream else {
76 println!(
77 "could not find hot reloading server at {:?}, make sure it's running",
78 socket
79 );
80 return;
81 };
82
83 let mut buf_reader = BufReader::new(socket);
84
85 loop {
86 let mut buf = String::new();
87
88 if let Err(err) = buf_reader.read_line(&mut buf) {
89 if err.kind() != std::io::ErrorKind::WouldBlock {
90 break;
91 }
92 }
93
94 let Ok(template) = serde_json::from_str(Box::leak(buf.into_boxed_str())) else {
95 continue;
96 };
97
98 callback(template);
99 }
100 });
101}
102
103#[macro_export]
105macro_rules! hot_reload_init {
106 () => {
107 #[cfg(debug_assertions)]
108 dioxus_hot_reload::init(dioxus_hot_reload::Config::new().root(env!("CARGO_MANIFEST_DIR")));
109 };
110
111 ($cfg: expr) => {
112 #[cfg(debug_assertions)]
113 dioxus_hot_reload::init($cfg.root(env!("CARGO_MANIFEST_DIR")));
114 };
115}