use futures::channel::oneshot::Sender;
use wasm_bindgen::{closure::Closure, JsCast, JsValue};
use web_sys::{ErrorEvent, MessageEvent, WebSocket};
pub(crate) fn connect_to_reload_server(live_reload_tx: Sender<()>) {
let mut live_reload_tx = Some(live_reload_tx);
let host = get_window_var("__PERSEUS_RELOAD_SERVER_HOST");
let port = get_window_var("__PERSEUS_RELOAD_SERVER_PORT");
let (host, port) = match (host, port) {
(Some(host), Some(port)) => (host, port),
_ => return,
};
let ws = match WebSocket::new(&format!("ws://{}:{}/receive", host, port)) {
Ok(ws) => ws,
Err(err) => return log(&format!("Connection failed: {:?}.", err)),
};
ws.set_binary_type(web_sys::BinaryType::Arraybuffer);
let onmessage_callback = Closure::wrap(Box::new(move |_| {
log("Reloading...");
match live_reload_tx.take() {
Some(tx) => { tx.send(()).unwrap(); },
None => log("Reload sender already invoked. It's likely that multiple reload events have occurred in too rapid succession. If the page does not reload in a matter of seconds, you should manually reload.")
}
}) as Box<dyn FnMut(MessageEvent)>);
ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
onmessage_callback.forget();
let onerror_callback = Closure::wrap(Box::new(move |err: ErrorEvent| {
log(&format!("Error: {:?}.", err));
}) as Box<dyn FnMut(ErrorEvent)>);
ws.set_onerror(Some(onerror_callback.as_ref().unchecked_ref()));
onerror_callback.forget();
let onopen_callback = Closure::wrap(Box::new(move |_| {
log("Connected.");
}) as Box<dyn FnMut(JsValue)>);
ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref()));
onopen_callback.forget();
}
fn get_window_var(name: &str) -> Option<String> {
let val_opt = web_sys::window().unwrap().get(name);
let js_obj = match val_opt {
Some(js_obj) => js_obj,
None => return None,
};
let state_str = match js_obj.as_string() {
Some(state_str) => state_str,
None => return None,
};
Some(state_str)
}
fn log(msg: &str) {
web_sys::console::log_1(&JsValue::from("[Live Reload Server]: ".to_string() + msg));
}
pub(crate) fn force_reload() {
web_sys::window()
.unwrap()
.location()
.reload_with_forceget(true)
.unwrap();
}