export function initDevReloader(wsAddr, pollIntervalMs = 500) { // State model is implemented with variables and closures. let auto = true; let connected = false; let socket = undefined; let initialized = false; const button = document.createElement("button"); const indicator = document.createElement("div"); const label = document.createElement("div"); // Rolling our own reactivity: call this after state change to initialize or // update DOM view. function render() { button.style.appearance = "none"; button.style.background = "#fff"; button.style.border = "solid 1px #0002"; button.style.borderRadius = "999px"; button.style.padding = "1rem"; button.style.position = "fixed"; button.style.zIndex = "999"; button.style.bottom = "1rem"; button.style.left = "1rem"; button.style.opacity = "0.5"; button.style.boxShadow = "0 0.5rem 1rem #0002"; button.style.display = "flex"; button.style.cursor = "pointer"; button.style.alignItems = "center"; button.style.fontFamily = "sans-serif"; indicator.style.width = "8px"; indicator.style.height = "8px"; indicator.style.borderRadius = "999px"; indicator.style.background = connected ? "#06f" : "#f60"; label.style.marginLeft = "1rem"; label.innerText = auto ? "Disable auto-reload" : "Enable auto-reload"; } function toggleAuto() { auto = !auto; render(); } function handleDisconnect() { if (connected || !initialized) { console.log("dev-reloader: disconnected"); connected = false; socket = undefined; render(); const intvl = setInterval(function () { try { socket = new WebSocket(wsAddr); socket.addEventListener("open", function () { console.log("dev-reloader: connected"); clearInterval(intvl); if (auto && initialized) { globalThis.location.reload(); } connected = true; initialized = true; render(); }); socket.addEventListener("close", handleDisconnect); socket.addEventListener("error", handleDisconnect); } catch { /* no-op */ } }, pollIntervalMs); } } render(); button.setAttribute("type", "button"); button.addEventListener("click", toggleAuto); button.appendChild(indicator); button.appendChild(label); document.body.appendChild(button); // Simulate disconnect event to initialize. handleDisconnect(); }