Skip to content

feat(v3 library): searchable Cover Art Archive picker in Change-cover#783

Merged
byrongamatos merged 1 commit into
mainfrom
feat/v3-cover-search
Jul 5, 2026
Merged

feat(v3 library): searchable Cover Art Archive picker in Change-cover#783
byrongamatos merged 1 commit into
mainfrom
feat/v3-cover-search

Conversation

@ChrisBeWithYou

@ChrisBeWithYou ChrisBeWithYou commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Adds a search box to the Change-cover picker so you can find an album cover even for a song with no metadata match (stacked on #782 → the metadata-curation capstone).

The gap

/art/candidates only offers CAA covers from a song's matched release — so the ~640 unmatched city-pop packs got nothing but Current / Pack / Upload / Paste-URL.

The fix

  • Backend: GET /api/song/{fn}/art/cover-search?q=_mb_search_release_groups(q) searches MusicBrainz /release-group (reusing the throttled _mb_http_get) and maps each album to its Cover Art Archive front thumb (coverartarchive.org/release-group/{id}/front-250). q defaults to the song's own artist + album/title (with the romaji fallback applied), so a blank-artist pack pre-fills a sensible query.
  • Frontend: a "Search covers" row in the picker (pre-filled), → a grid of album-cover tiles → click to apply through the existing /art/url path. Albums with no CAA art self-hide (img onerror), same as the auto candidates. The three __fbOpenImagePicker callers now pass artist/album for the pre-fill.

Verified live

Default query "Junko Yagami BAY CITY" → 8 albums; the thumbs resolve to real images (200 image/jpeg). Read-only search; a pick reuses the existing reversible art-override route (files untouched).

Known limitation: MusicBrainz release-group text search is fuzzy, so a few unrelated albums can appear — you pick the right one visually by its cover (the natural cover-picker interaction). Can tighten to an artist-constrained query if it proves noisy.

Stacked on #782. node --check clean across the three touched modules; server.py parses.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added cover art search in the cover picker, letting you look up matching covers before choosing one.
    • Improved cover art selection across songs and review screens with more song details prefilled for better search results.
  • Bug Fixes
    • Blank or missing cover search terms now return an empty result instead of an error.
    • Search failures now show a graceful unavailable state rather than breaking the picker.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c686b5c-e23d-4d2a-b7cc-d87c87162c58

📥 Commits

Reviewing files that changed from the base of the PR and between 6aaa2dc and 152d786.

📒 Files selected for processing (4)
  • server.py
  • static/v3/image-picker.js
  • static/v3/match-review.js
  • static/v3/songs.js

📝 Walkthrough

Walkthrough

Adds a MusicBrainz-backed cover search feature: a backend helper and endpoint that search Cover Art Archive release-groups and return candidate covers, plus frontend image-picker UI wiring that fetches and applies search results, prefilled using artist/album metadata passed from calling screens.

Changes

Cover Search Feature

Layer / File(s) Summary
MusicBrainz search helper and endpoint
server.py
Adds _mb_search_release_groups to query MusicBrainz release-groups and build cover candidates, and a new GET /api/song/{filename:path}/art/cover-search endpoint that derives a search query from request params or song pack metadata and returns {query, covers}, handling transport failures gracefully.
Image picker search UI and flow
static/v3/image-picker.js
Adds a "Search covers" section with input, skeleton tiles, and empty/error states; wires search button/Enter key to a new coverSearch function that fetches results and applies a selected cover; initializes _cur.query from picker options.
Caller metadata wiring
static/v3/match-review.js, static/v3/songs.js
Updates __fbOpenImagePicker calls in the cover-art tab, card overflow menu, and Song Details drawer to pass artist and album fields alongside filename and title.

Estimated code review effort: 2 (Simple) | ~15 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SongsUI as songs.js / match-review.js
  participant ImagePicker as image-picker.js
  participant Server as server.py
  participant MusicBrainz

  User->>SongsUI: Click "Change cover..."
  SongsUI->>ImagePicker: __fbOpenImagePicker(filename, title, artist, album)
  ImagePicker->>ImagePicker: compute _cur.query from artist/album
  User->>ImagePicker: Click Search / press Enter
  ImagePicker->>Server: GET /art/cover-search?q=query
  Server->>Server: derive query if q empty (pack metadata)
  Server->>MusicBrainz: _mb_search_release_groups(query)
  MusicBrainz-->>Server: release-groups results
  Server-->>ImagePicker: {query, covers}
  ImagePicker->>ImagePicker: render cover tiles
  User->>ImagePicker: Click a cover tile
  ImagePicker->>ImagePicker: apply('url', selectedCover)
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/v3-cover-search

Comment @coderabbitai help to get the list of available commands.

@ChrisBeWithYou

Copy link
Copy Markdown
Contributor Author

📋 Merge order — metadata-curation epic (7 PRs)

  1. feat(v3 library): "Fix metadata" popup — per-song override + lock, cover picker, MusicBrainz + AcoustID #777 — Fix-metadata popup
  2. feat(v3 library): "Write to file" in the Fix-metadata popup #778 — Write to file
  3. feat(v3 library): Match→Details "use these values" bridge #779 — Match→Details bridge
  4. feat(v3 library): genre field in the Fix-metadata popup #780 — Genre in Details
  5. feat(v3 library): persistent "no match" badge + Unmatched quick filter #781 — No-match badge + Unmatched filter (independent of 1–4 — fine to merge any time)
  6. feat(v3 library): batch→popup handoff + English-base romaji (metadata-curation capstone) #782 — Batch→popup handoff + romaji (capstone)
  7. feat(v3 library): searchable Cover Art Archive picker in Change-cover #783 — Searchable cover picker

#778#780 are stacked (each based on the branch above), so GitHub re-points each to main automatically as the previous one merges — just merge #777#778#779#780 top-down. #781 is independent (base: main).

⚠️ Hold #782 and #783 until #777#781 are all in main. #782's branch is a combined branch that already contains #777#781, so merging it early would double-merge the stack. Once #777#781 land, the author will rebase #782 (then #783) onto main — they shrink to just their own commits — and they're then ready to merge.

The cover picker only offered CAA covers from a song's MATCHED release, so an
unmatched song (the city-pop pile) got nothing but Current/Pack/Upload/URL. Add
a search box: GET /api/song/{fn}/art/cover-search?q= searches MusicBrainz
release-groups and returns each album's CAA front-250 thumb; the picker renders
them as pickable tiles (same apply→/art/url path; covers with no CAA art
self-hide). Pre-filled from the song's artist + album/title (romaji fallback), so
a blank-artist pack pre-fills "Junko Yagami …". Reuses the throttled _mb_http_get.
@byrongamatos
byrongamatos force-pushed the feat/v3-cover-search branch from d45cdc3 to 152d786 Compare July 5, 2026 21:36
@byrongamatos
byrongamatos changed the base branch from feat/v3-batch-popup-handoff to main July 5, 2026 21:36
@byrongamatos
byrongamatos merged commit 5be7093 into main Jul 5, 2026
1 check was pending
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants