91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import type { ElementRef } from '../../lib/teact/teact';
|
|
import type React from '../../lib/teact/teact';
|
|
import { memo, useMemo, useRef } from '../../lib/teact/teact';
|
|
|
|
import useBuffering from '../../hooks/useBuffering';
|
|
import useLastCallback from '../../hooks/useLastCallback';
|
|
import useSyncEffect from '../../hooks/useSyncEffect';
|
|
import useVideoCleanup from '../../hooks/useVideoCleanup';
|
|
import useVideoAutoPause from '../middle/message/hooks/useVideoAutoPause';
|
|
|
|
type VideoProps = React.DetailedHTMLProps<React.VideoHTMLAttributes<HTMLVideoElement>, HTMLVideoElement>;
|
|
|
|
type OwnProps =
|
|
{
|
|
ref?: ElementRef<HTMLVideoElement>;
|
|
isPriority?: boolean;
|
|
canPlay: boolean;
|
|
children?: React.ReactNode;
|
|
onReady?: NoneToVoidFunction;
|
|
onBroken?: NoneToVoidFunction;
|
|
}
|
|
& VideoProps;
|
|
|
|
function OptimizedVideo({
|
|
ref,
|
|
isPriority,
|
|
canPlay,
|
|
children,
|
|
onReady,
|
|
onBroken,
|
|
onTimeUpdate,
|
|
...restProps
|
|
}: OwnProps) {
|
|
const localRef = useRef<HTMLVideoElement>();
|
|
if (!ref) {
|
|
ref = localRef;
|
|
}
|
|
|
|
const { handlePlaying: handlePlayingForAutoPause } = useVideoAutoPause(ref, canPlay, isPriority);
|
|
|
|
const isReadyRef = useRef(false);
|
|
const handleReady = useLastCallback(() => {
|
|
if (!isReadyRef.current) {
|
|
onReady?.();
|
|
isReadyRef.current = true;
|
|
}
|
|
});
|
|
|
|
// This is only needed for browsers not allowing autoplay
|
|
const { isBuffered, bufferingHandlers } = useBuffering(true, onTimeUpdate, onBroken);
|
|
const { onPlaying: handlePlayingForBuffering, ...otherBufferingHandlers } = bufferingHandlers;
|
|
useSyncEffect(([prevIsBuffered]) => {
|
|
if (prevIsBuffered === undefined) {
|
|
return;
|
|
}
|
|
|
|
handleReady();
|
|
}, [isBuffered, handleReady]);
|
|
|
|
const handlePlaying = useLastCallback((e) => {
|
|
handlePlayingForAutoPause();
|
|
handlePlayingForBuffering(e);
|
|
handleReady();
|
|
restProps.onPlaying?.(e);
|
|
});
|
|
|
|
const mergedOtherBufferingHandlers = useMemo(() => {
|
|
const mergedHandlers: Record<string, AnyFunction> = {};
|
|
Object.keys(otherBufferingHandlers).forEach((keyString) => {
|
|
const key = keyString as keyof typeof otherBufferingHandlers;
|
|
mergedHandlers[key] = (event: Event) => {
|
|
restProps[key as keyof typeof restProps]?.(event);
|
|
otherBufferingHandlers[key]?.(event);
|
|
};
|
|
});
|
|
|
|
return mergedHandlers;
|
|
}, [otherBufferingHandlers, restProps]);
|
|
|
|
useVideoCleanup(ref, mergedOtherBufferingHandlers);
|
|
|
|
return (
|
|
|
|
<video ref={ref} autoPlay {...restProps} {...mergedOtherBufferingHandlers} onPlaying={handlePlaying}>
|
|
{children}
|
|
</video>
|
|
);
|
|
}
|
|
|
|
export default memo(OptimizedVideo);
|