diff --git a/web_server.py b/web_server.py index 49999570..4b3a2447 100644 --- a/web_server.py +++ b/web_server.py @@ -8294,6 +8294,7 @@ def start_wishlist_missing_downloads(): data = request.get_json() or {} force_download_all = data.get('force_download_all', False) category = data.get('category') # Get category filter (albums or singles) + track_ids = data.get('track_ids') # NEW: Get specific track IDs from frontend from core.wishlist_service import get_wishlist_service from database.music_database import MusicDatabase @@ -8371,8 +8372,21 @@ def start_wishlist_missing_downloads(): print(f"🔧 [Manual-Wishlist] Sanitized {len(wishlist_tracks)} tracks from wishlist service") - # FILTER BY CATEGORY if specified (same logic as auto-processing) - if category: + # FILTER BY TRACK IDs if specified (prioritized - prevents race conditions) + if track_ids: + # Convert to set for O(1) lookup + track_id_set = set(track_ids) + filtered_tracks = [] + for track in wishlist_tracks: + spotify_track_id = track.get('spotify_track_id') or track.get('id') + if spotify_track_id in track_id_set: + filtered_tracks.append(track) + + wishlist_tracks = filtered_tracks + print(f"🎯 [Manual-Wishlist] Filtered to {len(wishlist_tracks)} specific tracks by ID (preventing race condition)") + + # FILTER BY CATEGORY if specified and no track_ids (backward compatibility) + elif category: import json filtered_tracks = [] for track in wishlist_tracks: diff --git a/webui/static/script.js b/webui/static/script.js index 8e7c5342..048b56e7 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -5529,12 +5529,18 @@ async function startWishlistMissingTracksProcess(playlistId) { forceToggleContainer.style.display = 'none'; } + // Extract track IDs from what the user is currently seeing in the modal + // This prevents race conditions where wishlist changes between modal open and analysis start + const trackIds = process.tracks ? process.tracks.map(t => t.spotify_track_id || t.id).filter(id => id) : null; + console.log(`🎯 [Wishlist] Sending ${trackIds ? trackIds.length : 'all'} specific track IDs to prevent race condition`); + const response = await fetch('/api/wishlist/download_missing', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ force_download_all: forceDownloadAll, - category: window.currentWishlistCategory // Pass category to backend + category: window.currentWishlistCategory, // Keep for backward compat + track_ids: trackIds // NEW: Send exact tracks to process }) });