Kein Scrobble-Dienst konfiguriert. Trage die Scrobble-URL in den Einstellungen ein,
damit deine Wiedergaben aufgezeichnet werden.
`;
return;
}
const auth = subsonicAuthParams();
if (!auth) { body.innerHTML = _errBox('Nicht angemeldet.'); return; }
// Only show "Lade…" on the very first open — on a period/tab switch keep the current content
// in place until the new data arrives, so the modal doesn't flash small→big (min-height also
// keeps its size stable). A per-request token guards against out-of-order responses.
if (!body.dataset.loaded) body.innerHTML = `
Lade…
`;
const token = String(Date.now());
body.dataset.req = token;
const { from, to, bucket } = _range();
const qs = `${auth}&from=${from}&to=${to}&tz=${_tzOffsetSec()}&bucket=${bucket}&limit=10`;
try {
const res = await fetch(`${S.cfg.scrobbleUrl}/scrobble/stats?${qs}`);
if (body.dataset.req !== token) return; // a newer request superseded this one
if (!res.ok) { body.innerHTML = _errBox(`Fehler ${res.status}`); return; }
const d = await res.json();
if (body.dataset.req !== token) return;
if (d.firstPlayedAt) { _firstPlayedAt = d.firstPlayedAt; _renderTabs(); } // apply back-bound
_render(body, d);
body.dataset.loaded = '1';
} catch {
if (body.dataset.req === token) body.innerHTML = _errBox('Scrobble-Dienst nicht erreichbar.');
}
}
function _errBox(msg) {
return `
${esc(msg)}
`;
}
function _render(body, d) {
if (!d.totalPlays) {
body.innerHTML = `
Noch keine Wiedergaben in diesem Zeitraum. Spiel ein paar Songs — sie erscheinen hier automatisch.
`;
return;
}
body.innerHTML = [
_tiles(d),
_seriesChart(d.series, d.range.bucket),
_topList('Top-Künstler', d.topArtists, a => a.name, a => a.plays, a => a.artistId, true,
a => a.artistId ? { type: 'artist', id: a.artistId, name: a.name } : null),
_topList('Top-Songs', d.topTracks, t => `${t.title}${t.artist ? ' · ' + t.artist : ''}`, t => t.plays, t => t.coverArt || t.albumId || t.songId, false,
t => t.albumId ? { type: 'album', id: t.albumId, name: t.album, artist: t.artist } : null),
_topList('Top-Alben', d.topAlbums, a => `${a.name}${a.artist ? ' · ' + a.artist : ''}`, a => a.plays, a => a.coverArt || a.albumId, false,
a => a.albumId ? { type: 'album', id: a.albumId, name: a.name, artist: a.artist } : null),
_hourClock(d.byHour),
].join('');
}
function _tiles(d) {
const tile = (val, label) => `