Files
qbz/crates/qbz-qt/qml/views
vicrodh 494596616e feat(qt): port the Blacklist manager for artists and albums
The port had a 67-line settings row showing two counters and a header saying
the Manage chevron was "NOT shipped — this port has no Blacklist Manager view
for it to open". The Slint has 1,114 lines of manager plus the consumer surfaces
that make the feature mean anything.

- src/artist_blacklist.rs is a 1:1 port of the reference's per-user lifecycle,
  including the fail-open asymmetry (is_enabled reads TRUE when there is no
  session, everything else false/empty) and the byte-identical NO_SESSION_ERR.
  src/reco_dismiss_qt.rs carries the reco-dismissal store. Both are bound in
  ALL THREE session-activation paths — the offline one included, because the
  reference records that Tauri never bound it offline and blacklisted artists
  leaked into offline surfaces — and torn down on logout, or the next account
  inherits them.
- The manager view: three tabs (bordered, ADR-008 — no pills), search, sort,
  the enable toggle, the disabled warning banner, the four body branches per
  tab in their load-bearing order, windowed lists, and the clear-all confirm.
  Reached from Settings only, exactly like the Slint; no sidebar entry.
- Every one of the ten store mutations publishes TWICE — its own document and
  publish_settings() — because the Settings counters live in a different
  document and nav_qt::back() re-runs no per-view load. Without it,
  Manage -> unblock -> Back showed pre-mutation counters. The Slint gets this
  free from a shared global.
- The search field is driven imperatively, not by a binding: QbzLineEdit's X
  used to destroy the binding, after which the box went blank while the list
  stayed filtered.
- Consumer surfaces, which is where the feature actually lives: the album card
  and album list row gained "Block this album", the artist card gained the
  3-arg "Not interested", the album header menu gained Block/Unblock swapping
  on state, and the artist page gained the Show/Blacklist flip plus the amber
  hidden banner with its "Show artist" button. album_qt and artist_qt now seed
  isAlbumBlocked / isBlacklisted at document build time — without the seed an
  already-blocked album offered "Block this album" and the first click
  UN-blocked it, the same lie the pin glyph told before isPinned existed.
- search_qt passed &Default::default() for both blacklist snapshots, so nothing
  was filtered anywhere and a greyed row still played. It now passes the real
  snapshots at both call sites.
- The 17 toasts the spec had dropped for want of a toast host are wired: that
  premise stopped being true when toast_qt landed, and a Clear All that failed
  with NO_SESSION_ERR was completely silent. Their msgids are in all eight
  catalogues; the five album-axis ones existed only in es and nl.

Also fixed in passing, pre-existing on this branch and unrelated to the
blacklist: ArtistView's library tab read `libTracks` unqualified from a child
of the object that declares it, which QML resolves against the component root,
not the enclosing object — so the "Tracks" heading threw a ReferenceError and
never rendered. Found by forcing the artist route in the offscreen smoke, which
no earlier gate did.

cc
2026-07-29 21:24:12 -06:00
..