diff --git a/web_server.py b/web_server.py index a5970ab4..b3900a50 100644 --- a/web_server.py +++ b/web_server.py @@ -19071,6 +19071,15 @@ def get_version_info(): "title": "What's New in SoulSync", "subtitle": f"Version {SOULSYNC_VERSION} — Latest Changes", "sections": [ + { + "title": "🔧 Fix Wishlist Download Selection Ignoring Checkboxes", + "description": "Download Selection now respects which tracks are checked in the wishlist overview", + "features": [ + "• Selected track IDs are collected before closing the overview modal", + "• Only checked tracks are sent to the download analysis board", + "• If nothing is checked, downloads the full category (same as before)" + ] + }, { "title": "🔧 Fix Tidal OAuth Redirect URI in Docker", "description": "Tidal OAuth now uses the configured redirect URI instead of the Docker container hostname", diff --git a/webui/static/helper.js b/webui/static/helper.js index bf035727..4a6e9189 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3403,6 +3403,7 @@ function closeHelperSearch() { const WHATS_NEW = { '2.1': [ // Newest features first + { title: 'Fix Wishlist Download Selection', desc: 'Download Selection now only downloads checked tracks instead of the entire category' }, { title: 'Fix Tidal OAuth in Docker', desc: 'Tidal redirect URI now uses configured setting instead of Docker container hostname' }, { title: 'High-Res Cover Art', desc: 'Album art now sourced from Cover Art Archive (1200x1200+) when MusicBrainz release ID is available' }, { title: 'Embedded Lyrics', desc: 'Lyrics now embedded directly in audio file tags — Navidrome, Jellyfin, and Plex can display them' }, diff --git a/webui/static/script.js b/webui/static/script.js index 321a6e57..021a11d6 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -13039,11 +13039,15 @@ async function downloadSelectedCategory() { return; } + // Collect checked track IDs BEFORE closing the modal (checkboxes are destroyed on close) + const checkedBoxes = document.querySelectorAll('.wishlist-select-cb:checked'); + const selectedTrackIds = new Set(Array.from(checkedBoxes).map(cb => cb.dataset.trackId).filter(Boolean)); + closeWishlistOverviewModal(); - await openDownloadMissingWishlistModal(category); + await openDownloadMissingWishlistModal(category, selectedTrackIds.size > 0 ? selectedTrackIds : null); } -async function openDownloadMissingWishlistModal(category = null) { +async function openDownloadMissingWishlistModal(category = null, selectedTrackIds = null) { showLoadingOverlay('Loading wishlist...'); const playlistId = "wishlist"; // Use a consistent ID for wishlist @@ -13090,6 +13094,12 @@ async function openDownloadMissingWishlistModal(category = null) { const tracksData = await tracksResponse.json(); tracks = tracksData.tracks || []; + // Filter to only selected tracks if user made a selection + if (selectedTrackIds && selectedTrackIds.size > 0) { + tracks = tracks.filter(t => selectedTrackIds.has(t.id) || selectedTrackIds.has(t.spotify_track_id)); + console.log(`📥 Filtered to ${tracks.length} selected tracks (from ${tracksData.tracks?.length || 0} total)`); + } + } catch (error) { showToast(`Failed to fetch wishlist data: ${error.message}`, 'error'); hideLoadingOverlay();