hardlounge/client/js/loading-error-handlers.js

129 lines
3.4 KiB
JavaScript
Raw Normal View History

"use strict";
/*
* This is a separate file for two reasons:
* 1. CSP policy does not allow inline javascript
* 2. It has to be a small javascript executed before all other scripts,
* so that the timeout can be triggered while slow JS is loading
*/
(function () {
2019-11-05 19:29:51 +00:00
const msg = document.getElementById("loading-page-message");
2018-07-13 07:43:31 +00:00
if (msg) {
msg.textContent = "Loading the app…";
}
document.getElementById("loading-reload")?.addEventListener("click", () => location.reload());
2019-11-05 19:29:51 +00:00
const displayReload = () => {
const loadingReload = document.getElementById("loading-reload");
if (loadingReload) {
2017-10-28 20:50:57 +00:00
loadingReload.style.visibility = "visible";
}
};
2019-11-05 19:29:51 +00:00
const loadingSlowTimeout = setTimeout(() => {
const loadingSlow = document.getElementById("loading-slow");
if (loadingSlow) {
loadingSlow.style.visibility = "visible";
}
2019-11-05 19:29:51 +00:00
displayReload();
}, 5000);
/**
* @param {ErrorEvent} e
**/
2019-11-05 19:29:51 +00:00
const errorHandler = (e) => {
if (!msg) {
return;
}
2019-11-05 19:29:51 +00:00
msg.textContent = "An error has occurred that prevented the client from loading correctly.";
2019-11-05 19:29:51 +00:00
const summary = document.createElement("summary");
summary.textContent = "More details";
2019-11-05 19:29:51 +00:00
const data = document.createElement("pre");
data.textContent = e.message; // e is an ErrorEvent
2019-11-05 19:29:51 +00:00
const info = document.createElement("p");
info.textContent = "Open the developer tools of your browser for more information.";
2019-11-05 19:29:51 +00:00
const details = document.createElement("details");
details.appendChild(summary);
details.appendChild(data);
details.appendChild(info);
msg.parentNode?.insertBefore(details, msg.nextSibling);
window.clearTimeout(loadingSlowTimeout);
displayReload();
};
2019-11-05 19:29:51 +00:00
window.addEventListener("error", errorHandler);
window.g_TheLoungeRemoveLoading = () => {
delete window.g_TheLoungeRemoveLoading;
window.clearTimeout(loadingSlowTimeout);
window.removeEventListener("error", errorHandler);
document.getElementById("loading")?.remove();
2019-11-05 19:29:51 +00:00
};
2019-12-06 09:56:12 +00:00
// Apply user theme as soon as possible, before any other code loads
// This prevents flash of white while other code loads and socket connects
try {
const userSettings = JSON.parse(localStorage.getItem("settings") || "{}");
2019-12-06 09:56:12 +00:00
const themeEl = document.getElementById("theme");
if (!themeEl) {
return;
}
2019-12-06 09:56:12 +00:00
if (
typeof userSettings.theme === "string" &&
themeEl?.dataset.serverTheme !== userSettings.theme
2019-12-06 09:56:12 +00:00
) {
themeEl.setAttribute("href", `themes/${userSettings.theme}.css`);
2019-12-06 09:56:12 +00:00
}
if (
typeof userSettings.userStyles === "string" &&
!/[?&]nocss/.test(window.location.search)
) {
const userSpecifiedCSSElement = document.getElementById("user-specified-css");
if (!userSpecifiedCSSElement) {
return;
}
userSpecifiedCSSElement.innerHTML = userSettings.userStyles;
2019-12-06 09:56:12 +00:00
}
} catch (e) {
//
}
// Trigger early service worker registration
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("service-worker.js");
// Handler for messages coming from the service worker
const messageHandler = (/** @type {MessageEvent} */ event) => {
if (event.data.type === "fetch-error") {
// @ts-expect-error Argument of type '{ message: string; }' is not assignable to parameter of type 'ErrorEvent'.
2019-11-05 19:29:51 +00:00
errorHandler({
message: `Service worker failed to fetch an url: ${event.data.message}`,
});
// Display only one fetch error
navigator.serviceWorker.removeEventListener("message", messageHandler);
}
};
navigator.serviceWorker.addEventListener("message", messageHandler);
}
})();