- Clamp alreadyOwned to Math.max(0, ...) in batch completion display
to avoid showing negative owned count
- Map active_source deezer to deezer_track_id in both seasonal
playlist endpoints (current-playlist and curated), consistent
with core/seasonal_discovery.py logic
Adds a full Discover Sync tab to the Sync page with:
- Core UI scaffolding, playlist modal, empty-state handling
- ListenBrainz playlist integration with auto-update toggle persistence
- Sync progress tracking with matched/total counts on cards
- Navidrome playlist push on batch completion (V1 and V2 paths)
- Active download state display with polling resume on page reload
- Stuck-download detection for downloading and catch-all states
- Serialized sync queue to prevent concurrent backend contention
- Source badges, compact card layout, URL fixes
Replace generic music note placeholder with discover-specific emojis
based on playlist name (Fresh Tape=note, Archives=books, Seasonal=leaf,
Popular=fire, Hidden Gems=gem, etc.) with source-based fallbacks
for mirrored/wishlist/album entries.
- Queue batches for analysis instead of rejecting with 429
- Route all batch submissions through analysis queue
- Separate analysis executor to prevent thread starvation
- Expand batch color palette from 8 to 16 sequential colors
- Add queued phase display in batch panel
Adds a full Discover Sync tab to the Sync page with:
- Core UI scaffolding, playlist modal, empty-state handling
- ListenBrainz playlist integration with auto-update toggle persistence
- Sync progress tracking with matched/total counts on cards
- Navidrome playlist push on batch completion (V1 and V2 paths)
- Active download state display with polling resume on page reload
- Stuck-download detection for downloading and catch-all states
- Serialized sync queue to prevent concurrent backend contention
- Source badges, compact card layout, URL fixes