Add most events

This commit is contained in:
Zoe Roux 2024-06-30 11:25:43 +00:00
parent c6abcdeb2f
commit f5fa063bc0
No known key found for this signature in database

View File

@ -14,10 +14,15 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
paused, paused,
muted, muted,
volume, volume,
showNotificationControls,
onBuffer, onBuffer,
onLoad, onLoad,
onProgress, onProgress,
onPlaybackRateChange,
onError, onError,
onReadyForDisplay,
onSeek,
onVolumeChange,
onEnd, onEnd,
onPlaybackStateChanged, onPlaybackStateChanged,
}, },
@ -27,16 +32,20 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
const errorHandler = useRef<typeof onError>(onError); const errorHandler = useRef<typeof onError>(onError);
errorHandler.current = onError; errorHandler.current = onError;
const seek = useCallback(async (time: number, _tolerance?: number) => { const seek = useCallback(
if (isNaN(time)) { async (time: number, _tolerance?: number) => {
throw new Error('Specified time is not a number'); if (isNaN(time)) {
} throw new Error('Specified time is not a number');
if (!nativeRef.current) { }
console.warn('Video Component is not mounted'); if (!nativeRef.current) {
return; console.warn('Video Component is not mounted');
} return;
nativeRef.current.currentTime = time; }
}, []); nativeRef.current.currentTime = time;
onSeek?.({seekTime: time, currentTime: nativeRef.current.currentTime});
},
[onSeek],
);
const pause = useCallback(() => { const pause = useCallback(() => {
if (!nativeRef.current) { if (!nativeRef.current) {
@ -52,6 +61,20 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
nativeRef.current.play(); nativeRef.current.play();
}, []); }, []);
const setVolume = useCallback((vol: number) => {
if (!nativeRef.current) {
return;
}
nativeRef.current.volume = Math.max(0, Math.min(vol, 100)) / 100;
}, []);
const getCurrentPosition = useCallback(async () => {
if (!nativeRef.current) {
throw new Error('Video Component is not mounted');
}
return nativeRef.current.currentTime;
}, []);
const unsupported = useCallback(() => { const unsupported = useCallback(() => {
throw new Error('This is unsupported on the web'); throw new Error('This is unsupported on the web');
}, []); }, []);
@ -62,14 +85,17 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
seek, seek,
pause, pause,
resume, resume,
setVolume,
getCurrentPosition,
// making the video fullscreen does not work with some subtitles polyfils // making the video fullscreen does not work with some subtitles polyfils
// so I decided to not include it. // so I decided to not include it.
presentFullscreenPlayer: unsupported, presentFullscreenPlayer: unsupported,
dismissFullscreenPlayer: unsupported, dismissFullscreenPlayer: unsupported,
setFullScreen: unsupported,
save: unsupported, save: unsupported,
restoreUserInterfaceForPictureInPictureStopCompleted: unsupported, restoreUserInterfaceForPictureInPictureStopCompleted: unsupported,
}), }),
[seek, pause, resume, unsupported], [seek, pause, resume, unsupported, setVolume, getCurrentPosition],
); );
useEffect(() => { useEffect(() => {
@ -80,24 +106,31 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
} }
}, [paused, pause, resume]); }, [paused, pause, resume]);
useEffect(() => { useEffect(() => {
if (!nativeRef.current || !volume) { if (volume === undefined) {
return; return;
} }
nativeRef.current.volume = Math.max(0, Math.min(volume, 100)) / 100; setVolume(volume);
}, [volume]); }, [volume, setVolume]);
const setPlay = useSetAtom(playAtom);
useEffect(() => { useEffect(() => {
if (!nativeRef.current) return; // Not sure about how to do this but we want to wait for nativeRef to be initialized
// Set play state to the player's value (if autoplay is denied) setTimeout(() => {
setPlay(!nativeRef.current.paused); if (!nativeRef.current) {
}, [setPlay]); return;
}
const setProgress = useSetAtom(progressAtom); // Set play state to the player's value (if autoplay is denied)
// This is useful if our UI is in a play state but autoplay got denied so
// the video is actaully in a paused state.
onPlaybackStateChanged?.({isPlaying: !nativeRef.current.paused});
}, 500);
}, [onPlaybackStateChanged]);
return ( return (
<> <>
<MediaSessionManager {...source.metadata} /> {showNotificationControls && (
<MediaSessionManager {...source.metadata} />
)}
<video <video
ref={nativeRef} ref={nativeRef}
src={source.uri as string | undefined} src={source.uri as string | undefined}
@ -107,11 +140,30 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
playsInline playsInline
onCanPlay={() => onBuffer?.({isBuffering: false})} onCanPlay={() => onBuffer?.({isBuffering: false})}
onWaiting={() => onBuffer?.({isBuffering: true})} onWaiting={() => onBuffer?.({isBuffering: true})}
onRateChange={() => {
if (!nativeRef.current) {
return;
}
onPlaybackRateChange?.({
playbackRate: nativeRef.current?.playbackRate,
});
}}
onDurationChange={() => { onDurationChange={() => {
if (!nativeRef.current) { if (!nativeRef.current) {
return; return;
} }
onLoad?.({duration: nativeRef.current.duration} as any); onLoad?.({
currentTime: nativeRef.current.currentTime,
duration: nativeRef.current.duration,
videoTracks: [],
textTracks: [],
audioTracks: [],
naturalSize: {
width: nativeRef.current.videoWidth,
height: nativeRef.current.videoHeight,
orientation: 'landscape',
},
});
}} }}
onTimeUpdate={() => { onTimeUpdate={() => {
if (!nativeRef.current) { if (!nativeRef.current) {
@ -127,6 +179,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
seekableDuration: 0, seekableDuration: 0,
}); });
}} }}
onLoadedData={() => onReadyForDisplay?.()}
onError={() => { onError={() => {
if ( if (
nativeRef?.current?.error?.code === nativeRef?.current?.error?.code ===
@ -147,6 +200,12 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
}} }}
onPlay={() => onPlaybackStateChanged?.({isPlaying: true})} onPlay={() => onPlaybackStateChanged?.({isPlaying: true})}
onPause={() => onPlaybackStateChanged?.({isPlaying: false})} onPause={() => onPlaybackStateChanged?.({isPlaying: false})}
onVolumeChange={() => {
if (!nativeRef.current) {
return;
}
onVolumeChange?.({volume: nativeRef.current.volume});
}}
onEnded={onEnd} onEnded={onEnd}
style={{position: 'absolute', inset: 0, objectFit: 'contain'}} style={{position: 'absolute', inset: 0, objectFit: 'contain'}}
/> />