feat(scrobble stats): genre ranking (Top-Genres) — web + android
Play-log now stores each play's genre (from the song tags; web scrobbleLog + android PlayLogClient capture song.genre). The stats endpoint returns topGenres (GROUP BY lower(genre), case-insensitive, blanks ignored); web + android render a Top-Genres section. Schema migrates via ALTER TABLE. Old plays have no genre (fills going forward, like cover art). SW cache -> ns-v72. Android compileDebugKotlin + web build green; genre grouping + null-ignore unit-tested. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
249b693936
commit
0c7132a7f2
7 files changed
+56
-9
No files matched your search
+5
-2
@@ -207,6 +207,7 @@ function _render(body, d) {
|
||||
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),
|
||||
_topList('Top-Genres', d.topGenres, g => g.name, g => g.plays),
|
||||
_hourClock(d.byHour),
|
||||
].join('');
|
||||
}
|
||||
@@ -249,9 +250,11 @@ function _topList(title, items, labelFn, valFn, idFn = null, circular = false, n
|
||||
const rows = items.map((it, i) => {
|
||||
const val = valFn(it);
|
||||
const cover = idFn ? coverUrl(idFn(it), 80) : null;
|
||||
const thumb = `<div style="width:40px;height:40px;border-radius:${radius};background:var(--surface2);flex-shrink:0;overflow:hidden">
|
||||
const thumb = idFn
|
||||
? `<div style="width:40px;height:40px;border-radius:${radius};background:var(--surface2);flex-shrink:0;overflow:hidden">
|
||||
${cover ? `<img src="${esc(cover)}" loading="lazy" style="width:100%;height:100%;object-fit:cover" onerror="this.style.display='none'">` : ''}
|
||||
</div>`;
|
||||
</div>`
|
||||
: '';
|
||||
const nav = navFn ? navFn(it) : null;
|
||||
const navAttrs = nav
|
||||
? `data-nav-type="${nav.type}" data-nav-id="${esc(nav.id)}" data-nav-name="${esc(nav.name || '')}" data-nav-artist="${esc(nav.artist || '')}"`
|
||||
|
||||
Reference in new issue
Block a user