diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-02 22:50:26 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-02 22:50:26 +0300 |
| commit | 0482a98c538cbe9ca32b4775bd897b9c728cf686 (patch) | |
| tree | 226bcd3b3d9c6b8330cff531de40f5c137291879 /web/js/detach.js | |
| parent | daccc2fd2c43545fe2a904cccb1f866e38817a10 (diff) | |
add playback navigation shortcuts
Diffstat (limited to 'web/js/detach.js')
| -rw-r--r-- | web/js/detach.js | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/web/js/detach.js b/web/js/detach.js index f884231..d255b2e 100644 --- a/web/js/detach.js +++ b/web/js/detach.js @@ -35,6 +35,7 @@ window.__playerDetachCurrentState = currentState; lastStateSent = now; } }); + el?.addEventListener('ended', () => post({ type: 'detach-next' })); }); document.addEventListener('keydown', (ev) => { @@ -48,6 +49,12 @@ document.addEventListener('keydown', (ev) => { } else if (ev.key === 'f') { ev.preventDefault(); toggleFullscreen(); + } else if (ev.key === 'ArrowLeft' || ev.key === 'h') { + ev.preventDefault(); + seekRelative(ev.repeat ? -15 : -5); + } else if (ev.key === 'ArrowRight' || ev.key === 'l') { + ev.preventDefault(); + seekRelative(ev.repeat ? 15 : 5); } }); @@ -63,7 +70,7 @@ window.addEventListener('message', (ev) => { loadDetachedMedia(ev.data); break; case 'detach-command': - handleCommand(ev.data.action); + handleCommand(ev.data); break; case 'detach-request-state': sendState(); @@ -97,7 +104,8 @@ function loadDetachedMedia(payload) { sendState(); } -function handleCommand(action) { +function handleCommand(payload) { + const action = payload?.action; if (action === 'toggle-play') { togglePlayback(); } else if (action === 'pause') { @@ -108,6 +116,8 @@ function handleCommand(action) { const el = mediaElement(); if (!el) return; el.play().catch(() => {}); + } else if (action === 'seek-relative') { + seekRelative(Number(payload.seconds || 0)); } } @@ -118,6 +128,14 @@ function togglePlayback() { else el.pause(); } +function seekRelative(seconds) { + const el = mediaElement(); + if (!currentMedia || !el || !isFinite(seconds)) return; + const upper = el.duration && isFinite(el.duration) ? el.duration : Infinity; + el.currentTime = Math.max(0, Math.min(upper, (el.currentTime || 0) + seconds)); + sendState(); +} + function toggleFullscreen() { const player = document.getElementById('player'); if (!player) return; |
