rkgk/static/connection-status.js
liquidex 0d831698e2 add proper error and disconnect handling
error handling shows you the error and offers the ability to reload;
disconnect handling shows you that the page will reload in a few seconds.
it uses exponential backoff with some random sprinkled into it to prevent overwhelming the server once people's clients decide to reconnect.
2024-08-25 12:55:07 +02:00

68 lines
2.5 KiB
JavaScript

export class ConnectionStatus extends HTMLElement {
connectedCallback() {
this.loggingInDialog = this.querySelector("dialog[name='logging-in-dialog']");
this.loggingInThrobber = this.loggingInDialog.querySelector("rkgk-throbber");
// This is a progress dialog and shouldn't be closed.
this.loggingInDialog.addEventListener("cancel", (event) => event.preventDefault());
this.errorDialog = this.querySelector("dialog[name='error-dialog']");
this.errorText = this.errorDialog.querySelector("[name='error-text']");
this.errorRefresh = this.errorDialog.querySelector("button[name='refresh']");
// If this appears then something broke, and therefore the app can't continue normally.
this.errorDialog.addEventListener("cancel", (event) => event.preventDefault());
this.errorRefresh.addEventListener("click", () => {
window.location.reload();
});
this.disconnectedDialog = this.querySelector("dialog[name='disconnected-dialog']");
this.reconnectDuration = this.disconnectedDialog.querySelector(
"[name='reconnect-duration']",
);
// If this appears then we can't let the user use the app, because we're disconnected.
this.disconnectedDialog.addEventListener("cancel", (event) => event.preventDefault());
}
showLoggingIn() {
this.loggingInDialog.showModal();
}
hideLoggingIn() {
this.loggingInDialog.close();
}
showError(error) {
this.errorDialog.showModal();
if (error instanceof Error) {
if (error.stack != null && error.stack != "") {
this.errorText.textContent = `${error.toString()}\n\n${error.stack}`;
} else {
this.errorText.textContent = error.toString();
}
}
}
async showDisconnected(duration) {
this.disconnectedDialog.showModal();
let updateDuration = (remaining) => {
let seconds = Math.floor(remaining / 1000);
this.reconnectDuration.textContent = `${seconds} ${seconds == 1 ? "second" : "seconds"}`;
};
let remaining = duration;
updateDuration(remaining);
while (remaining > 0) {
let delay = Math.min(1000, remaining);
remaining -= delay;
updateDuration(remaining);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
customElements.define("rkgk-connection-status", ConnectionStatus);