diff --git a/src/lib/state.svelte.js b/src/lib/state.svelte.js index 31311c4..1dbb558 100644 --- a/src/lib/state.svelte.js +++ b/src/lib/state.svelte.js @@ -2558,12 +2558,55 @@ export async function openAlbumByName(artist, title, opts = {}) { if (request !== albumResolveRequest) return null; // A title-only or first-result fallback can cross into a namesake's // catalog. Without a verified id, both artist and title must match. - const match = res.albums?.find( + let match = res.albums?.find( (album) => catNorm(album.artist) === na && catNorm(album.title) === nt, ); - // A successful search that matched nothing is an answer ABOUT THE - // RECORD: this artist has no such album in the catalog. Negative-cache - // it. A throw below is an answer about the network, and is not cached. + // Deezer's SEARCH index is not the whole discography. The artist page + // merges a MusicBrainz supplement on top of it, so records Deezer does + // not carry at all still have a real id, a real release date and full + // Last.fm figures there — Panda Bear's "A ? of WHEN" is one, and it is + // exactly what made this resolve give up and fall through to a bare + // local page. Ask the ARTIST'S OWN discography before concluding the + // record does not exist; it is the same list the artist page's album + // expander opens from, and it is already cached whenever that page has + // been visited. + if (!match) { + const seed = await resolveArtistSeedByName(artist); + if (request !== albumResolveRequest) return null; + if (seed?.id != null) { + const page = await getCatalogArtistPage(seed.id).catch(() => null); + if (request !== albumResolveRequest) return null; + match = page?.albums?.find((album) => catNorm(album.title) === nt); + // The cached page is only SUPPLEMENTED once the artist page + // has been visited — cold, it is the raw Deezer list and the + // MB-only records are still missing. Run the same merge the + // artist page and the Now Playing panel run, rather than + // concluding the record does not exist. + if (!match) { + const identity = await api + .catalogArtistIdentity(seed.id, seed.name ?? artist) + .catch(() => null); + if (request !== albumResolveRequest) return null; + if (identity?.albums?.length) { + const merged = mergeArtistIdentity( + { + artist: { name: seed.name ?? artist }, + albums: page?.albums ?? [], + socials: [], + typeHints: [], + }, + identity, + ); + match = merged?.albums?.find( + (album) => catNorm(album.title) === nt, + ); + } + } + } + } + // A settled miss is an answer ABOUT THE RECORD: neither the catalog nor + // the artist's own discography has it. Negative-cache that. A throw + // below is an answer about the network, and is not cached. albumNameResolves.set(key, match ? match.id : null); if (!match) return null; openCatalogAlbum(match.id, opts);