diff --git a/web_app/static/index.html b/web_app/static/index.html index 0d56371..4545a76 100644 --- a/web_app/static/index.html +++ b/web_app/static/index.html @@ -116,7 +116,10 @@

Lyrics

- + diff --git a/web_app/static/script.js b/web_app/static/script.js index 441a4ed..2de78e7 100644 --- a/web_app/static/script.js +++ b/web_app/static/script.js @@ -613,7 +613,8 @@ function handleLyricLineClick(lineNumber) { async function generatePoster() { if (!currentMetadata) return; - loadingOverlay.style.display = 'flex'; + generateBtn.classList.add('loading'); + generateBtn.disabled = true; const indexingToggle = document.getElementById('indexingToggle'); const accentToggle = document.getElementById('accentToggle'); @@ -635,7 +636,8 @@ async function generatePoster() { const end = endVal; if (isNaN(start) || isNaN(end) || start >= end) { - loadingOverlay.style.display = 'none'; + generateBtn.classList.remove('loading'); + generateBtn.disabled = false; showToast("Please enter a valid range (Start must be less than End).", "error"); return; } @@ -669,13 +671,14 @@ async function generatePoster() { posterContainer.innerHTML = ''; posterContainer.appendChild(img); showDownloadButton(imageUrl, data.filename); - loadingOverlay.style.display = 'none'; }; } catch (error) { console.error("Generation failed", error); showToast(`Error: ${error.message}`, "error"); - loadingOverlay.style.display = 'none'; + } finally { + generateBtn.classList.remove('loading'); + generateBtn.disabled = false; } } diff --git a/web_app/static/style.css b/web_app/static/style.css index 468eb76..a69f565 100644 --- a/web_app/static/style.css +++ b/web_app/static/style.css @@ -140,6 +140,7 @@ header p { /* Buttons */ .primary-btn, .secondary-btn { + position: relative; /* For spinner positioning */ display: inline-flex; align-items: center; justify-content: center; @@ -166,6 +167,31 @@ header p { transform: translateY(-1px); } +.primary-btn.loading { + cursor: wait; + color: transparent; + pointer-events: none; +} + +.primary-btn .spinner { + display: none; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 20px; + height: 20px; + margin: 0; + border: 2px solid #1a1a1f; + border-top-color: transparent; + border-radius: 50%; + animation: spin 0.6s linear infinite; +} + +.primary-btn.loading .spinner { + display: block; +} + .secondary-btn { background: transparent; border-color: var(--border-color);