fix: artist page resolved "Flay!" to the far more popular "K.FLAY"

The Deezer artist match required only that every query word appear in the candidate name, so
"Flay!" (query word: flay) matched "K.FLAY" (words: k, flay). Sorted by fan count, K.FLAY
(54,822 fans) buried the real "Flay!" (39 fans) — the page showed K.FLAY's fans + top tracks.

Now prefer an EXACT normalized-name match ("flay" == "flay", not "kflay"), falling back to the
loose match only when there's no exact one. Web (detail.js) + Android (ArtistViewModel).
Verified against Deezer: exact match selects the real Flay! (id 12242284, whose top tracks
are actually Flay!). SW ns-v60.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-07-31 23:53:42 +02:00
1 parent b3cf01dd3b
commit e4f030c98d
3 files changed
+17 -8

No files matched your search

@@ -112,12 +112,15 @@ class ArtistViewModel(app: Application, savedState: SavedStateHandle) : AndroidV
}.getOrNull()
val artists = searchResp?.results?.filter { it.wrapperType == "artist" } ?: emptyList()
// artists are sorted by fan count (ItunesClient), so the first name match is the most popular
// one — disambiguates same-name artists (5x "Joji").
// artists are fan-sorted (ItunesClient), so firstOrNull gives the most popular match.
// Prefer an EXACT normalized-name match: "Flay!" must not resolve to the far more popular
// "K.FLAY" (its name merely contains "flay"). Only fall back to a loose contains-match.
fun norm(s: String?) = (s ?: "").lowercase().replace(Regex("[^a-z0-9]"), "")
val q = norm(artistName)
val iArtist = (
artists.find { it.artistName?.equals(artistName, ignoreCase = true) == true }
?: artists.find {
val n = it.artistName ?: return@find false
artists.firstOrNull { norm(it.artistName) == q }
?: artists.firstOrNull {
val n = it.artistName ?: return@firstOrNull false
n.contains(artistName, ignoreCase = true) || artistName.contains(n, ignoreCase = true)
}
?: artists.firstOrNull()