Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdbe48ce1a |
@@ -192,6 +192,50 @@
|
||||
return () => clearTimeout(id);
|
||||
});
|
||||
|
||||
// ── MediaSession action handlers ────────────────────────────────────────────
|
||||
// Without explicit handlers, iOS Safari loses lock-screen resume ability after
|
||||
// ~1 minute of pause because it falls back to its own default which doesn't
|
||||
// satisfy the user-gesture requirement for <audio>.play().
|
||||
// Handlers registered here call audioEl directly so iOS trusts the gesture.
|
||||
$effect(() => {
|
||||
if (typeof navigator === 'undefined' || !('mediaSession' in navigator) || !audioEl) return;
|
||||
const el = audioEl; // capture for closure
|
||||
|
||||
navigator.mediaSession.setActionHandler('play', () => {
|
||||
el.play().catch(() => {});
|
||||
});
|
||||
navigator.mediaSession.setActionHandler('pause', () => {
|
||||
el.pause();
|
||||
});
|
||||
navigator.mediaSession.setActionHandler('seekbackward', (d) => {
|
||||
el.currentTime = Math.max(0, el.currentTime - (d.seekOffset ?? 15));
|
||||
});
|
||||
navigator.mediaSession.setActionHandler('seekforward', (d) => {
|
||||
el.currentTime = Math.min(el.duration || 0, el.currentTime + (d.seekOffset ?? 30));
|
||||
});
|
||||
// previoustrack / nexttrack fall back to skip ±30s if no chapter nav available
|
||||
try {
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
||||
el.currentTime = Math.max(0, el.currentTime - 30);
|
||||
});
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
||||
el.currentTime = Math.min(el.duration || 0, el.currentTime + 30);
|
||||
});
|
||||
} catch { /* some browsers don't support these */ }
|
||||
|
||||
return () => {
|
||||
(['play', 'pause', 'seekbackward', 'seekforward'] as MediaSessionAction[]).forEach((a) => {
|
||||
try { navigator.mediaSession.setActionHandler(a, null); } catch { /* ignore */ }
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
// Keep playbackState in sync so iOS lock screen shows the right button state
|
||||
$effect(() => {
|
||||
if (typeof navigator === 'undefined' || !('mediaSession' in navigator)) return;
|
||||
navigator.mediaSession.playbackState = audioStore.isPlaying ? 'playing' : 'paused';
|
||||
});
|
||||
|
||||
// ── Save audio time on pause/end (debounced 2s) ─────────────────────────
|
||||
let audioTimeSaveTimer = 0;
|
||||
function saveAudioTime() {
|
||||
|
||||
Reference in New Issue
Block a user