Two changes to the local albums grid, both BUILT BUT UNSMOKED — Local Library
is best-effort for the next release, so this is committed to preserve it
rather than because it was validated.
1. ONE REBUILD PER QUERY. `rows` and `groups` are two bindings over one query:
the host derives `albumsVisible` from the search box and `albumsGrouped`
FROM `albumsVisible` (LocalLibraryView.qml:378-380). With a handler each,
a single keystroke rebuilt twice, and the first of the two was WRONG as
well as wasted — it chunked the new rows against the previous groups.
Turning grouping off did not save it either, because `groupRows` returns a
fresh `[]` every time and a new array is still a change. Coalesced onto a
zero-interval Timer: one rebuild per event-loop turn, reading both new
values. `Component.onCompleted` stays synchronous so a mount does not show
a frame of empty grid.
`[coltiming]` logs every rebuild with its cost, so a smoke run can falsify
the coalescing: one line per keystroke means it holds, two means it does
not. Timed around the work, never from a deferred callback.
2. ORDERED COVER REVEAL. The cold-thumbnail pool starts work in window order
but finishes out of order, since decode cost varies per cover, so covers
appeared scattered across the grid. Ordering the emission in Rust would
have made it worse: one slow decode at index 3 would hold 4..N behind it,
adding latency instead of hiding it. Instead arrivals are applied behind a
front that walks the window at a fixed rate; a cover landing behind the
front is applied at once. The front advances every tick unconditionally,
which is what makes a stall impossible, and a key with no ordinal is
released immediately.
Note for whoever picks this up: this reveal covers the LOCAL path only. The
uneven fill visible in ordinary navigation is HomeView's For You rails, which
take a different route (`forYouArt` via `onForyouArtReady`).
cc