feat(qt): local rows drag to the sidebar and the queue

The shared drag gains a LOCAL payload arm: a Local Library / Explorer
row enters via dragStartLocal carrying its ROW ID, resolved to
source-aware refs at drop time — a library row id can never be read as
a catalog id, the same invariant the picker's Payload enum enforces.
TrackRow's localDragSource reuses every existing guardrail (horizontal
arming, select-mode/dead-row/playBlocked gates, preventStealing,
cancel teardown) without touching catalogRow's meaning. Drops route
through the picker's own add matrix: refs onto a local playlist or the
Qobuz sidecar, and Qobuz ids onto a local playlist (previously a
documented POC gap); queue drops land at the exact slot through the
same insert path as Qobuz drags. Native-catalog tracks rows keep the
gesture off until their identity can ride it.

cc
This commit is contained in:
vicrodh committed 2026-08-30 18:58:32 -06:00
1 parent c6ae362b7e
commit e9fa3fb57b
5 files changed
+171 -14

No files matched your search

@@ -134,9 +134,16 @@ Item {
showFavorite: false
showDownload: false
showMenu: false
// Local rows are NOT drag sources: item.id is a local DB row id and
// the sidebar drop handler forwards it as a Qobuz catalog id.
// Local rows drag through the LOCAL arm: item.id is a local DB row
// id, so the shared drag carries it typed (`dragStartLocal`) and the
// drop handlers resolve it source-aware — the same guardrails as the
// picker. `draggable` stays false so `catalogRow` keeps meaning
// "item.id is a Qobuz catalog id".
draggable: false
// NOT for native-catalog rows: their `item.id` is the catalog seam's
// identity, not a legacy row id the drop resolver can look up — a
// ghost that lands as a silent no-op is worse than no gesture.
localDragSource: !root.nativeActions
qualityStyle: "icon"
// A failed physical row stays clickable so the user can retry after a
// drive returns. The preflight prevents any queue/NPB mutation until