lib.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use std::{
  2. io::{BufRead, BufReader},
  3. path::PathBuf,
  4. };
  5. use dioxus_core::Template;
  6. #[cfg(feature = "file_watcher")]
  7. pub use dioxus_html::HtmlCtx;
  8. use interprocess::local_socket::LocalSocketStream;
  9. use serde::{Deserialize, Serialize};
  10. #[cfg(feature = "custom_file_watcher")]
  11. mod file_watcher;
  12. #[cfg(feature = "custom_file_watcher")]
  13. pub use file_watcher::*;
  14. /// A message the hot reloading server sends to the client
  15. #[derive(Debug, Serialize, Deserialize, Clone)]
  16. #[serde(bound(deserialize = "'de: 'static"))]
  17. pub enum HotReloadMsg {
  18. /// A template has been updated
  19. UpdateTemplate(Template),
  20. /// An asset discovered by rsx! has been updated
  21. UpdateAsset(PathBuf),
  22. /// The program needs to be recompiled, and the client should shut down
  23. Shutdown,
  24. }
  25. /// Connect to the hot reloading listener. The callback provided will be called every time a template change is detected
  26. pub fn connect(callback: impl FnMut(HotReloadMsg) + Send + 'static) {
  27. let Ok(_manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") else {
  28. return;
  29. };
  30. // get the cargo manifest directory, where the target dir lives
  31. let mut path = PathBuf::from(_manifest_dir);
  32. // walk the path until we a find a socket named `dioxusin` inside that folder's target directory
  33. loop {
  34. let maybe = path.join("target").join("dioxusin");
  35. if maybe.exists() {
  36. path = maybe;
  37. break;
  38. }
  39. // It's likely we're running under just cargo and not dx
  40. path = match path.parent() {
  41. Some(parent) => parent.to_path_buf(),
  42. None => return,
  43. };
  44. }
  45. connect_at(path, callback);
  46. }
  47. pub fn connect_at(socket: PathBuf, mut callback: impl FnMut(HotReloadMsg) + Send + 'static) {
  48. std::thread::spawn(move || {
  49. // There might be a socket since the we're not running under the hot reloading server
  50. let Ok(socket) = LocalSocketStream::connect(socket.clone()) else {
  51. println!(
  52. "could not find hot reloading server at {:?}, make sure it's running",
  53. socket
  54. );
  55. return;
  56. };
  57. let mut buf_reader = BufReader::new(socket);
  58. loop {
  59. let mut buf = String::new();
  60. if let Err(err) = buf_reader.read_line(&mut buf) {
  61. if err.kind() != std::io::ErrorKind::WouldBlock {
  62. break;
  63. }
  64. }
  65. let Ok(template) = serde_json::from_str(Box::leak(buf.into_boxed_str())) else {
  66. continue;
  67. };
  68. callback(template);
  69. }
  70. });
  71. }
  72. /// Start the hot reloading server with the current directory as the root
  73. #[macro_export]
  74. macro_rules! hot_reload_init {
  75. () => {
  76. #[cfg(debug_assertions)]
  77. dioxus_hot_reload::init(dioxus_hot_reload::Config::new().root(env!("CARGO_MANIFEST_DIR")));
  78. };
  79. ($cfg: expr) => {
  80. #[cfg(debug_assertions)]
  81. dioxus_hot_reload::init($cfg.root(env!("CARGO_MANIFEST_DIR")));
  82. };
  83. }