v3 library: "Refresh Metadata" button + per-view re-match + filename-artist seed - #764
Conversation
…ename-artist seed
Adds a media-server-style "Refresh Metadata" control to the Songs toolbar
(beside "⟳ Refresh") — the metadata counterpart to a file scan.
- Re-matches the songs currently SHOWN (the visible grid window) against
MusicBrainz: a per-view refresh that's visible even on an already-matched
library. The button doubles as Stop while a pass runs; a batch progress bar
+ per-tile queued→working→done badges show what's happening. User-pinned
`manual` matches are never re-matched.
- Backend: POST /api/enrichment/{cancel,states,rematch}; /status gains
total/matched/current/cancelling; a cooperative cancel Event is checked
between songs in the match + art phases so Stop halts without waiting for
the whole queue. `states` is read-only (open); `cancel`/`rematch` are
demo-blocked.
- Matcher: when a pack's `artist` field is blank (common in community
charts), derive artist/title from the CDLC `Artist_Song-Title` filename
convention as a SEARCH SEED so text matching can identify it — the displayed
values still come only from the confirmed MusicBrainz match, nothing
estimated is shown as author-set. Rescues blank-artist packs that otherwise
always failed.
Tests: enrichment_states_for, the three new routes, cancel-halts-a-pass,
kick-clears-stale-cancel, filename parse, blank-artist seeding, and
present-artist-not-overridden.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughServer-side enrichment now tracks per-pass progress and supports cooperative cancellation, with new endpoints for cancel, rematch, and per-filename state queries. Matching falls back to filename-derived artist/title when manifest artist is blank. The Songs UI adds a metadata refresh button, progress bar, and per-tile badges polling these endpoints. ChangesEnrichment cancellation, progress, and rematch workflow
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant SongsUI
participant Server
participant EnrichRunner
User->>SongsUI: click Metadata button
SongsUI->>Server: POST /api/enrichment/rematch
Server->>EnrichRunner: reset filenames to unscanned, kick pass
loop polling
SongsUI->>Server: GET /api/enrichment/status
SongsUI->>Server: POST /api/enrichment/states
Server-->>SongsUI: progress + per-filename states
SongsUI->>SongsUI: patch tile badges, update progress bar
end
User->>SongsUI: click Stop
SongsUI->>Server: POST /api/enrichment/cancel
Server->>EnrichRunner: set _enrich_cancel
EnrichRunner->>EnrichRunner: stop after current item
Server-->>SongsUI: running=false
SongsUI->>SongsUI: clear badges, emit library:changed
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
Review pass (Claude Code). Solid. Backend: |
#781) * feat(v3 library): persistent "no match" badge + Unmatched quick filter The Refresh-Metadata batch (#764) shows a transient per-tile "no match" only while a pass runs, so the unmatched pile goes quiet at rest. Two additions make it visible + reachable: - Persistent per-card "No match" badge: query_page now marks each row `unmatched` (a cheap failed-set membership like favs/estd), and enrichBadge paints a subtle resting marker for those cards — tracked in a `_unmatched` set so a batch tile clearing falls back to it instead of wiping it. A live batch tile still wins while a pass runs. - "Unmatched" toolbar toggle (local-only): one click applies the same filter as the drawer's Match → Unmatched (match_state='failed'), so the no-match pile is a click away right after a batch. Re-queries + reflects active state. Test: query_page flags a failed row + the match=unmatched filter returns it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(v3 library): repaint persistent no-match badge after metadata tile-clear _clearMetaTiles removed every .v3-meta-tile node — including the new persistent 'No match' resting badge, which derives from _unmatched rather than _metaTile. A metadata rescan's tile-clear therefore dropped the badge until the next scroll re-rendered the card. Repaint it from _unmatched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: byrongamatos <xasiklas@gmail.com>
What
A media-server-style Refresh Metadata control on the Songs toolbar (beside ⟳ Refresh) — the metadata counterpart to a file scan. Where Refresh scans the folder for new files, this re-matches the songs you're viewing against MusicBrainz.
Behaviour
queued → working → donebadges. User-pinned (manual) matches are never touched.artistfield, which text search can't match on (and the per-field floor rejects). When the pack's artist is blank, the matcher now derives artist/title from the CDLCArtist_Song-Titlefilename convention as a search seed only — the displayed values still come solely from the confirmed MusicBrainz match, so nothing estimated is presented as author-set. This rescues blank-artist packs that previously always failed.API
POST /api/enrichment/rematch {filenames}— reset the given (visible) songs tounscanned(skipsmanualvia the existing never-overwrite guard) + kick one pass; returns the queued filenames.POST /api/enrichment/cancel— cooperative Stop; a cancelEventis checked between songs in the match + art phases.POST /api/enrichment/states {filenames}— per-window{filename: match_state}(+ current + running) for the tile badges. Read-only.GET /api/enrichment/statusgainstotal/matched/current/cancelling.cancel+rematchblocked (mutate/spend rate budget);statesstays open (read-only).Tests
enrichment_states_for, the three new routes, cancel-halts-a-pass-between-songs, kick-clears-a-stale-cancel, the filename parser, blank-artist seeding, and present-artist-not-overridden. Full enrichment + demo + scraper + context-menu + art suites green (162 passed).Verification
Exercised end-to-end on a live preview against a 1002-song DB + real MusicBrainz: the pass progresses (running/total/matched/current at the ≤1/s throttle), Stop halts mid-pass (1 of 8 before breaking), cancel-when-idle is a clean no-op, and the filename seed rescued a real blank-artist pack (
failed → matched). Frontend parses + is served correctly; the in-app visual pass (button/bar/tiles/toast pixels) is still worth an eyeball.🤖 Generated with Claude Code
Summary by CodeRabbit