feat(qt): find an available version for a track Qobuz pulled
Reachable from a dead row's context menu, in a playlist the user owns. The reference had this and shipped it with four defects; none are ported. It was unranked -- Qobuz's raw relevance order shown to the human. The weighted matcher that already lives in qbz-playlist-import does the ranking now, and its ISRC short-circuit matters most: licensing churn usually republishes the SAME recording under a new id with the SAME ISRC, and the pulled track keeps its isrc (confirmed in the 2026-08-17 capture of album 0886443985094). That case needs no human judgement, so the ISRC lookup runs first and pins its hit to the top. It removed before it added, so a failed add lost the track outright. The order here is add, reposition, remove. It did not preserve position -- the computed index went to a console.log and the replacement landed at the end. It lands where the dead row was, through the new updateTracksPosition verb. Every failure in that step is a warning and a different success toast: the repair still stands at the end of the playlist, exactly where the reference always put it. Position is a nicety, never a reason to abort a repair. Two guards. If the ISRC lookup answers with the dead track itself -- it can, since a pulled track keeps its metadata and search still indexes it -- then "replace" would be a no_duplicate no-op followed by a remove, and the user would lose the row while being told it was repaired. And when the remove fails the playlist permanently holds both rows: that is not rolled back, because a rollback is a second write that can fail the same way and would delete the only good copy. The list is refreshed so the user SEES both, and the toast says the old one has to go by hand rather than claiming a reload will fix it. cc
This commit is contained in:
7 files changed
+1310
-1
No files matched your search
@@ -701,6 +701,19 @@ Rectangle {
|
||||
PlaylistImportModal {
|
||||
anchors.fill: parent
|
||||
}
|
||||
// TrackReplacementModal — "Find available version" for a track Qobuz
|
||||
// pulled from the catalogue (2026-08-17 unavailable-tracks contract §6),
|
||||
// opened from the playlist row's context menu.
|
||||
//
|
||||
// Out here for the strongest form of its neighbours' reason: the apply
|
||||
// RELOADS the playlist underneath it (`refresh_after_membership_change`),
|
||||
// so a modal parented into the playlist view would be destroyed by its own
|
||||
// success — while a write is still settling. Self-gates on
|
||||
// QbzTrackReplace.replaceJson, so while closed it is an invisible,
|
||||
// non-interactive Item.
|
||||
TrackReplacementModal {
|
||||
anchors.fill: parent
|
||||
}
|
||||
MyQbzModals {
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user