fix(web player + stats modal): no auto-resume after user pause; stable stats modal
Player: opening the PWA no longer auto-plays when the user had paused. Pausing via the media notification while backgrounded routes through togglePlay, which now sets S._userPaused; _onForeground only auto-resumes an INVOLUNTARY background stop (_wasPlayingBeforeHide && !_userPaused). playCurrent clears the flag on a new track. Involuntary-stop/freeze recovery on foreground is preserved. Stats modal: no more small→big flash when switching period/tab — the body keeps a stable min-height and retains its current content until the new data arrives (only the first open shows 'Lade…'); a per-request token drops out-of-order responses. SW cache -> ns-v71. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
3129333f9a
commit
1d98b273e7
5 files changed
+21
-9
No files matched your search
+11
-3
@@ -109,7 +109,7 @@ function _buildOverlay() {
|
||||
style="padding:6px 10px;color:var(--text2);font-size:18px;background:none;border:none;cursor:pointer">✕</button>
|
||||
</div>
|
||||
<div class="stats-tabs" id="stats-tabs" style="display:flex;gap:6px;padding:12px 18px 0"></div>
|
||||
<div class="stats-body" id="stats-body" style="padding:16px 18px;overflow-y:auto"></div>
|
||||
<div class="stats-body" id="stats-body" style="padding:16px 18px;overflow-y:auto;min-height:62vh"></div>
|
||||
</div>`;
|
||||
// Delegated navigation: click an artist / album / track row → open its page.
|
||||
_overlay.querySelector('#stats-body').addEventListener('click', async e => {
|
||||
@@ -165,18 +165,26 @@ async function _load() {
|
||||
const auth = subsonicAuthParams();
|
||||
if (!auth) { body.innerHTML = _errBox('Nicht angemeldet.'); return; }
|
||||
|
||||
body.innerHTML = `<div style="text-align:center;color:var(--text2);padding:40px 0">Lade…</div>`;
|
||||
// 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 = `<div style="text-align:center;color:var(--text2);padding:40px 0">Lade…</div>`;
|
||||
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 {
|
||||
body.innerHTML = _errBox('Scrobble-Dienst nicht erreichbar.');
|
||||
if (body.dataset.req === token) body.innerHTML = _errBox('Scrobble-Dienst nicht erreichbar.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user