import React, { Component, createRef, EventHandler, HTMLAttributes, MutableRefObject, SyntheticEvent } from 'react';
import { CloudinaryImage, CloudinaryVideo } from '@cloudinary/url-gen';
import {
HtmlVideoLayer,
Plugins,
VideoPoster,
VideoSources,
cancelCurrentlyRunningPlugins
} from '@cloudinary/html';
type ReactEventHandler<T = Element> = EventHandler<SyntheticEvent<T>>;
interface VideoProps extends HTMLAttributes<HTMLVideoElement>{
cldVid: CloudinaryVideo,
cldPoster?: VideoPoster,
plugins?: Plugins,
sources?: VideoSources,
innerRef?: ((instance: any) => void) | MutableRefObject<unknown> | null
controls?: boolean
loop?: boolean,
muted?: boolean,
poster?: string,
preload?: string,
autoPlay?: boolean,
playsInline?: boolean
onPlay?: ReactEventHandler<any>,
onLoadStart?: ReactEventHandler<any>,
onPlaying?: ReactEventHandler<any>,
onError?: ReactEventHandler<any>,
onEnded?: ReactEventHandler<any>
}
const VIDEO_ATTRIBUTES_KEYS: string[] = ['controls', 'loop', 'muted', 'poster', 'preload', 'autoplay', 'playsinline'];
class AdvancedVideo extends Component <VideoProps> {
videoRef: MutableRefObject<HTMLVideoElement | null>
htmlVideoLayerInstance: HtmlVideoLayer;
constructor(props: VideoProps) {
super(props);
this.videoRef = createRef();
this.attachRef = this.attachRef.bind(this);
}
componentDidMount() {
this.htmlVideoLayerInstance = new HtmlVideoLayer(
this.videoRef && this.videoRef.current,
this.props.cldVid,
this.props.sources,
this.props.plugins,
this.getVideoAttributes(),
this.props.cldPoster
)
}
componentDidUpdate() {
cancelCurrentlyRunningPlugins(this.htmlVideoLayerInstance.htmlPluginState);
this.htmlVideoLayerInstance.update(
this.props.cldVid,
this.props.sources,
this.props.plugins,
this.getVideoAttributes(),
this.props.cldPoster
)
}
componentWillUnmount() {
cancelCurrentlyRunningPlugins(this.htmlVideoLayerInstance.htmlPluginState)
}
getVideoAttributes() {
const result = {};
VIDEO_ATTRIBUTES_KEYS.forEach((key: string) => {
if (key in this.props) {
result[key] = this.props[key];
}
});
return result;
}
attachRef(element: HTMLVideoElement) {
this.videoRef.current = element;
const { innerRef } = this.props;
if (innerRef) {
if (innerRef instanceof Function) {
innerRef(element);
} else {
innerRef.current = element;
}
}
};
render() {
const {
cldVid,
cldPoster,
plugins,
sources,
innerRef,
...videoAttrs
} = this.props;
return <video {...videoAttrs} ref={this.attachRef} />
}
}
export { AdvancedVideo };