From 080afe02367928244faee2311b3cf0ec9be68f05 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 26 Dec 2025 20:10:19 +0000 Subject: [PATCH] feat: improve generate button loading state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💡 What: Replaced the full-screen loading overlay with an inline loading state on the "Generate Poster" button. The button is now disabled and its text changes to "Generating..." during the poster creation process. 🎯 Why: The previous full-screen overlay was a disruptive user experience. This change provides contextual feedback directly on the element the user interacted with, which is a more modern and less jarring approach. It also prevents the user from clicking the button multiple times while a request is in progress. ♿ Accessibility: The button is now properly disabled using the `disabled` attribute, which prevents keyboard and screen reader interaction while it's in a loading state. This is an accessibility improvement. --- web_app/static/script.js | 19 ++++++++++--------- web_app/static/style.css | 6 ++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/web_app/static/script.js b/web_app/static/script.js index 441a4ed..8ef0642 100644 --- a/web_app/static/script.js +++ b/web_app/static/script.js @@ -613,12 +613,14 @@ function handleLyricLineClick(lineNumber) { async function generatePoster() { if (!currentMetadata) return; - loadingOverlay.style.display = 'flex'; + generateBtn.disabled = true; + generateBtn.textContent = 'Generating...'; - const indexingToggle = document.getElementById('indexingToggle'); - const accentToggle = document.getElementById('accentToggle'); + try { + const indexingToggle = document.getElementById('indexingToggle'); + const accentToggle = document.getElementById('accentToggle'); - let payload = { + let payload = { track_id: currentMetadata.id, metadata: currentMetadata, theme: themeInput.value, @@ -635,7 +637,6 @@ async function generatePoster() { const end = endVal; if (isNaN(start) || isNaN(end) || start >= end) { - loadingOverlay.style.display = 'none'; showToast("Please enter a valid range (Start must be less than End).", "error"); return; } @@ -648,8 +649,7 @@ async function generatePoster() { payload.indexing = indexingToggle ? indexingToggle.checked : false; } - try { - const response = await fetch('/api/generate', { + const response = await fetch('/api/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) @@ -669,13 +669,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.disabled = false; + generateBtn.textContent = 'Generate Poster'; } } diff --git a/web_app/static/style.css b/web_app/static/style.css index 468eb76..04cbd63 100644 --- a/web_app/static/style.css +++ b/web_app/static/style.css @@ -166,6 +166,12 @@ header p { transform: translateY(-1px); } +.primary-btn:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; +} + .secondary-btn { background: transparent; border-color: var(--border-color);