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:
parent
d0966ec262
commit
5b7f99c30b
3 changed files with 26 additions and 5 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"}
|
||||
|
|
|
|||
|
|
@ -2271,11 +2271,18 @@ async function openSyncDetailModal(entryId) {
|
|||
|
||||
let dlDisplay = dlIcon;
|
||||
if (!dlDisplay && t.download_status === 'wishlist') {
|
||||
// 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">→ Wishlist</button>`;
|
||||
// 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">→ 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">→ Wishlist</button>`;
|
||||
}
|
||||
}
|
||||
|
||||
return `
|
||||
|
|
|
|||
Loading…
Reference in a new issue