fix: audioSession playback type, exponential backoff, pageshow recovery

- Set navigator.audioSession.type = 'playback' on first play — tells Android
  OS this is a music app, keeping background network alive through Doze mode
- Replace flat 2s error retry with exponential backoff (1s/2s/4s/8s)
- Add pageshow event alongside visibilitychange for Samsung/iOS PWA reliability
- Attempt audio resume on foreground if OS killed playback while backgrounded
- Switch preload from hidden audio element to link rel=prefetch (lighter,
  avoids triggering two-audio-stream detection on Android)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-03 21:34:23 +02:00
1 parent 502427d02c
commit 33dc07ed5d
2 files changed
+30 -15

No files matched your search

+11 -8
View File
@@ -5,10 +5,10 @@ import { api, streamUrl, coverUrl, downloadUrl } from './api.js';
import { loadRecommendations } from './views.js';
import { updateLyricsHighlight, onNpSongChange } from './nowplaying.js';
// ─── PRELOAD (keeps network alive through Doze mode gap between tracks) ───
let _preAudio = null;
let _preUrl = '';
let _preId = '';
// ─── PRELOAD (resource hint keeps connection open through Doze gap) ───
let _preUrl = '';
let _preId = '';
let _preLink = null;
function _nextIdx() {
if(S.repeat === 'one') return S.qIdx;
@@ -25,14 +25,17 @@ function _preloadNext() {
if(!next || _preId === next.id) return;
_preId = next.id;
_preUrl = streamUrl(next.id); // generate URL once — reused by main element
if(!_preAudio) { _preAudio = new Audio(); _preAudio.preload = 'auto'; }
_preAudio.volume = 0;
_preAudio.src = _preUrl; // Chrome starts buffering immediately
if(_preLink) _preLink.remove();
_preLink = document.createElement('link');
_preLink.rel = 'prefetch';
_preLink.as = 'fetch';
_preLink.href = _preUrl;
document.head.appendChild(_preLink);
}
function _clearPreload() {
_preId = ''; _preUrl = '';
if(_preAudio) { _preAudio.src = ''; }
if(_preLink) { _preLink.remove(); _preLink = null; }
}
// ─── PLAYBACK ───