Logs tab, Record page rework, and a Spotify match that works - #19
Merged
Conversation
Five things the user asked for, in one pass. **Spotify metadata matched nothing the media session reported.** The guard compared Spotify's bare track name against the detected title after running only Spotify's side through the window-title splitter — so it compared a parsed string against an unparsed one for every track SMTC found, which has been the common case since Phase 7 made SMTC the primary source. "9Pm (Till I Come)" never matched "ATB - 9Pm (Till I Come)": four attempts, several seconds, then an untagged recording. `DetectedTrackMatch` reduces both sides to a common form and compares them in both shapes, title alone and artist joined on. Normalisation stops well short of fuzzy — the wrong answer here is not "no metadata" but a file tagged as a different song, so it forgives case, spacing and the punctuation each source wraps a qualifier in, and nothing else. **The session total read "0 saved" forever.** `_savedCount` refreshed `HasSaved` and not `SavedCountText`, which is derived from the same field. The count was right the whole time; only the string was stale, and nothing failed. **The activity log is a tab.** Third home in three attempts, because a log wants either the whole surface or none of it and a shared page offers neither. `LogsPage` is a second view onto `RecordViewModel` — a ViewModel of its own would mean a second sink subscription and two histories. **The display is backlit rather than reflective**, and no longer carries the track name. Pale grey with near-black segments was a calculator face and the palest object in a nearly black window; inverted, contrast goes up and it reads as the one lit thing on the page. The scanlines and the glass gradient flip with it — a black line over a near-black ground is invisible, and a top-dark gradient reads as a shadow. The meter's own drawing and spectrum are untouched. The track name moves to the Currently recording card, where it sits with the art and album it belongs to; the face keeps transport, format and the counter, which now has the right-hand side and a printed ELAPSED legend. Session totals move onto the heading they count, as `Count: n | Time: hh:mm:ss` — they had been stacked in a card describing one track, two timescales in one block, with the duration spelled as prose inches from a fixed-width clock. **The readiness chips and `ReadinessProbe` are gone**, with their fourteen resource strings. A missing ffmpeg is already an InfoBar with a sentence in it; five green pills saying nothing is wrong is a row always present and never read. **The FlaUI Desktop suite is deleted** rather than skipped — it was pinned to exactly the layout this rewrites — along with CI's Category filter and the FlaUI.UIA3 reference. Automation ids stay on every control; they are a Phase 9 accessibility requirement in their own right. 995 tests green, 19 of them new over the matcher. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
revtex added a commit
that referenced
this pull request
Aug 14, 2026
* Bring the changelog up to date with PRs 12-23 It was last touched in #11 and ten PRs have merged since, so the file described an app several phases behind the one in the tree - which for a Keep a Changelog file is worse than an empty one, because it reads as current. Entries for: the refresh token lost an hour into every session, SMTC as the primary track source and the TFM raise that allows it, endpoint hot-plug, extended-length paths, VB-CABLE detection, the existing-file policy checked before it could know the destination, the Logs tab and the Record page rework, the Spotify match guard, genre from Spotify's artists with Last.fm behind it, the media-session floor and its two mappers, Last.fm's missing album guard, the shutdown that left a ghost process, and the provider summaries on Settings. Readiness is deliberately absent: it was added in #18 and removed in #19, so no release ever carried it and an entry for each would be two lines describing nothing. Test count updated to 1051 (877 Core, 174 UI). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Require a changelog entry per PR, and drop two stray images The changelog going ten PRs stale was not an oversight anyone would catch by trying harder, so it is a rule with a check behind it now rather than a good intention. CLAUDE.md states it; a CI job fails a pull request whose diff does not touch CHANGELOG.md, with a `no-changelog` label as the escape hatch so a test-only fix opts out by saying so instead of by staying quiet. The job runs on ubuntu with no `needs`, so it answers in seconds alongside the Windows build rather than behind it - which is why it is a job of its own, despite the note on `build` arguing against exactly that for publish-check. That case was gated on `needs: build` and paid for a second VM to run strictly afterwards; this one does not. Also removes 06aa2f03-...jpg and b514cfc3-...jpg from the repository root. Both were untracked, and both were mine to be suspicious of and wrong about: I guessed earlier they were leaked cover-art downloads. They are not. CoverArtFetcher writes to GetTempPath() under the name "<random>.offstream-cover.jpg" and never to the working directory, and these were a matched pair of 1024x572 images, which is not the shape album art comes in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Five things from one batch.
1. Spotify metadata matched nothing SMTC reported
The attached log showed four failed attempts then "Spotify had no metadata for 'ATB - 9Pm (Till I Come)'." — for a track Spotify obviously knows.
The guard compared Spotify's bare track name against the detected title after running only Spotify's side through the window-title splitter. So it compared a parsed string against an unparsed one for every track the media session found, which is the common case since Phase 7 made SMTC primary — SMTC reports titles verbatim, where the window-title parser has already split them.
DetectedTrackMatchreduces both sides to a common form and compares them in both shapes: the title alone, and the artist joined on. A provider's bare name matches a detectedArtist - Titlebecause joining the provider's own artist onto its name produces the same thing.Normalisation deliberately stops well short of fuzzy. The wrong answer at a track boundary is not "no metadata", it is a file tagged as a different song — so it forgives case, accents, spacing, and the punctuation each source wraps a qualifier in, and nothing else. Three guard tests pin the line:
"Song"must not match"Song (Live)","Song (Radio Edit)"must not match"Song (Extended Mix)", and"9Pm (Till I Come)"must not match"9Am (Till I Come)".19 new tests.
2. The saved count showed zero
[ObservableProperty]on_savedCountrefreshedHasSavedand notSavedCountText, which is derived from the same field. The count was correct in the debugger the whole time and stale on screen, and nothing failed. One attribute.Worth watching for on the rest of this page — a missing
[NotifyPropertyChangedFor]has no compile-time or runtime signal at all.3. Logs is its own tab, beside Advanced
Third home in three attempts: the whole page, then a fixed-height box, then a collapsed expander. A log wants either the whole surface or none of it, and a shared page can offer neither.
LogsPageis a second view ontoRecordViewModelrather than a ViewModel of its own — the lines, the filter and both buttons are already there and subscribed to the sink since startup, so a second ViewModel would mean a second subscription and two histories diverging by construction order. Auto-scroll (follow the tail only while already at the tail) moves with it.4. Display and Currently recording
ELAPSEDlegend. A bare00:03:42on a recorder could be elapsed, remaining, or a timestamp; one small word settles it once instead of every glance. Format text moves beside the transport block, which is where it belongs — "recording" and "recording as what" are one question.Count: n | Time: hh:mm:sswith a rule filling the gap. They were stacked inside a card describing a single track — two timescales in one block — and the duration was prose (4m 12s) sitting inches from a fixed-width clock, so comparing them meant converting between them.5. Removals
ReadinessProbe, plus fourteen resource strings and the DI registration. A missing ffmpeg is already an InfoBar with a sentence in it, and a library folder is already unsaveable without one. Five green pills reporting nothing is wrong is a row that is always there and never read.FlaUI.UIA3and CI's--filter "Category!=Desktop"go with them. Automation ids stay on every control — they are a Phase 9 accessibility requirement in their own right and are what any future suite would need.Verification
dotnet buildclean,dotnet format --verify-no-changesclean, 995 tests green (824 Core + 171 UI). No UI testing run, per your standing instruction — worth a look at the Record and Logs tabs, and at whether the inverted display reads right on your monitor.🤖 Generated with Claude Code