From 138918995b287d00c82e729e6279f63d86725256 Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Tue, 30 Dec 2025 20:57:54 +0100 Subject: [PATCH] feat: add gentle loading fallback after 3 seconds If no lesson loads within 3 seconds, show a centered, gray notice with fade-in animation suggesting to select from menu or check help. Includes link to help dialog. --- src/app.js | 29 ++++++++++++++++++++++++++++- src/i18n.js | 2 ++ src/main.css | 17 +++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/app.js b/src/app.js index 67180fc..26a183d 100644 --- a/src/app.js +++ b/src/app.js @@ -238,6 +238,29 @@ function restoreLessonCache() { // ================= MODULE INITIALIZATION ================= +let loadingTimeout = null; + +function showLoadingFallback() { + // Only show if no lesson is loaded yet + if (!elements.lessonTitle.textContent) { + elements.lessonDescription.innerHTML = ` +
+

${t("loadingFallbackText")}

+ +
+ `; + } +} + +function clearLoadingTimeout() { + if (loadingTimeout) { + clearTimeout(loadingTimeout); + loadingTimeout = null; + } +} + async function initializeModules() { try { const modules = await loadModules(getLanguage()); @@ -257,9 +280,10 @@ async function initializeModules() { } updateProgressDisplay(); + clearLoadingTimeout(); } catch (error) { console.error("Failed to load modules:", error); - elements.lessonDescription.textContent = t("failedToLoad"); + showLoadingFallback(); } } @@ -656,6 +680,9 @@ function init() { // Initialize CodeMirror editor initCodeEditor(); + // Set timeout to show fallback if loading takes too long + loadingTimeout = setTimeout(showLoadingFallback, 3000); + // Load modules after editor is ready initializeModules().catch(console.error); diff --git a/src/i18n.js b/src/i18n.js index 63977bc..f8e802c 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -87,6 +87,7 @@ const translations = { resetAll: "Reset All", // Dynamic content + loadingFallbackText: "Could not load lesson. Please select one from the menu or check the help.", completed: "Completed", successMessage: "CRISPY! ٩(◕‿◕)۶ Your code works correctly.", keepTrying: "Keep trying!", @@ -180,6 +181,7 @@ const translations = { resetAll: "Alles zurücksetzen", // Dynamic content + loadingFallbackText: "Lektion konnte nicht geladen werden. Bitte wähle eine aus dem Menü oder prüfe die Hilfe.", completed: "Erledigt", successMessage: "CRISPY! ٩(◕‿◕)۶ Dein Code funktioniert.", keepTrying: "Weiter versuchen!", diff --git a/src/main.css b/src/main.css index f2c13e5..9c3afdf 100644 --- a/src/main.css +++ b/src/main.css @@ -241,6 +241,23 @@ code, kbd { opacity: 0.3; } +/* Loading fallback notice */ +.loading-fallback { + text-align: center; + padding: 3rem 1rem; + color: var(--light-text); + animation: fadeIn 0.5s ease; +} + +.loading-fallback p { + margin-bottom: 1rem; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + .module-pill { display: inline-flex; align-items: center;