From ecc07c681151a68649f7ab275c2fb13f622fbf30 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sat, 13 Jun 2026 10:58:29 -0700 Subject: [PATCH] #867 UX (real fix): render Tidal discovery modal BEFORE the blocking discovery-start POST MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prior UX commit removed a redundant frontend pre-fetch, but the modal was still only opened at the END of openTidalDiscoveryModal — AFTER awaiting /api/tidal/discovery/start, whose backend handler fetches the whole playlist synchronously (Tidal sleeps 1s/page, ~10s) before responding. So the modal still didn't appear for ~10s. Now open the modal first (with a 'Loading playlist from Tidal…' note), then fire the discovery-start POST and begin polling; return early so the shared open at the bottom is skipped for this path. --- webui/static/sync-services.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/webui/static/sync-services.js b/webui/static/sync-services.js index cf3f8f86..f8445edd 100644 --- a/webui/static/sync-services.js +++ b/webui/static/sync-services.js @@ -540,6 +540,17 @@ async function openTidalDiscoveryModal(playlistId, playlistData) { // Only start discovery if not already discovered AND not currently discovering if (!isAlreadyDiscovered && !isCurrentlyDiscovering) { + // Open the modal FIRST so it appears instantly. The discovery-start POST + // below fetches the ENTIRE playlist server-side before it responds (Tidal + // sleeps 1s per page → ~10s for a large playlist). Previously the modal + // was only opened AFTER this await, so the user stared at nothing for those + // ~10s. Now the modal shows immediately with a loading note and tracks + // stream in once discovery starts. We return early so the shared open at + // the bottom isn't reached for this path. (#867 UX) + openYouTubeDiscoveryModal(fakeUrlHash); + const _descEl = document.querySelector(`#youtube-discovery-modal-${fakeUrlHash} .modal-description`); + if (_descEl) _descEl.textContent = 'Loading playlist from Tidal…'; + // Start Tidal discovery process automatically (like sync.py) try { console.log(`🔍 Starting Tidal discovery for: ${playlistData.name}`); @@ -553,10 +564,12 @@ async function openTidalDiscoveryModal(playlistId, playlistData) { if (result.error) { console.error('❌ Error starting Tidal discovery:', result.error); showToast(`Error starting discovery: ${result.error}`, 'error'); + if (_descEl) _descEl.textContent = 'Could not start discovery.'; return; } console.log('✅ Tidal discovery started, beginning polling...'); + if (_descEl) _descEl.textContent = 'Discovering tracks…'; // Update phase to discovering now that backend discovery is actually started tidalPlaylistStates[playlistId].phase = 'discovering'; @@ -571,7 +584,9 @@ async function openTidalDiscoveryModal(playlistId, playlistData) { } catch (error) { console.error('❌ Error starting Tidal discovery:', error); showToast(`Error starting discovery: ${error.message}`, 'error'); + if (_descEl) _descEl.textContent = 'Could not start discovery.'; } + return; } else if (isCurrentlyDiscovering) { // Resume polling if discovery is already in progress (like YouTube) console.log(`🔄 Resuming Tidal discovery polling for: ${playlistData.name}`);