From 467ee8a0fe243e1cf45e1abeeb33bdb1311eca24 Mon Sep 17 00:00:00 2001 From: Honey Date: Sat, 23 May 2026 13:08:33 +0200 Subject: [PATCH] fix: consistent artist parsing across player, NP overlay, and song list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract parseArtists() helper — uses Navidrome's resolved artists array when it has multiple entries, otherwise splits artist string on ';' only. Removes old split on / that broke Au/Ra, HUNTR/X etc everywhere. Co-Authored-By: Claude Sonnet 4.6 --- src/components.js | 6 ++---- src/player.js | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/components.js b/src/components.js index f97bded..0aafb19 100644 --- a/src/components.js +++ b/src/components.js @@ -2,7 +2,7 @@ import { S } from './state.js'; import { esc, formatDur } from './utils.js'; import { coverUrl } from './api.js'; // Circular imports — safe (only used inside event handlers after module init) -import { playQueue, toggleStar, playPreview } from './player.js'; +import { playQueue, toggleStar, playPreview, parseArtists } from './player.js'; import { showCtxMenu, openDlModal } from './ui.js'; import { navigate, quickPlayAlbum, quickPlayArtist } from './views.js'; @@ -33,9 +33,7 @@ export function makeSongItem(s, idx, list, { noArtistLink = false, noAlbumLink = el.className = 'song-item' + (S.queue[S.qIdx]?.id === s.id ? ' playing' : ''); el.dataset.songId = s.id; const cv = coverUrl(s.coverArt, 128); - const artistParts = Array.isArray(s.artists) && s.artists.length - ? s.artists - : s.artist ? [{ name: s.artist, id: s.artistId || '' }] : []; + const artistParts = parseArtists(s); const artistHtml = artistParts.length ? artistParts.map(a => noArtistLink ? `${esc(a.name)}` diff --git a/src/player.js b/src/player.js index 7ac01a8..5739892 100644 --- a/src/player.js +++ b/src/player.js @@ -442,14 +442,20 @@ function _updatePlayingHighlights() { }); } +// Returns [{name, id}] using Navidrome's resolved artists when available, +// otherwise splits the artist string on ';' only (safe for names like Au/Ra). +export function parseArtists(s) { + if (Array.isArray(s.artists) && s.artists.length > 1) return s.artists; + return (s.artist || '').split(/\s*;\s*/).filter(Boolean) + .map((name, i) => ({ name, id: i === 0 ? (s.artistId || '') : '' })); +} + export function updatePlayerUI(s, _skipMediaSession = false) { document.getElementById('player-title').textContent = s.title; - const artistParts = (s.artist || '').split(/\s*(?:\/|•|,)\s*/).filter(Boolean); + const artistParts = parseArtists(s); document.getElementById('player-artist-name').innerHTML = artistParts.length - ? artistParts.map((name, i) => { - const aid = i === 0 ? (s.artistId || '') : ''; - return `${esc(name)}`; - }).join(' • ') + ? artistParts.map(a => `${esc(a.name)}`) + .join(' • ') : '—'; document.getElementById('player-album-name').textContent = s.album || ''; const art = document.getElementById('player-art'); @@ -515,12 +521,10 @@ export function _syncNpDirect(s) { const t = document.getElementById('np-title'); if(t) t.textContent = s.title || '—'; const an = document.getElementById('np-artist-name'); if(an) { - const parts = (s.artist || '').split(/\s*(?:\/|•|,)\s*/).filter(Boolean); + const parts = parseArtists(s); an.innerHTML = parts.length - ? parts.map((name, i) => { - const aid = i === 0 ? (s.artistId || '') : ''; - return `${esc(name)}`; - }).join(' • ') + ? parts.map(a => `${esc(a.name)}`) + .join(' • ') : '—'; } const aln = document.getElementById('np-album-name'); if(aln) aln.textContent = s.album || '';