use crate::server::HotReloadState;
use axum::{
extract::{
ws::{Message, WebSocket},
WebSocketUpgrade,
},
response::IntoResponse,
Extension,
};
use dioxus_hot_reload::HotReloadMsg;
use futures_util::{pin_mut, FutureExt};
pub async fn hot_reload_handler(
ws: WebSocketUpgrade,
Extension(state): Extension<HotReloadState>,
) -> impl IntoResponse {
ws.on_upgrade(|socket| async move {
let err = hotreload_loop(socket, state).await;
if let Err(err) = err {
tracing::error!("Hotreload receiver failed: {}", err);
}
})
}
async fn hotreload_loop(mut socket: WebSocket, state: HotReloadState) -> anyhow::Result<()> {
tracing::info!("🔥 Hot Reload WebSocket connected");
for template in state.all_templates() {
socket
.send(Message::Text(serde_json::to_string(&template).unwrap()))
.await?;
}
let mut rx = state.messages.subscribe();
loop {
let msg = {
let mut _socket = socket.recv().fuse();
let mut _rx = rx.recv().fuse();
pin_mut!(_socket, _rx);
let msg = futures_util::select! {
msg = _rx => msg,
e = _socket => {
if let Some(Err(e)) = e {
tracing::info!("🔥 Hot Reload WebSocket Error: {}", e);
} else {
tracing::info!("🔥 Hot Reload WebSocket Closed");
}
break;
},
};
let Ok(msg) = msg else { break };
match msg {
HotReloadMsg::UpdateTemplate(template) => {
Message::Text(serde_json::to_string(&template).unwrap())
}
HotReloadMsg::UpdateAsset(asset) => {
Message::Text(format!("reload-asset: {}", asset.display()))
}
HotReloadMsg::Shutdown => {
tracing::info!("🔥 Hot Reload WebSocket shutting down");
break;
}
}
};
socket.send(msg).await?;
}
Ok(())
}