feat: Zeitleiste "Neu von deinen Künstlern" (Web) + Backend-Endpunkt

Eigener Punkt in der Seitenleiste: jüngste Veröffentlichungen aller
gefolgten Künstler, nach Monat gruppiert, neueste zuerst, umschaltbar auf
30/90/365 Tage. Was schon in der Bibliothek liegt, ist markiert (Vergleich
über Künstler + Albumname, akzent- und zeichenunabhängig); alles andere
bekommt einen Laden-Knopf zum vertrauten Download-Dialog.

Neuer Endpunkt POST /api/artist-releases (backend/lib/releases.js): die
Deezer-Zuordnung passiert serverseitig, weil die Künstler-Pins dort
ohnehin liegen. Gepinnte nutzen die feste ID, ungepinnte werden über den
Namen gesucht und nach Fan-Zahl sortiert; ohne Treffer kommt der Name als
ohneZuordnung zurück und die Oberfläche rät zum Pinnen.

Cache im Backend statt im Client — bei 30 gefolgten Künstlern wären das
sonst 30 Deezer-Aufrufe pro Gerät und App-Start. 6 h für Alben, 24 h für
die Namenszuordnung, max. 4 Anfragen parallel, bei Deezer-Fehlern wird
der abgelaufene Stand ausgeliefert statt einer leeren Liste.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-09-18 13:50:33 +02:00
1 parent 19f241e493
commit 908488a337
8 files changed
+345 -2

No files matched your search

+15
View File
@@ -76,6 +76,9 @@
<div class="nav-item" onclick="navigate('discover')" data-page="discover">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polygon points="10 8 16 12 10 16 10 8"/></svg>Global Suche
</div>
<div class="nav-item" onclick="navigate('artist-news')" data-page="artist-news">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>Von deinen Künstlern
</div>
<div class="nav-item" onclick="navigate('new-releases')" data-page="new-releases">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>Neue Releases
</div>
@@ -406,6 +409,18 @@
</div>
<!-- NEW RELEASES -->
<div class="page" id="page-artist-news">
<div class="page-header">
<div class="page-title">Neu von <em>deinen Künstlern</em></div>
</div>
<div id="artist-news-sort" class="sort-chips">
<button class="sort-chip active" data-days="90" onclick="loadArtistNews(90)">90 Tage</button>
<button class="sort-chip" data-days="30" onclick="loadArtistNews(30)">30 Tage</button>
<button class="sort-chip" data-days="365" onclick="loadArtistNews(365)">1 Jahr</button>
</div>
<div id="artist-news-list"></div>
</div>
<div class="page" id="page-new-releases">
<div class="page-header">
<div class="page-title">Neue <em>Releases</em></div>