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

+20
View File
@@ -1178,3 +1178,23 @@ button:focus{outline:none}
.cmp-bar{height:6px;border-radius:3px;background:var(--accent)}
.cmp-track{display:flex;align-items:center;gap:10px;padding:6px 0;min-width:0}
.cmp-track img{width:40px;height:40px;border-radius:6px;object-fit:cover;flex-shrink:0}
/* ─── NEU VON DEINEN KÜNSTLERN ─────────────────────────────────────────── */
.artist-news-hint{background:rgba(232,160,32,.08);border:1px solid rgba(232,160,32,.28);border-radius:10px;padding:10px 14px;font-size:12px;color:var(--text2);line-height:1.5;margin-bottom:14px}
.artist-news-hint strong{color:var(--text)}
.artist-news-row{display:flex;align-items:center;gap:14px;padding:10px 12px;border-radius:12px;transition:background .15s}
.artist-news-row:hover{background:var(--surface)}
.artist-news-art{width:56px;height:56px;flex-shrink:0;border-radius:8px;overflow:hidden;background:var(--surface2);display:flex;align-items:center;justify-content:center}
.artist-news-art img{width:100%;height:100%;object-fit:cover}
.artist-news-info{flex:1;min-width:0}
.artist-news-title{font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.artist-news-sub{font-size:12px;color:var(--text2);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.artist-news-artist{cursor:pointer;transition:color .15s}
.artist-news-artist:hover{color:var(--accent);text-decoration:underline}
.artist-news-date{font-size:11px;color:var(--text3);margin-top:3px}
.artist-news-action{flex-shrink:0}
.artist-news-have{font-size:12px;color:var(--text3);white-space:nowrap}
@media(max-width:600px){
.artist-news-art{width:46px;height:46px}
.artist-news-row{gap:10px;padding:8px 6px}
}