phonograph/static/dev_reloader.mjs

82 lines
2.5 KiB
JavaScript
Raw Normal View History

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();
}