Add help dialog to video player

This commit is contained in:
MerlinScheurer 2025-02-01 13:28:19 +01:00
parent c41872b6b7
commit 3fcef13f14
2 changed files with 121 additions and 7 deletions

View File

@ -128,14 +128,19 @@ const VideoPlayer = ({
const [isMuted, setIsMuted] = useState(false); const [isMuted, setIsMuted] = useState(false);
const [playbackSpeedIndex, setPlaybackSpeedIndex] = useState(3); const [playbackSpeedIndex, setPlaybackSpeedIndex] = useState(3);
const [lastSubtitleTack, setLastSubtitleTack] = useState(0); const [lastSubtitleTack, setLastSubtitleTack] = useState(0);
const [showHelpDialog, setShowHelpDialog] = useState(false);
const [showInfoDialog, setShowInfoDialog] = useState(false);
const [infoDialogContent, setInfoDialogContent] = useState('');
// const questionmarkPressed = useKeyPress('?'); const questionmarkPressed = useKeyPress('?');
const mutePressed = useKeyPress('m'); const mutePressed = useKeyPress('m');
const fullscreenPressed = useKeyPress('f'); const fullscreenPressed = useKeyPress('f');
const subtitlesPressed = useKeyPress('c'); const subtitlesPressed = useKeyPress('c');
const increasePlaybackSpeedPressed = useKeyPress('>'); const increasePlaybackSpeedPressed = useKeyPress('>');
const decreasePlaybackSpeedPressed = useKeyPress('<'); const decreasePlaybackSpeedPressed = useKeyPress('<');
const resetPlaybackSpeedPressed = useKeyPress('='); const resetPlaybackSpeedPressed = useKeyPress('=');
const arrowRightPressed = useKeyPress('ArrowRight');
const arrowLeftPressed = useKeyPress('ArrowLeft');
const videoId = video.data.youtube_id; const videoId = video.data.youtube_id;
const videoUrl = video.data.media_url; const videoUrl = video.data.media_url;
@ -151,6 +156,16 @@ const VideoPlayer = ({
videoSrcProgress = searchParamVideoProgress; videoSrcProgress = searchParamVideoProgress;
} }
const infoDialog = (content: string) => {
setInfoDialogContent(content);
setShowInfoDialog(true);
setTimeout(() => {
setShowInfoDialog(false);
setInfoDialogContent('');
}, 500);
};
const handleVideoEnd = const handleVideoEnd =
( (
youtubeId: string, youtubeId: string,
@ -194,9 +209,11 @@ const VideoPlayer = ({
const newSpeed = playbackSpeedIndex + 1; const newSpeed = playbackSpeedIndex + 1;
if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeed]) { if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeed]) {
videoRef.current.playbackRate = VIDEO_PLAYBACK_SPEEDS[newSpeed]; const speed = VIDEO_PLAYBACK_SPEEDS[newSpeed];
videoRef.current.playbackRate = speed;
setPlaybackSpeedIndex(newSpeed); setPlaybackSpeedIndex(newSpeed);
infoDialog(`${speed}x`);
} }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -207,9 +224,11 @@ const VideoPlayer = ({
const newSpeedIndex = playbackSpeedIndex - 1; const newSpeedIndex = playbackSpeedIndex - 1;
if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]) { if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]) {
videoRef.current.playbackRate = VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]; const speed = VIDEO_PLAYBACK_SPEEDS[newSpeedIndex];
videoRef.current.playbackRate = speed;
setPlaybackSpeedIndex(newSpeedIndex); setPlaybackSpeedIndex(newSpeedIndex);
infoDialog(`${speed}x`);
} }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -220,9 +239,11 @@ const VideoPlayer = ({
const newSpeedIndex = 3; const newSpeedIndex = 3;
if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]) { if (videoRef.current && VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]) {
videoRef.current.playbackRate = VIDEO_PLAYBACK_SPEEDS[newSpeedIndex]; const speed = VIDEO_PLAYBACK_SPEEDS[newSpeedIndex];
videoRef.current.playbackRate = speed;
setPlaybackSpeedIndex(newSpeedIndex); setPlaybackSpeedIndex(newSpeedIndex);
infoDialog(`${speed}x`);
} }
} }
}, [resetPlaybackSpeedPressed]); }, [resetPlaybackSpeedPressed]);
@ -230,10 +251,14 @@ const VideoPlayer = ({
useEffect(() => { useEffect(() => {
if (fullscreenPressed) { if (fullscreenPressed) {
if (videoRef.current && videoRef.current.requestFullscreen && !document.fullscreenElement) { if (videoRef.current && videoRef.current.requestFullscreen && !document.fullscreenElement) {
videoRef.current.requestFullscreen(); videoRef.current.requestFullscreen().catch(e => {
console.error(e);
infoDialog('Unable to enter fullscreen');
});
} else { } else {
document.exitFullscreen().catch(e => { document.exitFullscreen().catch(e => {
console.error(e); console.error(e);
infoDialog('Unable to exit fullscreen');
}); });
} }
} }
@ -265,6 +290,31 @@ const VideoPlayer = ({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [subtitlesPressed]); }, [subtitlesPressed]);
useEffect(() => {
if (arrowLeftPressed) {
infoDialog('- 5 seconds');
}
}, [arrowLeftPressed]);
useEffect(() => {
if (arrowRightPressed) {
infoDialog('+ 5 seconds');
}
}, [arrowRightPressed]);
useEffect(() => {
if (questionmarkPressed) {
if (!showHelpDialog) {
setTimeout(() => {
setShowHelpDialog(false);
}, 3000);
}
setShowHelpDialog(!showHelpDialog);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [questionmarkPressed]);
return ( return (
<> <>
<div id="player" className={embed ? '' : 'player-wrapper'}> <div id="player" className={embed ? '' : 'player-wrapper'}>
@ -320,6 +370,60 @@ const VideoPlayer = ({
</video> </video>
</div> </div>
</div> </div>
<dialog className="video-modal" open={showHelpDialog}>
<div className="video-modal-text">
<table className="video-modal-table">
<tbody>
<tr>
<td>Show help</td>
<td>?</td>
</tr>
<tr>
<td>Toggle mute</td>
<td>m</td>
</tr>
<tr>
<td>Toggle fullscreen</td>
<td>f</td>
</tr>
<tr>
<td>Toggle subtitles (if available)</td>
<td>c</td>
</tr>
<tr>
<td>Increase speed</td>
<td>&gt;</td>
</tr>
<tr>
<td>Decrease speed</td>
<td>&lt;</td>
</tr>
<tr>
<td>Reset speed</td>
<td>=</td>
</tr>
<tr>
<td>Back 5 seconds</td>
<td></td>
</tr>
<tr>
<td>Forward 5 seconds</td>
<td></td>
</tr>
</tbody>
</table>
<form className="video-modal-form" method="dialog">
<button>Close</button>
</form>
</div>
</dialog>
<dialog className="video-modal" open={showInfoDialog}>
<div className="video-modal-text">{infoDialogContent}</div>
</dialog>
<div className="sponsorblock" id="sponsorblock"> <div className="sponsorblock" id="sponsorblock">
{sponsorBlock?.is_enabled && ( {sponsorBlock?.is_enabled && (
<> <>

View File

@ -790,7 +790,8 @@ video:-webkit-full-screen {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
top: 20%; top: 20%;
width: 100%; transform: translateX(-50%);
left: 50%;
text-align: center; text-align: center;
} }
@ -798,7 +799,16 @@ video:-webkit-full-screen {
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
color: #eeeeee; color: #eeeeee;
font-size: 1.3em; font-size: 1.3em;
display: none; }
.video-modal-table {
margin: auto;
background: rgba(0, 0, 0, 0.5);
}
.video-modal-form {
margin: auto;
background: rgba(0, 0, 0, 0.5);
} }
.video-main video { .video-main video {