91 lines
2.7 KiB
JavaScript
91 lines
2.7 KiB
JavaScript
// This used to be based on waiting for a websocket to disconnect, but that was
|
|
// flaky. Now we simply poll the shit out of the healthcheck endpoint.
|
|
export function initDevReloader(healthzAddr, pollIntervalMs = 500) {
|
|
// State model is implemented with variables and closures.
|
|
let auto = !!sessionStorage.getItem("__dev_reloader_auto");
|
|
let connected = false;
|
|
let initialized = false;
|
|
let interval;
|
|
|
|
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;
|
|
sessionStorage.setItem("__dev_reloader_auto", auto ? "present" : "");
|
|
if (auto && !interval) {
|
|
startInterval();
|
|
} else if (!auto && interval) {
|
|
clearInterval(interval);
|
|
interval = undefined;
|
|
connected = false;
|
|
initialized = false;
|
|
}
|
|
render();
|
|
}
|
|
|
|
function startInterval() {
|
|
interval = setInterval(function () {
|
|
fetch(healthzAddr)
|
|
.then(function () {
|
|
if (!connected) {
|
|
console.log("dev-reloader: connected");
|
|
if (auto && initialized) {
|
|
globalThis.location.reload();
|
|
}
|
|
connected = true;
|
|
initialized = true;
|
|
render();
|
|
}
|
|
})
|
|
.catch(function () {
|
|
if (connected) {
|
|
console.log("dev-reloader: disconnected");
|
|
connected = false;
|
|
render();
|
|
}
|
|
});
|
|
}, pollIntervalMs);
|
|
}
|
|
|
|
render();
|
|
|
|
button.setAttribute("type", "button");
|
|
button.addEventListener("click", toggleAuto);
|
|
button.appendChild(indicator);
|
|
button.appendChild(label);
|
|
document.body.appendChild(button);
|
|
|
|
if (auto) {
|
|
startInterval();
|
|
}
|
|
}
|