Track details from the queue, a playlist or a smart playlist looked
the track up in libraryStore's whole-library array, and returned
silently when it had not loaded, so the menu item did nothing. That
dependency is also why every track was fetched eagerly at startup
(20.5 MB at 26k tracks).
GetTracksByPaths answers for the paths in hand, and trackCache holds
the answers: bounded, coalesced into one call per task, and forgetting
what the retag, removal and scan events name. Every opener, and
track-details' own refresh after a save, go through it. A source sweep
pins the whole-library array to the store and the Tracks view.
Closes#279
Component and store cases for everything in this series, several of
which exist because the thing they pin is invisible everywhere else:
- `view-lifecycle` and `keyboard-reach` — a document listener count
that does not grow across a simulated navigate cycle, and a tab
sequence that reaches the sidebar and plays a row without a mouse.
- `notifications`, `notification-store`, `confirm-dialog`,
`empty-states` — the four levels, the (level, region, key)
coalescing window, and loading/failed/empty as three states.
- `card-grid-repaint` — fails if `artists-view`'s or `genres-view`'s
per-render arrow functions are hoisted to stable fields, which is
the audit's own recommendation and takes the cards from 1 highlighted
to 0. It exists for no other reason.
- `lazy-track-details` — reads the five sources and fails on a
returning static import, the same shape as `TestNoDirectRuntimeEmits`
and for the same reason: the invariant is about what the code does
*not* say.
- `now-playing` — a position report that changes nothing must not
touch the DOM again, and a track change must. The first fails
against the old unconditional `updated()`.
- `playlist-virtualization`, `list-render-cost`, `selection`, `icons`,
and the store cases for the library-filter race, the never-settling
waiter and the per-playlist patch.