lib.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. #[cfg(feature = "serve")]
  15. mod websocket;
  16. #[cfg(feature = "serve")]
  17. pub use websocket::*;
  18. #[cfg(feature = "serve")]
  19. /// The script to inject into the page to reconnect to server if the connection is lost
  20. pub const RECONNECT_SCRIPT: &str = include_str!("assets/autoreload.js");
  21. /// A message the hot reloading server sends to the client
  22. #[derive(Debug, Serialize, Deserialize, Clone)]
  23. #[serde(bound(deserialize = "'de: 'static"))]
  24. pub enum HotReloadMsg {
  25. /// A template has been updated
  26. UpdateTemplate(Template),
  27. /// An asset discovered by rsx! has been updated
  28. UpdateAsset(PathBuf),
  29. /// The program needs to be recompiled, and the client should shut down
  30. Shutdown,
  31. }
  32. /// Connect to the hot reloading listener. The callback provided will be called every time a template change is detected
  33. pub fn connect(callback: impl FnMut(HotReloadMsg) + Send + 'static) {
  34. if cfg!(windows) {
  35. connect_at(PathBuf::from("@dioxusin"), callback);
  36. } else {
  37. // FIXME: this is falling back onto the current directory when not running under cargo, which is how the CLI runs this.
  38. // This needs to be fixed.
  39. let _manifest_dir = std::env::var("CARGO_MANIFEST_DIR");
  40. // get the cargo manifest directory, where the target dir lives
  41. let mut path = match _manifest_dir {
  42. Ok(manifest_dir) => PathBuf::from(manifest_dir),
  43. Err(_) => std::env::current_dir().unwrap(),
  44. };
  45. // walk the path until we a find a socket named `dioxusin` inside that folder's target directory
  46. loop {
  47. let maybe = path.join("target").join("dioxusin");
  48. if maybe.exists() {
  49. path = maybe;
  50. break;
  51. }
  52. // It's likely we're running under just cargo and not dx
  53. path = match path.parent() {
  54. Some(parent) => parent.to_path_buf(),
  55. None => return,
  56. };
  57. }
  58. println!("connecting to {:?}", path);
  59. connect_at(path, callback);
  60. }
  61. }
  62. pub fn connect_at(socket: PathBuf, mut callback: impl FnMut(HotReloadMsg) + Send + 'static) {
  63. std::thread::spawn(move || {
  64. // There might be a socket since the we're not running under the hot reloading server
  65. let stream = if cfg!(windows) {
  66. LocalSocketStream::connect("@dioxusin")
  67. } else {
  68. LocalSocketStream::connect(socket.clone())
  69. };
  70. let Ok(socket) = stream else {
  71. println!(
  72. "could not find hot reloading server at {:?}, make sure it's running",
  73. socket
  74. );
  75. return;
  76. };
  77. let mut buf_reader = BufReader::new(socket);
  78. loop {
  79. let mut buf = String::new();
  80. if let Err(err) = buf_reader.read_line(&mut buf) {
  81. if err.kind() != std::io::ErrorKind::WouldBlock {
  82. break;
  83. }
  84. }
  85. let Ok(template) = serde_json::from_str(Box::leak(buf.into_boxed_str())) else {
  86. continue;
  87. };
  88. callback(template);
  89. }
  90. });
  91. }
  92. /// Start the hot reloading server with the current directory as the root
  93. #[macro_export]
  94. macro_rules! hot_reload_init {
  95. () => {
  96. #[cfg(debug_assertions)]
  97. dioxus_hot_reload::init(dioxus_hot_reload::Config::new().root(env!("CARGO_MANIFEST_DIR")));
  98. };
  99. ($cfg: expr) => {
  100. #[cfg(debug_assertions)]
  101. dioxus_hot_reload::init($cfg.root(env!("CARGO_MANIFEST_DIR")));
  102. };
  103. }