Sync wishlist re-add: skip wing-it stubs (match the sync), no clickable button

'sami matar' was a wing-it FALLBACK stub — a placeholder the discovery pipeline
makes when it can't resolve a track to real metadata (no album, no cover). The
live sync explicitly skips wing_it_* ids for the wishlist (no metadata to act on),
but my re-add didn't — so it stored a coverless, single-classified placeholder.
That's why: sync didn't add it, no images, marked single.

Fix (parity): reconstruct refuses ids starting 'wing_it_'. Frontend renders the
'-> Wishlist' status as plain, non-clickable text for wing-it rows (with a tooltip)
since they were never actually wishlisted. Real tracks keep the working button +
the byte-identical-payload re-add from the prior fix.
This commit is contained in:
BoulderBadgeDad 2026-06-24 16:51:43 -07:00
parent d0966ec262
commit 5b7f99c30b
3 changed files with 26 additions and 5 deletions

View file

@ -71,6 +71,11 @@ def reconstruct_sync_track_data(
return None
sid = str(tr.get('source_track_id') or '')
# Wing-it fallback stubs have no real metadata (no album/cover) — the live sync
# SKIPS them for the wishlist (services/sync_service.py), so the re-add must too,
# rather than store a coverless, mis-classified placeholder.
if sid.startswith('wing_it_'):
return None
# Primary: the exact normalized track the auto-add used.
if sid:

View file

@ -100,6 +100,15 @@ def test_refuses_when_no_id_and_no_full_track():
assert reconstruct_sync_track_data([_tr(0, "")], [], 0) is None
def test_refuses_wing_it_stub():
# Wing-it fallback stubs have no real metadata; the sync skips them, so must we —
# even if a full (stub) track happens to be in tracks_json.
trs = [_tr(0, "wing_it_abc123", name="Sami Matar", artist="X")]
assert reconstruct_sync_track_data(trs, [], 0) is None
stub = {"id": "wing_it_abc123", "name": "Sami Matar", "album": "Sami Matar", "artists": ["X"]}
assert reconstruct_sync_track_data(trs, [stub], 0) is None
def test_build_map_skips_idless_and_non_dicts():
m = build_original_tracks_map([_full("a"), {"name": "no id"}, "garbage", None])
assert set(m.keys()) == {"a"}

View file

@ -2271,12 +2271,19 @@ async function openSyncDetailModal(entryId) {
let dlDisplay = dlIcon;
if (!dlDisplay && t.download_status === 'wishlist') {
// Wing-it fallback stubs (no real metadata) were never actually
// wishlisted by the sync — show them as plain, non-clickable.
const isWingIt = String(t.source_track_id || '').startsWith('wing_it_');
if (isWingIt) {
dlDisplay = `<span class="sync-dl-wishlist" title="No metadata — this track couldn't be resolved, so it can't be added to the wishlist">&rarr; Wishlist</span>`;
} else {
// Clickable: re-add this exact track to the wishlist with the
// same context the sync originally used.
dlDisplay = `<button type="button" class="sync-dl-wishlist sync-dl-wishlist-btn" `
+ `onclick="_readdSyncWishlist(${entryId}, ${i}, this)" `
+ `title="Re-add to wishlist with the original sync context">&rarr; Wishlist</button>`;
}
}
return `
<tr class="sync-detail-row ${statusClass}">