fix(web): Deezer artist images + rename the search label

- Search artist cards now use the Deezer artist picture directly (Deezer artists carry
  a photo, unlike iTunes entities) instead of a null image + an extra album lookup;
  the lookup stays only as a fallback when no picture is present.
- Non-local (Deezer) artist pages: fetch the Deezer artist picture (/artist/{id}) for
  the hero photo, which was blank because getArtistImage only runs for Navidrome artists.
- Label "iTunes Künstler" → "Deezer Künstler".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-07-30 22:01:59 +02:00
1 parent ad433c4dbc
commit a65613b5a1
4 files changed
+25 -3

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'ns-v49';
const CACHE = 'ns-v50';
const PRECACHE = ['/', 'index.html', 'manifest.json', 'icon.svg'];
const SKIP_PATHS = ['/rest/stream', '/rest/download', '/config.js'];
// Auth token params stripped from cache keys so artwork survives across sessions/token refreshes.
+8
View File
@@ -372,6 +372,14 @@ export async function itunesLookupArtistAlbums(artistId, limit=100) {
} catch { return []; }
}
// Deezer artist photo (for the hero on non-local artist pages). iTunes artist entities had none.
export async function deezerArtistImage(artistId) {
try {
const a = await (await fetch(`${_deezerBase()}/artist/${artistId}`)).json();
return a.picture_xl || a.picture_big || a.picture_medium || null;
} catch { return null; }
}
export async function itunesTopCharts() {
const urls = [_chartsUrl('de', 'albums'), _chartsUrl('us', 'albums')];
for(const url of urls) {
+14 -1
View File
@@ -1,6 +1,6 @@
import { S } from '../state.js';
import { esc, toast } from '../utils.js';
import { api, coverUrl, itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesLookupArtistAlbums, fetchRomajiIndex, dispArtistById, dispAlbumName, cacheArtistSortNames, ensureArtistSortMap } from '../api.js';
import { api, coverUrl, itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesLookupArtistAlbums, deezerArtistImage, fetchRomajiIndex, dispArtistById, dispAlbumName, cacheArtistSortNames, ensureArtistSortMap } from '../api.js';
import { makeCard, makeAlbumCard, makeGlobalTrackItem, makeSongItem } from '../ui/components.js';
import { playQueue, dlSongLocal, toggleStar, parseArtists } from '../player/player.js';
import { showCtxMenu, openDlModal } from '../ui/ui.js';
@@ -146,6 +146,19 @@ export async function loadArtistDetail(artist) {
});
const itunesArtistId = knownItunes ?? iArtistMatch?.artistId ?? null;
// Non-local (Deezer) artist has no Navidrome photo — fetch the Deezer artist picture for the hero.
if (!hasND && itunesArtistId && pfpWrap) {
const dzImg = iArtistMatch?.artworkUrl100 || await deezerArtistImage(itunesArtistId);
if (dzImg) {
const pfpImg = document.createElement('img');
pfpImg.className = 'artist-hero-pfp';
pfpImg.onload = pfpImg.onerror = () => { if (bgEl) bgEl.style.backgroundImage = `url('${dzImg}')`; _revealHero(); };
pfpImg.src = dzImg;
pfpWrap.prepend(pfpImg);
document.getElementById('artist-hero-pfp-initial')?.style.setProperty('display', 'none');
}
}
const [iAlbumsRes, iTracksRes] = itunesArtistId
? await Promise.allSettled([
itunesLookupArtistAlbums(itunesArtistId),
+2 -1
View File
@@ -130,9 +130,10 @@ export async function doGlobalSearch(q) {
const s = mkSection('Künstler');
const row = document.createElement('div'); row.className = 'scroll-row';
artists.forEach(a => {
const c = makeCard(a.artistName, 'iTunes Künstler', null, '🎤');
const c = makeCard(a.artistName, 'Deezer Künstler', a.artworkUrl100 || null, '🎤');
c.onclick = () => loadItunesArtistResults(a.artistId, a.artistName);
row.appendChild(c);
if (a.artworkUrl100) return; // Deezer artists already carry a photo — no extra lookup
itunesSearch(a.artistName,'album',1).then(res => {
if(!res[0]) return;
const imgUrl = res[0].artworkUrl100?.replace('100x100','300x300');