Add video player hotkeys
This commit is contained in:
parent
b836697e2a
commit
702000a493
|
|
@ -1,10 +1,21 @@
|
|||
import updateVideoProgressById from '../api/actions/updateVideoProgressById';
|
||||
import updateWatchedState from '../api/actions/updateWatchedState';
|
||||
import { SponsorBlockSegmentType, SponsorBlockType, VideoResponseType } from '../pages/Video';
|
||||
import { Dispatch, Fragment, SetStateAction, SyntheticEvent, useState } from 'react';
|
||||
import {
|
||||
Dispatch,
|
||||
Fragment,
|
||||
SetStateAction,
|
||||
SyntheticEvent,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import formatTime from '../functions/formatTime';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import getApiUrl from '../configuration/getApiUrl';
|
||||
import { useKeyPress } from '../functions/useKeypressHook';
|
||||
|
||||
const VIDEO_PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3];
|
||||
|
||||
type VideoTag = SyntheticEvent<HTMLVideoElement, Event>;
|
||||
|
||||
|
|
@ -109,10 +120,23 @@ const VideoPlayer = ({
|
|||
onWatchStateChanged,
|
||||
onVideoEnd,
|
||||
}: VideoPlayerProps) => {
|
||||
const videoRef = useRef<HTMLVideoElement | null>(null);
|
||||
|
||||
const [searchParams] = useSearchParams();
|
||||
const searchParamVideoProgress = searchParams.get('t');
|
||||
|
||||
const [skippedSegments, setSkippedSegments] = useState<SponsorSegmentsSkippedType>({});
|
||||
const [isMuted, setIsMuted] = useState(false);
|
||||
const [playbackSpeedIndex, setPlaybackSpeedIndex] = useState(3);
|
||||
const [lastSubtitleTack, setLastSubtitleTack] = useState(0);
|
||||
|
||||
// const questionmarkPressed = useKeyPress('?');
|
||||
const mutePressed = useKeyPress('m');
|
||||
const fullscreenPressed = useKeyPress('f');
|
||||
const subtitlesPressed = useKeyPress('c');
|
||||
const increasePlaybackSpeedPressed = useKeyPress('>');
|
||||
const decreasePlaybackSpeedPressed = useKeyPress('<');
|
||||
const resetPlaybackSpeedPressed = useKeyPress('=');
|
||||
|
||||
const videoId = video.data.youtube_id;
|
||||
const videoUrl = video.data.media_url;
|
||||
|
|
@ -153,11 +177,95 @@ const VideoPlayer = ({
|
|||
onVideoEnd?.();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (mutePressed) {
|
||||
setIsMuted(!isMuted);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [mutePressed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (increasePlaybackSpeedPressed) {
|
||||
const newSpeed = playbackSpeedIndex + 1;
|
||||
|
||||
if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeed]) {
|
||||
videoRef.current.playbackRate = VIDEO_PLAYBACK_SPEEDS[newSpeed];
|
||||
|
||||
setPlaybackSpeedIndex(newSpeed);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [increasePlaybackSpeedPressed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (decreasePlaybackSpeedPressed) {
|
||||
const newSpeedIndex = playbackSpeedIndex - 1;
|
||||
|
||||
if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]) {
|
||||
videoRef.current.playbackRate = VIDEO_PLAYBACK_SPEEDS[newSpeedIndex];
|
||||
|
||||
setPlaybackSpeedIndex(newSpeedIndex);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [decreasePlaybackSpeedPressed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (resetPlaybackSpeedPressed) {
|
||||
const newSpeedIndex = 3;
|
||||
|
||||
if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]) {
|
||||
videoRef.current.playbackRate = VIDEO_PLAYBACK_SPEEDS[newSpeedIndex];
|
||||
|
||||
setPlaybackSpeedIndex(newSpeedIndex);
|
||||
}
|
||||
}
|
||||
}, [resetPlaybackSpeedPressed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (fullscreenPressed) {
|
||||
if (videoRef.current && videoRef.current.requestFullscreen && !document.fullscreenElement) {
|
||||
videoRef.current.requestFullscreen();
|
||||
} else {
|
||||
document.exitFullscreen().catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [fullscreenPressed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (subtitlesPressed) {
|
||||
if (videoRef.current) {
|
||||
const tracks = [...videoRef.current.textTracks];
|
||||
|
||||
if (tracks.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const lastIndex = tracks.findIndex(x => x.mode === 'showing');
|
||||
const active = tracks[lastIndex];
|
||||
|
||||
if (!active && lastSubtitleTack !== 0) {
|
||||
tracks[lastSubtitleTack - 1].mode = 'showing';
|
||||
} else {
|
||||
if (active) {
|
||||
active.mode = 'hidden';
|
||||
|
||||
setLastSubtitleTack(lastIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [subtitlesPressed]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="player" className={embed ? '' : 'player-wrapper'}>
|
||||
<div className={embed ? '' : 'video-main'}>
|
||||
<video
|
||||
ref={videoRef}
|
||||
key={`${getApiUrl()}${videoUrl}`}
|
||||
poster={`${getApiUrl()}${videoThumbUrl}`}
|
||||
onVolumeChange={(videoTag: VideoTag) => {
|
||||
|
|
@ -196,6 +304,7 @@ const VideoPlayer = ({
|
|||
width="100%"
|
||||
playsInline
|
||||
id="video-item"
|
||||
muted={isMuted}
|
||||
>
|
||||
<source
|
||||
src={`${getApiUrl()}${videoUrl}#t=${videoSrcProgress}`}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
|
||||
// source: https://thibault.sh/react-hooks/use-key-press
|
||||
export function useKeyPress(targetKey: string) {
|
||||
const [isKeyPressed, setIsKeyPressed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === targetKey) {
|
||||
setIsKeyPressed(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyUp = (event: KeyboardEvent) => {
|
||||
if (event.key === targetKey) {
|
||||
setIsKeyPressed(false);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
window.addEventListener('keyup', handleKeyUp);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
window.removeEventListener('keyup', handleKeyUp);
|
||||
};
|
||||
}, [targetKey]);
|
||||
|
||||
return isKeyPressed;
|
||||
}
|
||||
Loading…
Reference in New Issue