soulsync/webui/static
BoulderBadgeDad 6bc2836f47 Feature: preferred album-art source selection (opt-in, ordered, with fallback)
Lets users pick which providers' cover art to use and in what priority,
generalizing the single prefer_caa_art toggle into an ordered, mix-and-match
list (Sokhi's request). Fully opt-in: default album_art_order is [], so every
existing install is byte-for-byte unchanged until the user enables sources.

How it works:
- Per album, walk the user's ordered sources top-to-bottom; the first source
  that actually has THIS album's cover wins. A miss falls through to the next;
  if all miss, the download's own art is kept (today's default). The worst case
  is always exactly the cover you'd get today -- never wrong art, never an
  error into the download.
- Connection-gated: a source is only tried when the user is connected to it
  (free sources CAA/Deezer/iTunes/AudioDB always; Spotify only when
  authenticated). Tidal/Qobuz/HiFi deferred (cover-URL construction + no clean
  core accessor -- not shipping unverified extraction).
- Album-match validated: a source's art is used only when the album it returns
  matches the requested artist+album (significant-token subset, tolerant of
  Deluxe/Remastered/articles/feat./multi-artist). A loose top search hit for a
  different record is treated as a miss -> guarantees no wrong-album art.
- The list supersedes the legacy prefer_caa_art toggle: when album_art_order is
  non-empty it is the sole authority (add 'caa' to the list to use Cover Art
  Archive), and prefer_caa_art is neutralized for both the embedded-tag art and
  cover.jpg paths. With an empty list, prefer_caa_art behaves exactly as before.

Implementation:
- core/metadata/art_sources.py: pure resolver -- effective_art_order (config +
  legacy back-compat) and resolve_cover_art (ordered walk + fallback,
  exception-safe per source). No network/config/DB; fully unit-testable.
- core/metadata/art_lookup.py: availability gating, per-source lookups against
  existing clients (Deezer/iTunes/AudioDB/Spotify search + CAA via MBID),
  album-match validation, per-album caching, and select_preferred_art_url --
  the single gate the pipeline calls (no-op unless an explicit list is set).
- core/metadata/artwork.py: wired into embed_album_art_metadata and
  download_cover_art, gated so no configured list == current behavior.
- web_server.py: GET /api/metadata/art-sources (connected sources only).
- config/settings.py: default album_art_order: [].
- webui (index.html + settings.js): reorderable list in Core Features reusing
  the hybrid-source-list pattern + real service logos (with emoji fallback);
  load/save wired through the existing metadata_enhancement settings flow.
  loadArtSourceOrder populates the saved order synchronously (filtered to known
  sources, not availability) so a save before the availability fetch resolves,
  or a temporarily-disconnected source, can never wipe the saved order.

Tests: 40 unit/seam tests (resolver ordering/fallback/back-compat, availability,
per-source extraction, album-match validation incl. wrong-album/wrong-artist
rejection, caching, exception-safety, the off-by-default gate). Full metadata
suite still green (610 passed) -- the gated integration changes nothing when no
list is configured.

Note: the settings UI (DOM-heavy, not unit-testable in the JS harness) and the
live per-source art-fetch quality are validated by manual testing.
2026-06-01 11:45:07 -07:00
..
docs
vendor
amazon.svg
api-monitor.js Dashboard: round Last.fm avatar, invert dark-mark logos (Tidal/Qobuz/Discogs/Amazon) 2026-05-27 19:32:32 -07:00
artists.png
audiodb.png Dashboard: equalizer bars now show real brand logos in the avatar disc 2026-05-27 19:22:28 -07:00
auto-sync.js Auto-Sync sidebar: brand logo on each source-group header 2026-05-27 20:23:12 -07:00
automation.png
basic-search-v2.css Basic search: visual overhaul + per-source picker in hybrid mode 2026-05-28 10:22:07 -07:00
beatport-ui.js
core.js Persist completed downloads in downloads view 2026-05-24 10:02:00 -07:00
dashboard.png
discover-section-controller.js
discover.js UI: migrate remaining compact button families to the .btn--sm tier 2026-05-29 11:40:31 -07:00
discover.png
docs-images-needed.md
docs.js
downloads.js Track-detail modal: click any download row for a rich, status-aware view 2026-05-31 20:24:37 -07:00
enrichment.js
explorer.png
favicon.png
help.png
helper.js Basic search: visual overhaul + per-source picker in hybrid mode 2026-05-28 10:22:07 -07:00
hydrabase.png
import.png
init.js UI: migrate remaining compact button families to the .btn--sm tier 2026-05-29 11:40:31 -07:00
library.js Player: 'Play next' action + accent-correct queue buttons 2026-05-30 14:54:14 -07:00
library.png
manifest.json
media-player.js Player: seek hover tooltip on the Now Playing progress bar 2026-05-30 15:15:58 -07:00
mobile.css Standardize artist-detail hero action buttons 2026-05-28 12:35:02 -07:00
pages-extra.js Batches panel: redesign expanded track rows + fix scrollbar clipping 2026-05-31 22:44:58 -07:00
particles.js
placeholder-album.png
pwa-icon-192.png
pwa-icon-512.png
search.js Search: bump live-search debounce 300ms -> 600ms (#751) 2026-05-30 15:34:34 -07:00
search.png
settings.js Feature: preferred album-art source selection (opt-in, ordered, with fallback) 2026-06-01 11:45:07 -07:00
settings.png
setup-wizard.css
setup-wizard.js
shared-helpers.js refactor(webui): finish stats standalone handling in react 2026-05-23 23:01:56 +03:00
shell-bridge.js refactor(webui): finish stats standalone handling in react 2026-05-23 23:01:56 +03:00
stats-automations.js Mirrored playlist modal: revamp + fix header clipping on long playlists 2026-06-01 09:31:20 -07:00
style.css Mirrored playlist modal: revamp + fix header clipping on long playlists 2026-06-01 09:31:20 -07:00
sw.js
sync-lastfm.js Add Last.fm Radio tab to Sync page (Phase 1c.2) 2026-05-26 15:24:23 -07:00
sync-listenbrainz.js Add Last.fm Radio tab to Sync page (Phase 1c.2) 2026-05-26 15:24:23 -07:00
sync-services.js Tools: add Deep Scan option to the Database Updater 2026-05-29 10:47:02 -07:00
sync-soulsync-discovery.js SoulSync Discovery tab: open mirror detail modal after refresh 2026-05-26 20:02:50 -07:00
sync-spotify.js feat(media-player): playable tracks across modals + lyrics + cleanups 2026-05-22 21:19:50 -07:00
sync.png
track-detail.js Track-detail modal: click any download row for a rich, status-aware view 2026-05-31 20:24:37 -07:00
trans.png
trans2.png
whisoul.png
wishlist-tools.js Merge pull request #594 from Skowll/telegram_thread_id 2026-05-26 11:47:08 -07:00
worker-orbs.js