use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
use winit::window::Window;
static PATCHED: AtomicBool = AtomicBool::new(false);
static WINDOW: Mutex<Option<Arc<Window>>> = Mutex::new(None);
pub(crate) fn connect() {
dioxus_devtools::subsecond::register_handler(Arc::new(|| {
PATCHED.store(true, Ordering::SeqCst);
log::info!("hot reload: patch applied");
if let Ok(window) = WINDOW.lock() {
if let Some(window) = window.as_ref() {
window.request_redraw();
}
}
}));
#[cfg(target_os = "android")]
engine_settings();
#[cfg(not(target_arch = "wasm32"))]
dioxus_devtools::connect_subsecond();
#[cfg(target_arch = "wasm32")]
connect_page();
}
#[cfg(target_arch = "wasm32")]
fn connect_page() {
use wasm_bindgen::closure::Closure;
let Some(window) = web_sys::window() else {
return;
};
let apply = Closure::<dyn FnMut(String)>::new(apply_message);
let _ = js_sys::Reflect::set(&window, &"__frusPatch".into(), apply.as_ref());
apply.forget();
}
#[cfg(target_arch = "wasm32")]
fn apply_message(text: String) {
use dioxus_devtools::DevserverMsg;
let text: &'static str = Box::leak(text.into_boxed_str());
let Ok(DevserverMsg::HotReload(message)) = serde_json::from_str::<DevserverMsg>(text) else {
return;
};
if message.for_build_id.is_some_and(|id| id != 0) {
return;
}
if let Some(table) = message.jump_table {
static APPLIED: Mutex<Vec<std::path::PathBuf>> = Mutex::new(Vec::new());
if let Ok(mut applied) = APPLIED.lock() {
if applied.contains(&table.lib) {
return;
}
applied.push(table.lib.clone());
}
if let Err(error) = unsafe { dioxus_devtools::subsecond::apply_patch(table) } {
log::warn!("hot reload: the patch could not be applied: {error:?}");
}
}
}
#[cfg(target_os = "android")]
const ENGINE_SETTINGS: &str = "/data/local/tmp/dx/.env";
#[cfg(target_os = "android")]
fn engine_settings() {
let Ok(text) = std::fs::read_to_string(ENGINE_SETTINGS) else {
return;
};
for line in text.lines() {
if let Some((key, value)) = line.split_once('=') {
std::env::set_var(key.trim(), value.trim());
}
}
}
#[cfg(target_os = "android")]
pub(crate) fn under_engine() -> bool {
std::path::Path::new(ENGINE_SETTINGS).is_file()
}
pub(crate) fn set_window(window: Arc<Window>) {
if let Ok(mut slot) = WINDOW.lock() {
*slot = Some(window);
}
}
pub(crate) fn take_patched() -> bool {
PATCHED.swap(false, Ordering::SeqCst)
}