feat: add session-level API cache — skip spinners on home/albums/artists/playlists revisit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-06-06 11:45:22 +02:00
1 parent 08ca8303f3
commit d8908c69e9
2 files changed
+31 -9

No files matched your search

+10 -9
View File
@@ -1,6 +1,6 @@
import { S } from './state.js';
import { esc, formatDur, toast } from './utils.js';
import { api, coverUrl, itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesLookupArtistAlbums, itunesTopCharts, itunesTopSongs } from './api.js';
import { api, apiCached, apiIsCached, coverUrl, itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesLookupArtistAlbums, itunesTopCharts, itunesTopSongs } from './api.js';
// Circular imports — safe (only used inside function bodies)
import { playQueue, dlSongLocal, playPreview, toggleStar, parseArtists } from './player.js';
import { showCtxMenu, openEditPlModal, openDlModal, closeSidebar, switchNavMode } from './ui.js';
@@ -279,10 +279,10 @@ async function loadGenreDetail(g) {
export async function loadAlbumRow(id, method, extra) {
const c = document.getElementById(id);
if(!c) return;
c.innerHTML = '<div class="spinner"></div>';
if (!apiIsCached(method, extra)) c.innerHTML = '<div class="spinner"></div>';
try {
const [r] = await Promise.all([
api(method, extra),
apiCached(method, extra),
S.cfg.showRomaji ? fetchRomajiIndex().catch(() => {}) : Promise.resolve(),
]);
c.innerHTML = '';
@@ -293,9 +293,9 @@ export async function loadAlbumRow(id, method, extra) {
// ─── ARTISTS ───
export async function loadArtists() {
const g = document.getElementById('artists-grid');
g.innerHTML = '<div class="spinner"></div>';
if (!apiIsCached('getArtists')) g.innerHTML = '<div class="spinner"></div>';
try {
const r = await api('getArtists');
const r = await apiCached('getArtists');
const all = (r.artists?.index || []).flatMap(i => i.artist || []);
if (S.cfg.showRomaji) await fetchRomajiIndex().catch(() => {});
g.innerHTML = '';
@@ -327,9 +327,10 @@ export async function loadAlbums(type = _albumSort) {
document.querySelectorAll('#albums-sort-chips .sort-chip').forEach(c =>
c.classList.toggle('active', c.dataset.sort === type));
const g = document.getElementById('albums-grid');
g.innerHTML = '<div class="spinner"></div>';
const extra = `&type=${type}&size=500`;
if (!apiIsCached('getAlbumList2', extra)) g.innerHTML = '<div class="spinner"></div>';
try {
const r = await api('getAlbumList2', `&type=${type}&size=500`);
const r = await apiCached('getAlbumList2', extra);
g.innerHTML = '';
(r.albumList2?.album || []).forEach(a => g.appendChild(makeAlbumCard(a)));
} catch(e) { g.innerHTML = `<p style="color:var(--danger)">${e.message}</p>`; }
@@ -688,9 +689,9 @@ export async function loadAlbumDetail(album) {
// ─── PLAYLISTS ───
export async function loadPlaylists() {
const g = document.getElementById('playlists-grid');
g.innerHTML = '<div class="spinner"></div>';
if (!apiIsCached('getPlaylists')) g.innerHTML = '<div class="spinner"></div>';
try {
const r = await api('getPlaylists');
const r = await apiCached('getPlaylists', '', 3 * 60 * 1000);
const lists = r.playlists?.playlist || [];
g.innerHTML = '';
if(!lists.length) { g.innerHTML = '<div class="empty-state"><div class="icon">🎶</div><p>Keine Playlists vorhanden</p></div>'; return; }