Merge pull request #1154 from Stremio/feat/hold-to-speedup

Player: Hold spacebar or left click to speed up 2x
This commit is contained in:
Timothy Z. 2026-03-11 17:26:49 +02:00 committed by GitHub
commit 89515a2a75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 60 additions and 7 deletions

View file

@ -96,6 +96,11 @@ const Player = ({ urlParams, queryParams }) => {
const isNavigating = React.useRef(false); const isNavigating = React.useRef(false);
const pressTimer = React.useRef(null);
const longPress = React.useRef(false);
const HOLD_DELAY = 200;
const onImplementationChanged = React.useCallback(() => { const onImplementationChanged = React.useCallback(() => {
video.setSubtitlesSize(settings.subtitlesSize); video.setSubtitlesSize(settings.subtitlesSize);
video.setSubtitlesOffset(settings.subtitlesOffset); video.setSubtitlesOffset(settings.subtitlesOffset);
@ -296,14 +301,14 @@ const Player = ({ urlParams, queryParams }) => {
}, [player.nextVideo, handleNextVideoNavigation, profile.settings]); }, [player.nextVideo, handleNextVideoNavigation, profile.settings]);
const onVideoClick = React.useCallback(() => { const onVideoClick = React.useCallback(() => {
if (video.state.paused !== null) { if (video.state.paused !== null && !longPress.current) {
if (video.state.paused) { if (video.state.paused) {
onPlayRequestedDebounced(); onPlayRequestedDebounced();
} else { } else {
onPauseRequestedDebounced(); onPauseRequestedDebounced();
} }
} }
}, [video.state.paused]); }, [video.state.paused, longPress.current]);
const onVideoDoubleClick = React.useCallback(() => { const onVideoDoubleClick = React.useCallback(() => {
onPlayRequestedDebounced.cancel(); onPlayRequestedDebounced.cancel();
@ -625,11 +630,11 @@ const Player = ({ urlParams, queryParams }) => {
if (video.state.paused) { if (video.state.paused) {
onPlayRequested(); onPlayRequested();
setSeeking(false); setSeeking(false);
} else { } else if (!pressTimer.current) {
onPauseRequested(); onPauseRequested();
} }
} }
}, [menusOpen, nextVideoPopupOpen, video.state.paused, onPlayRequested, onPauseRequested]); }, [menusOpen, nextVideoPopupOpen, video.state.paused, pressTimer.current, onPlayRequested, onPauseRequested]);
onShortcut('seekForward', (combo) => { onShortcut('seekForward', (combo) => {
if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) { if (!menusOpen && !nextVideoPopupOpen && video.state.time !== null) {
@ -726,11 +731,31 @@ const Player = ({ urlParams, queryParams }) => {
}, [settings.escExitFullscreen]); }, [settings.escExitFullscreen]);
React.useLayoutEffect(() => { React.useLayoutEffect(() => {
const onKeyUp = (event) => { const onKeyDown = (e) => {
if (event.code === 'ArrowRight' || event.code === 'ArrowLeft') { if (e.code !== 'Space' || e.repeat) return;
longPress.current = false;
pressTimer.current = setTimeout(() => {
longPress.current = true;
onPlaybackSpeedChanged(2);
}, HOLD_DELAY);
};
const onKeyUp = (e) => {
if (e.code !== 'Space' && e.code !== 'ArrowRight' && e.code !== 'ArrowLeft') return;
if (e.code === 'ArrowRight' || e.code === 'ArrowLeft') {
setSeeking(false); setSeeking(false);
return;
}
if (e.code === 'Space') {
clearTimeout(pressTimer.current);
pressTimer.current = null;
onPlaybackSpeedChanged(1);
} }
}; };
const onWheel = ({ deltaY }) => { const onWheel = ({ deltaY }) => {
if (menusOpen || video.state.volume === null) return; if (menusOpen || video.state.volume === null) return;
@ -742,13 +767,41 @@ const Player = ({ urlParams, queryParams }) => {
} }
} }
}; };
const onMouseDownHold = (e) => {
if (e.button !== 0) return; // left mouse button only
longPress.current = false;
pressTimer.current = setTimeout(() => {
longPress.current = true;
onPlaybackSpeedChanged(2);
}, HOLD_DELAY);
};
const onMouseUp = (e) => {
if (e.button !== 0) return;
clearTimeout(pressTimer.current);
if (longPress.current) {
onPlaybackSpeedChanged(1);
}
};
if (routeFocused) { if (routeFocused) {
window.addEventListener('keyup', onKeyUp); window.addEventListener('keyup', onKeyUp);
window.addEventListener('keydown', onKeyDown);
window.addEventListener('wheel', onWheel); window.addEventListener('wheel', onWheel);
window.addEventListener('mousedown', onMouseDownHold);
window.addEventListener('mouseup', onMouseUp);
} }
return () => { return () => {
window.removeEventListener('keyup', onKeyUp); window.removeEventListener('keyup', onKeyUp);
window.removeEventListener('keydown', onKeyDown);
window.removeEventListener('wheel', onWheel); window.removeEventListener('wheel', onWheel);
window.removeEventListener('mousedown', onMouseDownHold);
window.removeEventListener('mouseup', onMouseUp);
}; };
}, [routeFocused, menusOpen, video.state.volume]); }, [routeFocused, menusOpen, video.state.volume]);

View file

@ -15,7 +15,7 @@
.options-container { .options-container {
flex: 0 1 auto; flex: 0 1 auto;
max-height: calc(3.2rem * 8); max-height: calc(3.2rem * 10);
padding: 0 1rem 0.5rem; padding: 0 1rem 0.5rem;
.option { .option {