Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@saas786
Forked from KrustyC/ReactJWPlayer.tsx
Created April 2, 2020 09:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saas786/35e6437c7a784ca53e07277daf984954 to your computer and use it in GitHub Desktop.
Save saas786/35e6437c7a784ca53e07277daf984954 to your computer and use it in GitHub Desktop.
import * as React from 'react';
import PropTypes from 'prop-types';
import { JWPlayerProps, JWPlayerInstance } from './types';
import useJWPlayer from './hooks/useJWPlayer';
import useScript from './hooks/useScript';
const ReactJWPlayer = React.forwardRef((props: JWPlayerProps, ref?: JWPlayerInstance) => {
const { isScriptLoaded, isError } = useScript(props.playerId);
const { playerInstance, playerElement } = useJWPlayer(props, isScriptLoaded);
if (ref) {
React.useImperativeHandle(ref, () => playerInstance)
}
if (!isScriptLoaded) {
return <div>Loading...</div>;
}
if (isError) {
return <div>Error...</div>;
}
return <div id={`${props.playerId}-${Math.random()}`} ref={playerElement} />;
});
ReactJWPlayer.displayName = 'ReactJWPlayer';
ReactJWPlayer.propTypes = {
playerId: PropTypes.string.isRequired,
// playerOptions: PropTypes.shape({
// playlistId: PropTypes.string.isRequired,
// aspectratio: PropTypes.oneOf(['true', 'false', 'viewable']),
// autostart: PropTypes.string,
// height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
// mute: PropTypes.bool,
// repeat: PropTypes.bool,
// stretching: PropTypes.oneOf(['uniform', 'exactfit', 'fill', 'none']),
// volume: PropTypes.number,
// type: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
// }).isRequired,
onAdBlock: PropTypes.func,
onAdClick: PropTypes.func,
onAdCompanions: PropTypes.func,
onAdComplete: PropTypes.func,
onAdError: PropTypes.func,
onAdImpression: PropTypes.func,
onAdPause: PropTypes.func,
onAdPlay: PropTypes.func,
onAdRequest: PropTypes.func,
onAdSchedule: PropTypes.func,
onAdSkipped: PropTypes.func,
onAdStarted: PropTypes.func,
onAdTime: PropTypes.func,
onAudioTracks: PropTypes.func,
onAudioTrackChanged: PropTypes.func,
onBeforeComplete: PropTypes.func,
onBeforePlay: PropTypes.func,
onBuffer: PropTypes.func,
onBufferChange: PropTypes.func,
onCast: PropTypes.func,
onCaptionsChanged: PropTypes.func,
onCaptionsList: PropTypes.func,
onComplete: PropTypes.func,
onControls: PropTypes.func,
onDisplayClick: PropTypes.func,
onError: PropTypes.func,
onFirstFrame: PropTypes.func,
onIdle: PropTypes.func,
onFullscreen: PropTypes.func,
onLevels: PropTypes.func,
onLevelsChanged: PropTypes.func,
onMeta: PropTypes.func,
onMute: PropTypes.func,
onPause: PropTypes.func,
onPlay: PropTypes.func,
onPlaylist: PropTypes.func,
onPlaylistComplete: PropTypes.func,
onPlaylistItem: PropTypes.func,
onPlayAttemptFailed: PropTypes.func,
onReady: PropTypes.func,
onResize: PropTypes.func,
onSeek: PropTypes.func,
onSeeked: PropTypes.func,
onSetupError: PropTypes.func,
onTime: PropTypes.func,
onVisualQuality: PropTypes.func,
onVolume: PropTypes.func,
};
ReactJWPlayer.defaultProps = {
onAdBlock: null,
onAdClick: null,
onAdCompanions: null,
onAdComplete: null,
onAdError: null,
onAdImpression: null,
onAdPause: null,
onAdPlay: null,
onAdRequest: null,
onAdSchedule: null,
onAdSkipped: null,
onAdStarted: null,
onAdTime: null,
onAudioTracks: null,
onAudioTrackChanged: null,
onBeforeComplete: null,
onBeforePlay: null,
onBuffer: null,
onBufferChange: null,
onCast: null,
onCaptionsChanged: null,
onCaptionsList: null,
onComplete: null,
onControls: null,
onDisplayClick: null,
onError: null,
onFirstFrame: null,
onIdle: null,
onFullscreen: null,
onLevels: null,
onLevelsChanged: null,
onMeta: null,
onMute: null,
onPause: null,
onPlay: null,
onPlaylist: null,
onPlaylistComplete: null,
onPlaylistItem: null,
onPlayAttemptFailed: null,
onReady: null,
onResize: null,
onSeek: null,
onSeeked: null,
onSetupError: null,
onTime: null,
onVisualQuality: null,
onVolume: null,
};
export default ReactJWPlayer;
import * as React from 'react';
import { JWPlayerProps, WindowWithJwPlayer, JWPlayerElement, JWPlayerInstance } from '../../types';
import { JW_PLAYLIST_URL, EVENT_NAME_TO_FUNCTION_MAP } from '../../constants';
interface JWPLayerRefs {
playerElement: JWPlayerElement;
playerInstance: jwplayer.JWPlayer;
}
const windowHasJwPlayer = (window: Window): window is WindowWithJwPlayer =>
window && typeof (window as any).jwplayer === 'function';
const useJWPlayer = (props: JWPlayerProps, isScriptLoaded: boolean): JWPLayerRefs => {
const playerElement = React.useRef<HTMLDivElement | null>(null);
const [playerInstance, setPlayerInstance] = React.useState<jwplayer.JWPlayer | null>(null);
React.useEffect(() => {
if (!windowHasJwPlayer(window)) {
return;
}
if (!isScriptLoaded || playerElement.current === null) {
return;
}
const defaultOptions = (window.jwplayer as any).defaults;
const {
playerOptions: { playlistId, ...otherPlayerOptions },
} = props;
const pobjetc = window.jwplayer(playerElement.current); // @TODO find a proper name
pobjetc.setup({
...defaultOptions,
...otherPlayerOptions,
playlist: `${JW_PLAYLIST_URL}/${playlistId}`,
});
// const events = Object.entries(EVENT_NAME_TO_FUNCTION_MAP).map(([eventKey, propame]) => {
// console.log(eventKey, propame);
// });
// // @TODO ask John how to deal with the type system
// const events = Object.keys(EVENT_NAME_TO_FUNCTION_MAP).map((eventKey: any) => []);
setPlayerInstance(pobjetc);
// return () => playerInstance.remove();
}, [isScriptLoaded]);
React.useEffect(() => {
return { playerInstance, playerElement };
};
export default useJWPlayer;
import * as React from 'react';
import { JW_PLAYER_URL } from '../../constants';
const useScript = (playerId: string) => {
const [isScriptLoaded, setIsScriptLoaded] = React.useState(false);
const [isError, setIsError] = React.useState(false);
React.useEffect(() => {
const script = document.createElement('script');
script.setAttribute('src', `${JW_PLAYER_URL}/${playerId}.js`);
script.setAttribute('type', 'text/javascript');
script.setAttribute('async', 'true');
script.addEventListener('load', () => setIsScriptLoaded(true));
script.addEventListener('error', () => setIsError(true));
document.body.appendChild(script);
return () => {
script.remove();
};
}, []);
return { isScriptLoaded, isError };
};
export default useScript;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment