UNPKG

wotnot-video-react

Version:

Video-React is a web video player built from the ground up for an HTML5 world using React library.

1,891 lines (1,635 loc) 133 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var PropTypes = _interopDefault(require('prop-types')); var React = require('react'); var React__default = _interopDefault(React); var classNames = _interopDefault(require('classnames')); var redux = require('redux'); function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } var LOAD_START = 'video-react/LOAD_START'; var CAN_PLAY = 'video-react/CAN_PLAY'; var WAITING = 'video-react/WAITING'; var CAN_PLAY_THROUGH = 'video-react/CAN_PLAY_THROUGH'; var PLAYING = 'video-react/PLAYING'; var PLAY = 'video-react/PLAY'; var PAUSE = 'video-react/PAUSE'; var END = 'video-react/END'; var SEEKING = 'video-react/SEEKING'; var SEEKED = 'video-react/SEEKED'; var SEEKING_TIME = 'video-react/SEEKING_TIME'; var END_SEEKING = 'video-react/END_SEEKING'; var DURATION_CHANGE = 'video-react/DURATION_CHANGE'; var TIME_UPDATE = 'video-react/TIME_UPDATE'; var VOLUME_CHANGE = 'video-react/VOLUME_CHANGE'; var PROGRESS_CHANGE = 'video-react/PROGRESS_CHANGE'; var RATE_CHANGE = 'video-react/RATE_CHANGE'; var SUSPEND = 'video-react/SUSPEND'; var ABORT = 'video-react/ABORT'; var EMPTIED = 'video-react/EMPTIED'; var STALLED = 'video-react/STALLED'; var LOADED_META_DATA = 'video-react/LOADED_META_DATA'; var LOADED_DATA = 'video-react/LOADED_DATA'; var RESIZE = 'video-react/RESIZE'; var ERROR = 'video-react/ERROR'; var ACTIVATE_TEXT_TRACK = 'video-react/ACTIVATE_TEXT_TRACK'; function handleLoadStart(videoProps) { return { type: LOAD_START, videoProps: videoProps }; } function handleCanPlay(videoProps) { return { type: CAN_PLAY, videoProps: videoProps }; } function handleWaiting(videoProps) { return { type: WAITING, videoProps: videoProps }; } function handleCanPlayThrough(videoProps) { return { type: CAN_PLAY_THROUGH, videoProps: videoProps }; } function handlePlaying(videoProps) { return { type: PLAYING, videoProps: videoProps }; } function handlePlay(videoProps) { return { type: PLAY, videoProps: videoProps }; } function handlePause(videoProps) { return { type: PAUSE, videoProps: videoProps }; } function handleEnd(videoProps) { return { type: END, videoProps: videoProps }; } function handleSeeking(videoProps) { return { type: SEEKING, videoProps: videoProps }; } function handleSeeked(videoProps) { return { type: SEEKED, videoProps: videoProps }; } function handleDurationChange(videoProps) { return { type: DURATION_CHANGE, videoProps: videoProps }; } function handleTimeUpdate(videoProps) { return { type: TIME_UPDATE, videoProps: videoProps }; } function handleVolumeChange(videoProps) { return { type: VOLUME_CHANGE, videoProps: videoProps }; } function handleProgressChange(videoProps) { return { type: PROGRESS_CHANGE, videoProps: videoProps }; } function handleRateChange(videoProps) { return { type: RATE_CHANGE, videoProps: videoProps }; } function handleSuspend(videoProps) { return { type: SUSPEND, videoProps: videoProps }; } function handleAbort(videoProps) { return { type: ABORT, videoProps: videoProps }; } function handleEmptied(videoProps) { return { type: EMPTIED, videoProps: videoProps }; } function handleStalled(videoProps) { return { type: STALLED, videoProps: videoProps }; } function handleLoadedMetaData(videoProps) { return { type: LOADED_META_DATA, videoProps: videoProps }; } function handleLoadedData(videoProps) { return { type: LOADED_DATA, videoProps: videoProps }; } function handleResize(videoProps) { return { type: RESIZE, videoProps: videoProps }; } function handleError(videoProps) { return { type: ERROR, videoProps: videoProps }; } function handleSeekingTime(time) { return { type: SEEKING_TIME, time: time }; } function handleEndSeeking(time) { return { type: END_SEEKING, time: time }; } function activateTextTrack(textTrack) { return { type: ACTIVATE_TEXT_TRACK, textTrack: textTrack }; } var videoActions = /*#__PURE__*/Object.freeze({ __proto__: null, LOAD_START: LOAD_START, CAN_PLAY: CAN_PLAY, WAITING: WAITING, CAN_PLAY_THROUGH: CAN_PLAY_THROUGH, PLAYING: PLAYING, PLAY: PLAY, PAUSE: PAUSE, END: END, SEEKING: SEEKING, SEEKED: SEEKED, SEEKING_TIME: SEEKING_TIME, END_SEEKING: END_SEEKING, DURATION_CHANGE: DURATION_CHANGE, TIME_UPDATE: TIME_UPDATE, VOLUME_CHANGE: VOLUME_CHANGE, PROGRESS_CHANGE: PROGRESS_CHANGE, RATE_CHANGE: RATE_CHANGE, SUSPEND: SUSPEND, ABORT: ABORT, EMPTIED: EMPTIED, STALLED: STALLED, LOADED_META_DATA: LOADED_META_DATA, LOADED_DATA: LOADED_DATA, RESIZE: RESIZE, ERROR: ERROR, ACTIVATE_TEXT_TRACK: ACTIVATE_TEXT_TRACK, handleLoadStart: handleLoadStart, handleCanPlay: handleCanPlay, handleWaiting: handleWaiting, handleCanPlayThrough: handleCanPlayThrough, handlePlaying: handlePlaying, handlePlay: handlePlay, handlePause: handlePause, handleEnd: handleEnd, handleSeeking: handleSeeking, handleSeeked: handleSeeked, handleDurationChange: handleDurationChange, handleTimeUpdate: handleTimeUpdate, handleVolumeChange: handleVolumeChange, handleProgressChange: handleProgressChange, handleRateChange: handleRateChange, handleSuspend: handleSuspend, handleAbort: handleAbort, handleEmptied: handleEmptied, handleStalled: handleStalled, handleLoadedMetaData: handleLoadedMetaData, handleLoadedData: handleLoadedData, handleResize: handleResize, handleError: handleError, handleSeekingTime: handleSeekingTime, handleEndSeeking: handleEndSeeking, activateTextTrack: activateTextTrack }); var Fullscreen = /*#__PURE__*/function () { function Fullscreen() {} var _proto = Fullscreen.prototype; _proto.request = function request(elm) { if (elm.requestFullscreen) { elm.requestFullscreen(); } else if (elm.webkitRequestFullscreen) { elm.webkitRequestFullscreen(); } else if (elm.mozRequestFullScreen) { elm.mozRequestFullScreen(); } else if (elm.msRequestFullscreen) { elm.msRequestFullscreen(); } }; _proto.exit = function exit() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } }; _proto.addEventListener = function addEventListener(handler, domRef) { domRef.addEventListener('fullscreenchange', handler); domRef.addEventListener('webkitfullscreenchange', handler); domRef.addEventListener('mozfullscreenchange', handler); domRef.addEventListener('MSFullscreenChange', handler); }; _proto.removeEventListener = function removeEventListener(handler, domRef) { domRef.removeEventListener('fullscreenchange', handler); domRef.removeEventListener('webkitfullscreenchange', handler); domRef.removeEventListener('mozfullscreenchange', handler); domRef.removeEventListener('MSFullscreenChange', handler); }; _createClass(Fullscreen, [{ key: "isFullscreen", get: function get() { return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement; } }, { key: "enabled", get: function get() { return document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled || document.msFullscreenEnabled; } }]); return Fullscreen; }(); var fullscreen = new Fullscreen(); var OPERATE = 'video-react/OPERATE'; var FULLSCREEN_CHANGE = 'video-react/FULLSCREEN_CHANGE'; var PLAYER_ACTIVATE = 'video-react/PLAYER_ACTIVATE'; var USER_ACTIVATE = 'video-react/USER_ACTIVATE'; function handleFullscreenChange(isFullscreen) { return { type: FULLSCREEN_CHANGE, isFullscreen: isFullscreen }; } function activate(activity) { return { type: PLAYER_ACTIVATE, activity: activity }; } function userActivate(activity) { return { type: USER_ACTIVATE, activity: activity }; } function play(operation) { if (operation === void 0) { operation = { action: 'play', source: '' }; } this.video.play(); return { type: OPERATE, operation: operation }; } function pause(operation) { if (operation === void 0) { operation = { action: 'pause', source: '' }; } this.video.pause(); return { type: OPERATE, operation: operation }; } function togglePlay(operation) { if (operation === void 0) { operation = { action: 'toggle-play', source: '' }; } this.video.togglePlay(); return { type: OPERATE, operation: operation }; } // seek video by time function seek(time, operation) { if (operation === void 0) { operation = { action: 'seek', source: '' }; } this.video.seek(time); return { type: OPERATE, operation: operation }; } // jump forward x seconds function forward(seconds, operation) { if (operation === void 0) { operation = { action: "forward-" + seconds, source: '' }; } this.video.forward(seconds); return { type: OPERATE, operation: operation }; } // jump back x seconds function replay(seconds, operation) { if (operation === void 0) { operation = { action: "replay-" + seconds, source: '' }; } this.video.replay(seconds); return { type: OPERATE, operation: operation }; } function changeRate(rate, operation) { if (operation === void 0) { operation = { action: 'change-rate', source: '' }; } this.video.playbackRate = rate; return { type: OPERATE, operation: operation }; } function changeVolume(volume, operation) { if (operation === void 0) { operation = { action: 'change-volume', source: '' }; } var v = volume; if (volume < 0) { v = 0; } if (volume > 1) { v = 1; } this.video.volume = v; return { type: OPERATE, operation: operation }; } function mute(muted, operation) { if (operation === void 0) { operation = { action: muted ? 'muted' : 'unmuted', source: '' }; } this.video.muted = muted; return { type: OPERATE, operation: operation }; } function toggleFullscreen(player) { if (fullscreen.enabled) { if (fullscreen.isFullscreen) { fullscreen.exit(); } else { fullscreen.request(this.rootElement); } return { type: OPERATE, operation: { action: 'toggle-fullscreen', source: '' } }; } return { type: FULLSCREEN_CHANGE, isFullscreen: !player.isFullscreen }; } var playerActions = /*#__PURE__*/Object.freeze({ __proto__: null, OPERATE: OPERATE, FULLSCREEN_CHANGE: FULLSCREEN_CHANGE, PLAYER_ACTIVATE: PLAYER_ACTIVATE, USER_ACTIVATE: USER_ACTIVATE, handleFullscreenChange: handleFullscreenChange, activate: activate, userActivate: userActivate, play: play, pause: pause, togglePlay: togglePlay, seek: seek, forward: forward, replay: replay, changeRate: changeRate, changeVolume: changeVolume, mute: mute, toggleFullscreen: toggleFullscreen }); var initialState = { currentSrc: null, duration: 0, currentTime: 0, seekingTime: 0, buffered: null, waiting: false, seeking: false, paused: true, autoPaused: false, ended: false, playbackRate: 1, muted: false, volume: 1, readyState: 0, networkState: 0, videoWidth: 0, videoHeight: 0, hasStarted: false, userActivity: true, isActive: false, isFullscreen: false, activeTextTrack: null }; function player(state, action) { if (state === void 0) { state = initialState; } switch (action.type) { case USER_ACTIVATE: return _extends({}, state, { userActivity: action.activity }); case PLAYER_ACTIVATE: return _extends({}, state, { isActive: action.activity }); case FULLSCREEN_CHANGE: return _extends({}, state, { isFullscreen: !!action.isFullscreen }); case SEEKING_TIME: return _extends({}, state, { seekingTime: action.time }); case END_SEEKING: return _extends({}, state, { seekingTime: 0 }); case LOAD_START: return _extends({}, state, action.videoProps, { hasStarted: false, ended: false }); case CAN_PLAY: return _extends({}, state, action.videoProps, { waiting: false }); case WAITING: return _extends({}, state, action.videoProps, { waiting: true }); case CAN_PLAY_THROUGH: case PLAYING: return _extends({}, state, action.videoProps, { waiting: false }); case PLAY: return _extends({}, state, action.videoProps, { ended: false, paused: false, autoPaused: false, waiting: false, hasStarted: true }); case PAUSE: return _extends({}, state, action.videoProps, { paused: true }); case END: return _extends({}, state, action.videoProps, { ended: true }); case SEEKING: return _extends({}, state, action.videoProps, { seeking: true }); case SEEKED: return _extends({}, state, action.videoProps, { seeking: false }); case ERROR: return _extends({}, state, action.videoProps, { error: 'UNKNOWN ERROR', ended: true }); case DURATION_CHANGE: case TIME_UPDATE: case VOLUME_CHANGE: case PROGRESS_CHANGE: case RATE_CHANGE: case SUSPEND: case ABORT: case EMPTIED: case STALLED: case LOADED_META_DATA: case LOADED_DATA: case RESIZE: return _extends({}, state, action.videoProps); case ACTIVATE_TEXT_TRACK: return _extends({}, state, { activeTextTrack: action.textTrack }); default: return state; } } var initialState$1 = { count: 0, operation: { action: '', source: '' } }; function operation(state, action) { if (state === void 0) { state = initialState$1; } switch (action.type) { case OPERATE: return _extends({}, state, { count: state.count + 1, operation: _extends({}, state.operation, action.operation) }); default: return state; } } function reducer (state, action) { if (state === void 0) { state = {}; } return { player: player(state.player, action), operation: operation(state.operation, action) }; } var playerReducer = player; var operationReducer = operation; var Manager = /*#__PURE__*/function () { function Manager(store) { this.store = store || redux.createStore(reducer); this.video = null; this.rootElement = null; } var _proto = Manager.prototype; _proto.getActions = function getActions() { var manager = this; var dispatch = this.store.dispatch; var actions = _extends({}, playerActions, videoActions); function bindActionCreator(actionCreator) { return function bindAction() { // eslint-disable-next-line prefer-rest-params var action = actionCreator.apply(manager, arguments); if (typeof action !== 'undefined') { dispatch(action); } }; } return Object.keys(actions).filter(function (key) { return typeof actions[key] === 'function'; }).reduce(function (boundActions, key) { boundActions[key] = bindActionCreator(actions[key]); return boundActions; }, {}); }; _proto.getState = function getState() { return this.store.getState(); } // subscribe state change ; _proto.subscribeToStateChange = function subscribeToStateChange(listener, getState) { if (!getState) { getState = this.getState.bind(this); } var prevState = getState(); var handleChange = function handleChange() { var state = getState(); if (state === prevState) { return; } var prevStateCopy = prevState; prevState = state; listener(state, prevStateCopy); }; return this.store.subscribe(handleChange); } // subscribe to operation state change ; _proto.subscribeToOperationStateChange = function subscribeToOperationStateChange(listener) { var _this = this; return this.subscribeToStateChange(listener, function () { return _this.getState().operation; }); } // subscribe to player state change ; _proto.subscribeToPlayerStateChange = function subscribeToPlayerStateChange(listener) { var _this2 = this; return this.subscribeToStateChange(listener, function () { return _this2.getState().player; }); }; return Manager; }(); var propTypes = { actions: PropTypes.object, player: PropTypes.object, position: PropTypes.string, className: PropTypes.string }; var defaultProps = { position: 'left' }; var BigPlayButton = /*#__PURE__*/function (_Component) { _inheritsLoose(BigPlayButton, _Component); function BigPlayButton(props, context) { var _this; _this = _Component.call(this, props, context) || this; _this.handleClick = _this.handleClick.bind(_assertThisInitialized(_this)); return _this; } var _proto = BigPlayButton.prototype; _proto.componentDidMount = function componentDidMount() {}; _proto.handleClick = function handleClick() { var actions = this.props.actions; actions.play(); }; _proto.render = function render() { var _this$props = this.props, player = _this$props.player, position = _this$props.position; return /*#__PURE__*/React__default.createElement("button", { className: classNames('video-react-button', 'video-react-big-play-button', "video-react-big-play-button-" + position, this.props.className, { 'big-play-button-hide': player.hasStarted || !player.currentSrc }), type: "button", "aria-live": "polite", tabIndex: "0", onClick: this.handleClick }, /*#__PURE__*/React__default.createElement("span", { className: "video-react-control-text" }, "Play Video")); }; return BigPlayButton; }(React.Component); BigPlayButton.propTypes = propTypes; BigPlayButton.defaultProps = defaultProps; BigPlayButton.displayName = 'BigPlayButton'; var propTypes$1 = { player: PropTypes.object, className: PropTypes.string }; function LoadingSpinner(_ref) { var player = _ref.player, className = _ref.className; if (player.error) { return null; } return /*#__PURE__*/React__default.createElement("div", { className: classNames('video-react-loading-spinner', className) }); } LoadingSpinner.propTypes = propTypes$1; LoadingSpinner.displayName = 'LoadingSpinner'; var propTypes$2 = { poster: PropTypes.string, player: PropTypes.object, actions: PropTypes.object, className: PropTypes.string }; function PosterImage(_ref) { var poster = _ref.poster, player = _ref.player, actions = _ref.actions, className = _ref.className; if (!poster || player.hasStarted) { return null; } return /*#__PURE__*/React__default.createElement("div", { className: classNames('video-react-poster', className), style: { backgroundImage: "url(\"" + poster + "\")" }, onClick: function onClick() { if (player.paused) { actions.play(); } } }); } PosterImage.propTypes = propTypes$2; PosterImage.displayName = 'PosterImage'; // eslint-disable-next-line no-self-compare var isNaN = Number.isNaN || function (value) { return value !== value; }; /** * @file format-time.js * * Format seconds as a time string, H:MM:SS or M:SS * Supplying a guide (in seconds) will force a number of leading zeros * to cover the length of the guide * * @param {Number} seconds Number of seconds to be turned into a string * @param {Number} guide Number (in seconds) to model the string after * @return {String} Time formatted as H:MM:SS or M:SS * @private * @function formatTime */ function formatTime(seconds, guide) { if (seconds === void 0) { seconds = 0; } if (guide === void 0) { guide = seconds; } var s = Math.floor(seconds % 60); var m = Math.floor(seconds / 60 % 60); var h = Math.floor(seconds / 3600); var gm = Math.floor(guide / 60 % 60); var gh = Math.floor(guide / 3600); // handle invalid times if (isNaN(seconds) || seconds === Infinity) { // '-' is false for all relational operators (e.g. <, >=) so this setting // will add the minimum number of fields specified by the guide h = '-'; m = '-'; s = '-'; } // Check if we need to show hours h = h > 0 || gh > 0 ? h + ":" : ''; // If hours are showing, we may need to add a leading zero. // Always show at least one digit of minutes. m = ((h || gm >= 10) && m < 10 ? "0" + m : m) + ":"; // Check if leading zero is need for seconds s = s < 10 ? "0" + s : s; return h + m + s; } // Check if the element belongs to a video element // only accept <source />, <track />, // <MyComponent isVideoChild /> // elements function isVideoChild(c) { if (c.props && c.props.isVideoChild) { return true; } return c.type === 'source' || c.type === 'track'; } var find = function find(elements, func) { return elements.filter(func)[0]; }; // check if two components are the same type var isTypeEqual = function isTypeEqual(component1, component2) { var type1 = component1.type; var type2 = component2.type; if (typeof type1 === 'string' || typeof type2 === 'string') { return type1 === type2; } if (typeof type1 === 'function' && typeof type2 === 'function') { return type1.displayName === type2.displayName; } return false; }; // merge default children // sort them by `order` property // filter them by `disabled` property function mergeAndSortChildren(defaultChildren, _children, _parentProps, defaultOrder) { if (defaultOrder === void 0) { defaultOrder = 1; } var children = React__default.Children.toArray(_children); var order = _parentProps.order, parentProps = _objectWithoutPropertiesLoose(_parentProps, ["order"]); // ignore order from parent return children.filter(function (e) { return !e.props.disabled; }) // filter the disabled components .concat(defaultChildren.filter(function (c) { return !find(children, function (component) { return isTypeEqual(component, c); }); })).map(function (element) { var defaultComponent = find(defaultChildren, function (c) { return isTypeEqual(c, element); }); var defaultProps = defaultComponent ? defaultComponent.props : {}; var props = _extends({}, parentProps, defaultProps, element.props); var e = /*#__PURE__*/React__default.cloneElement(element, props, element.props.children); return e; }).sort(function (a, b) { return (a.props.order || defaultOrder) - (b.props.order || defaultOrder); }); } /** * Temporary utility for generating the warnings */ function deprecatedWarning(oldMethodCall, newMethodCall) { // eslint-disable-next-line no-console console.warn("WARNING: " + oldMethodCall + " will be deprecated soon! Please use " + newMethodCall + " instead."); } function throttle(callback, limit) { var _arguments = arguments; var wait = false; return function () { if (!wait) { // eslint-disable-next-line prefer-rest-params callback.apply(void 0, _arguments); wait = true; setTimeout(function () { wait = false; }, limit); } }; } var mediaProperties = ['error', 'src', 'srcObject', 'currentSrc', 'crossOrigin', 'networkState', 'preload', 'buffered', 'readyState', 'seeking', 'currentTime', 'duration', 'paused', 'defaultPlaybackRate', 'playbackRate', 'played', 'seekable', 'ended', 'autoplay', 'loop', 'mediaGroup', 'controller', 'controls', 'volume', 'muted', 'defaultMuted', 'audioTracks', 'videoTracks', 'textTracks', 'width', 'height', 'videoWidth', 'videoHeight', 'poster']; var propTypes$3 = { actions: PropTypes.object, player: PropTypes.object, children: PropTypes.any, startTime: PropTypes.number, loop: PropTypes.bool, muted: PropTypes.bool, autoPlay: PropTypes.bool, playsInline: PropTypes.bool, src: PropTypes.string, poster: PropTypes.string, className: PropTypes.string, preload: PropTypes.oneOf(['auto', 'metadata', 'none']), crossOrigin: PropTypes.string, onLoadStart: PropTypes.func, onWaiting: PropTypes.func, onCanPlay: PropTypes.func, onCanPlayThrough: PropTypes.func, onPlaying: PropTypes.func, onEnded: PropTypes.func, onSeeking: PropTypes.func, onSeeked: PropTypes.func, onPlay: PropTypes.func, onPause: PropTypes.func, onProgress: PropTypes.func, onDurationChange: PropTypes.func, onError: PropTypes.func, onSuspend: PropTypes.func, onAbort: PropTypes.func, onEmptied: PropTypes.func, onStalled: PropTypes.func, onLoadedMetadata: PropTypes.func, onLoadedData: PropTypes.func, onTimeUpdate: PropTypes.func, onRateChange: PropTypes.func, onVolumeChange: PropTypes.func, onResize: PropTypes.func }; var Video = /*#__PURE__*/function (_Component) { _inheritsLoose(Video, _Component); function Video(props) { var _this; _this = _Component.call(this, props) || this; _this.video = null; // the html5 video _this.play = _this.play.bind(_assertThisInitialized(_this)); _this.pause = _this.pause.bind(_assertThisInitialized(_this)); _this.seek = _this.seek.bind(_assertThisInitialized(_this)); _this.forward = _this.forward.bind(_assertThisInitialized(_this)); _this.replay = _this.replay.bind(_assertThisInitialized(_this)); _this.toggleFullscreen = _this.toggleFullscreen.bind(_assertThisInitialized(_this)); _this.getProperties = _this.getProperties.bind(_assertThisInitialized(_this)); _this.renderChildren = _this.renderChildren.bind(_assertThisInitialized(_this)); _this.handleLoadStart = _this.handleLoadStart.bind(_assertThisInitialized(_this)); _this.handleCanPlay = _this.handleCanPlay.bind(_assertThisInitialized(_this)); _this.handleCanPlayThrough = _this.handleCanPlayThrough.bind(_assertThisInitialized(_this)); _this.handlePlay = _this.handlePlay.bind(_assertThisInitialized(_this)); _this.handlePlaying = _this.handlePlaying.bind(_assertThisInitialized(_this)); _this.handlePause = _this.handlePause.bind(_assertThisInitialized(_this)); _this.handleEnded = _this.handleEnded.bind(_assertThisInitialized(_this)); _this.handleWaiting = _this.handleWaiting.bind(_assertThisInitialized(_this)); _this.handleSeeking = _this.handleSeeking.bind(_assertThisInitialized(_this)); _this.handleSeeked = _this.handleSeeked.bind(_assertThisInitialized(_this)); _this.handleFullscreenChange = _this.handleFullscreenChange.bind(_assertThisInitialized(_this)); _this.handleError = _this.handleError.bind(_assertThisInitialized(_this)); _this.handleSuspend = _this.handleSuspend.bind(_assertThisInitialized(_this)); _this.handleAbort = _this.handleAbort.bind(_assertThisInitialized(_this)); _this.handleEmptied = _this.handleEmptied.bind(_assertThisInitialized(_this)); _this.handleStalled = _this.handleStalled.bind(_assertThisInitialized(_this)); _this.handleLoadedMetaData = _this.handleLoadedMetaData.bind(_assertThisInitialized(_this)); _this.handleLoadedData = _this.handleLoadedData.bind(_assertThisInitialized(_this)); _this.handleTimeUpdate = _this.handleTimeUpdate.bind(_assertThisInitialized(_this)); _this.handleRateChange = _this.handleRateChange.bind(_assertThisInitialized(_this)); _this.handleVolumeChange = _this.handleVolumeChange.bind(_assertThisInitialized(_this)); _this.handleDurationChange = _this.handleDurationChange.bind(_assertThisInitialized(_this)); _this.handleProgress = throttle(_this.handleProgress.bind(_assertThisInitialized(_this)), 250); _this.handleKeypress = _this.handleKeypress.bind(_assertThisInitialized(_this)); _this.handleTextTrackChange = _this.handleTextTrackChange.bind(_assertThisInitialized(_this)); return _this; } var _proto = Video.prototype; _proto.componentDidMount = function componentDidMount() { this.forceUpdate(); // make sure the children can get the video property if (this.video && this.video.textTracks) { this.video.textTracks.onaddtrack = this.handleTextTrackChange; this.video.textTracks.onremovetrack = this.handleTextTrackChange; } } // get all video properties ; _proto.getProperties = function getProperties() { var _this2 = this; if (!this.video) { return null; } return mediaProperties.reduce(function (properties, key) { properties[key] = _this2.video[key]; return properties; }, {}); } // get playback rate ; _proto.handleTextTrackChange = function handleTextTrackChange() { var _this$props = this.props, actions = _this$props.actions, player = _this$props.player; if (this.video && this.video.textTracks) { var activeTextTrack = Array.from(this.video.textTracks).find(function (textTrack) { return textTrack.mode === 'showing'; }); if (activeTextTrack !== player.activeTextTrack) { actions.activateTextTrack(activeTextTrack); } } } // play the video ; _proto.play = function play() { var promise = this.video.play(); if (promise !== undefined) { promise.catch(function () {}).then(function () {}); } } // pause the video ; _proto.pause = function pause() { var promise = this.video.pause(); if (promise !== undefined) { promise.catch(function () {}).then(function () {}); } } // Change the video source and re-load the video: ; _proto.load = function load() { this.video.load(); } // Add a new text track to the video ; _proto.addTextTrack = function addTextTrack() { var _this$video; (_this$video = this.video).addTextTrack.apply(_this$video, arguments); } // Check if your browser can play different types of video: ; _proto.canPlayType = function canPlayType() { var _this$video2; (_this$video2 = this.video).canPlayType.apply(_this$video2, arguments); } // toggle play ; _proto.togglePlay = function togglePlay() { if (this.video.paused) { this.play(); } else { this.pause(); } } // seek video by time ; _proto.seek = function seek(time) { try { this.video.currentTime = time; } catch (e) {// console.log(e, 'Video is not ready.') } } // jump forward x seconds ; _proto.forward = function forward(seconds) { this.seek(this.video.currentTime + seconds); } // jump back x seconds ; _proto.replay = function replay(seconds) { this.forward(-seconds); } // enter or exist full screen ; _proto.toggleFullscreen = function toggleFullscreen() { var _this$props2 = this.props, player = _this$props2.player, actions = _this$props2.actions; actions.toggleFullscreen(player); } // Fired when the user agent // begins looking for media data ; _proto.handleLoadStart = function handleLoadStart() { var _this$props3 = this.props, actions = _this$props3.actions, onLoadStart = _this$props3.onLoadStart; actions.handleLoadStart(this.getProperties()); if (onLoadStart) { onLoadStart.apply(void 0, arguments); } } // A handler for events that // signal that waiting has ended ; _proto.handleCanPlay = function handleCanPlay() { var _this$props4 = this.props, actions = _this$props4.actions, onCanPlay = _this$props4.onCanPlay; actions.handleCanPlay(this.getProperties()); if (onCanPlay) { onCanPlay.apply(void 0, arguments); } } // A handler for events that // signal that waiting has ended ; _proto.handleCanPlayThrough = function handleCanPlayThrough() { var _this$props5 = this.props, actions = _this$props5.actions, onCanPlayThrough = _this$props5.onCanPlayThrough; actions.handleCanPlayThrough(this.getProperties()); if (onCanPlayThrough) { onCanPlayThrough.apply(void 0, arguments); } } // A handler for events that // signal that waiting has ended ; _proto.handlePlaying = function handlePlaying() { var _this$props6 = this.props, actions = _this$props6.actions, onPlaying = _this$props6.onPlaying; actions.handlePlaying(this.getProperties()); if (onPlaying) { onPlaying.apply(void 0, arguments); } } // Fired whenever the media has been started ; _proto.handlePlay = function handlePlay() { var _this$props7 = this.props, actions = _this$props7.actions, onPlay = _this$props7.onPlay; actions.handlePlay(this.getProperties()); if (onPlay) { onPlay.apply(void 0, arguments); } } // Fired whenever the media has been paused ; _proto.handlePause = function handlePause() { var _this$props8 = this.props, actions = _this$props8.actions, onPause = _this$props8.onPause; actions.handlePause(this.getProperties()); if (onPause) { onPause.apply(void 0, arguments); } } // Fired when the duration of // the media resource is first known or changed ; _proto.handleDurationChange = function handleDurationChange() { var _this$props9 = this.props, actions = _this$props9.actions, onDurationChange = _this$props9.onDurationChange; actions.handleDurationChange(this.getProperties()); if (onDurationChange) { onDurationChange.apply(void 0, arguments); } } // Fired while the user agent // is downloading media data ; _proto.handleProgress = function handleProgress() { var _this$props10 = this.props, actions = _this$props10.actions, onProgress = _this$props10.onProgress; if (this.video) { actions.handleProgressChange(this.getProperties()); } if (onProgress) { onProgress.apply(void 0, arguments); } } // Fired when the end of the media resource // is reached (currentTime == duration) ; _proto.handleEnded = function handleEnded() { var _this$props11 = this.props, loop = _this$props11.loop, player = _this$props11.player, actions = _this$props11.actions, onEnded = _this$props11.onEnded; if (loop) { this.seek(0); this.play(); } else if (!player.paused) { this.pause(); } actions.handleEnd(this.getProperties()); if (onEnded) { onEnded.apply(void 0, arguments); } } // Fired whenever the media begins waiting ; _proto.handleWaiting = function handleWaiting() { var _this$props12 = this.props, actions = _this$props12.actions, onWaiting = _this$props12.onWaiting; actions.handleWaiting(this.getProperties()); if (onWaiting) { onWaiting.apply(void 0, arguments); } } // Fired whenever the player // is jumping to a new time ; _proto.handleSeeking = function handleSeeking() { var _this$props13 = this.props, actions = _this$props13.actions, onSeeking = _this$props13.onSeeking; actions.handleSeeking(this.getProperties()); if (onSeeking) { onSeeking.apply(void 0, arguments); } } // Fired when the player has // finished jumping to a new time ; _proto.handleSeeked = function handleSeeked() { var _this$props14 = this.props, actions = _this$props14.actions, onSeeked = _this$props14.onSeeked; actions.handleSeeked(this.getProperties()); if (onSeeked) { onSeeked.apply(void 0, arguments); } } // Handle Fullscreen Change ; _proto.handleFullscreenChange = function handleFullscreenChange() {} // Fires when the browser is // intentionally not getting media data ; _proto.handleSuspend = function handleSuspend() { var _this$props15 = this.props, actions = _this$props15.actions, onSuspend = _this$props15.onSuspend; actions.handleSuspend(this.getProperties()); if (onSuspend) { onSuspend.apply(void 0, arguments); } } // Fires when the loading of an audio/video is aborted ; _proto.handleAbort = function handleAbort() { var _this$props16 = this.props, actions = _this$props16.actions, onAbort = _this$props16.onAbort; actions.handleAbort(this.getProperties()); if (onAbort) { onAbort.apply(void 0, arguments); } } // Fires when the current playlist is empty ; _proto.handleEmptied = function handleEmptied() { var _this$props17 = this.props, actions = _this$props17.actions, onEmptied = _this$props17.onEmptied; actions.handleEmptied(this.getProperties()); if (onEmptied) { onEmptied.apply(void 0, arguments); } } // Fires when the browser is trying to // get media data, but data is not available ; _proto.handleStalled = function handleStalled() { var _this$props18 = this.props, actions = _this$props18.actions, onStalled = _this$props18.onStalled; actions.handleStalled(this.getProperties()); if (onStalled) { onStalled.apply(void 0, arguments); } } // Fires when the browser has loaded // meta data for the audio/video ; _proto.handleLoadedMetaData = function handleLoadedMetaData() { var _this$props19 = this.props, actions = _this$props19.actions, onLoadedMetadata = _this$props19.onLoadedMetadata, startTime = _this$props19.startTime; if (startTime && startTime > 0) { this.video.currentTime = startTime; } actions.handleLoadedMetaData(this.getProperties()); if (onLoadedMetadata) { onLoadedMetadata.apply(void 0, arguments); } } // Fires when the browser has loaded // the current frame of the audio/video ; _proto.handleLoadedData = function handleLoadedData() { var _this$props20 = this.props, actions = _this$props20.actions, onLoadedData = _this$props20.onLoadedData; actions.handleLoadedData(this.getProperties()); if (onLoadedData) { onLoadedData.apply(void 0, arguments); } } // Fires when the current // playback position has changed ; _proto.handleTimeUpdate = function handleTimeUpdate() { var _this$props21 = this.props, actions = _this$props21.actions, onTimeUpdate = _this$props21.onTimeUpdate; actions.handleTimeUpdate(this.getProperties()); if (onTimeUpdate) { onTimeUpdate.apply(void 0, arguments); } } /** * Fires when the playing speed of the audio/video is changed */ ; _proto.handleRateChange = function handleRateChange() { var _this$props22 = this.props, actions = _this$props22.actions, onRateChange = _this$props22.onRateChange; actions.handleRateChange(this.getProperties()); if (onRateChange) { onRateChange.apply(void 0, arguments); } } // Fires when the volume has been changed ; _proto.handleVolumeChange = function handleVolumeChange() { var _this$props23 = this.props, actions = _this$props23.actions, onVolumeChange = _this$props23.onVolumeChange; actions.handleVolumeChange(this.getProperties()); if (onVolumeChange) { onVolumeChange.apply(void 0, arguments); } } // Fires when an error occurred // during the loading of an audio/video ; _proto.handleError = function handleError() { var _this$props24 = this.props, actions = _this$props24.actions, onError = _this$props24.onError; actions.handleError(this.getProperties()); if (onError) { onError.apply(void 0, arguments); } }; _proto.handleResize = function handleResize() { var _this$props25 = this.props, actions = _this$props25.actions, onResize = _this$props25.onResize; actions.handleResize(this.getProperties()); if (onResize) { onResize.apply(void 0, arguments); } }; _proto.handleKeypress = function handleKeypress() {}; _proto.renderChildren = function renderChildren() { var _this3 = this; var props = _extends({}, this.props, { video: this.video }); // to make sure the children can get video property if (!this.video) { return null; } // only keep <source />, <track />, <MyComponent isVideoChild /> elements return React__default.Children.toArray(this.props.children).filter(isVideoChild).map(function (c) { var cprops; if (typeof c.type === 'string') { // add onError to <source /> if (c.type === 'source') { cprops = _extends({}, c.props); var preOnError = cprops.onError; cprops.onError = function () { if (preOnError) { preOnError.apply(void 0, arguments); } _this3.handleError.apply(_this3, arguments); }; } } else { cprops = props; } return /*#__PURE__*/React__default.cloneElement(c, cprops); }); }; _proto.render = function render() { var _this4 = this; var _this$props26 = this.props, loop = _this$props26.loop, poster = _this$props26.poster, preload = _this$props26.preload, src = _this$props26.src, autoPlay = _this$props26.autoPlay, playsInline = _this$props26.playsInline, muted = _this$props26.muted, crossOrigin = _this$props26.crossOrigin, videoId = _this$props26.videoId; return /*#__PURE__*/React__default.createElement("video", { className: classNames('video-react-video', this.props.className), id: videoId, crossOrigin: crossOrigin, ref: function ref(c) { _this4.video = c; }, muted: muted, preload: preload, loop: loop, playsInline: playsInline, autoPlay: autoPlay, poster: poster, src: src, onLoadStart: this.handleLoadStart, onWaiting: this.handleWaiting, onCanPlay: this.handleCanPlay, onCanPlayThrough: this.handleCanPlayThrough, onPlaying: this.handlePlaying, onEnded: this.handleEnded, onSeeking: this.handleSeeking, onSeeked: this.handleSeeked, onPlay: this.handlePlay, onPause: this.handlePause, onProgress: this.handleProgress, onDurationChange: this.handleDurationChange, onError: this.handleError, onSuspend: this.handleSuspend, onAbort: this.handleAbort, onEmptied: this.handleEmptied, onStalled: this.handleStalled, onLoadedMetadata: this.handleLoadedMetaData, onLoadedData: this.handleLoadedData, onTimeUpdate: this.handleTimeUpdate, onRateChange: this.handleRateChange, onVolumeChange: this.handleVolumeChange, tabIndex: "-1" }, this.renderChildren()); }; _createClass(Video, [{ key: "playbackRate", get: function get() { return this.video.playbackRate; } // set playback rate // speed of video , set: function set(rate) { this.video.playbackRate = rate; } }, { key: "muted", get: function get() { return this.video.muted; }, set: function set(val) { this.video.muted = val; } }, { key: "volume", get: function get() { return this.video.volume; }, set: function set(val) { if (val > 1) { val = 1; } if (val < 0) { val = 0; } this.video.volume = val; } // video width }, { key: "videoWidth", get: function get() { return this.video.videoWidth; } // video height }, { key: "videoHeight", get: function get() { return this.video.videoHeight; } }]); return Video; }(React.Component); Video.propTypes = propTypes$3; Video.displayName = 'Video'; var propTypes$4 = { manager: PropTypes.object, className: PropTypes.string }; var Bezel = /*#__PURE__*/function (_Component) { _inheritsLoose(Bezel, _Component); function Bezel(props, context) { var _this; _this = _Component.call(this, props, context) || this; _this.timer = null; props.manager.subscribeToOperationStateChange(_this.handleStateChange.bind(_assertThisInitialized(_this))); _this.state = { hidden: true, operation: {} }; return _this; } var _proto = Bezel.prototype; _proto.handleStateChange = function handleStateChange(state, prevState) { var _this2 = this; if (state.count !== prevState.count && state.operation.source === 'shortcut') { if (this.timer) { // previous animation is not finished clearTimeout(this.timer); // cancel it this.timer = null; } // show it // update operation this.setState({ hidden: false, count: state.count, operation: state.operation }); // hide it after 0.5s this.timer = setTimeout(function () { _this2.setState({ hidden: true }); _this2.timer = null; }, 500); } }; _proto.render = function render() { // only displays for shortcut so far if (this.state.operation.source !== 'shortcut') { return null; } var style = this.state.hidden ? { display: 'none' } : null; return /*#__PURE__*/React__default.createElement("div", { className: classNames({ 'video-react-bezel': true, 'video-react-bezel-animation': this.state.count % 2 === 0, 'video-react-bezel-animation-alt': this.state.count % 2 === 1 }, this.props.className), style: style, role: "status", "aria-label": this.state.operation.action }, /*#__PURE__*/React__default.createElement("div", { className: classNames('video-react-bezel-icon', "video-react-bezel-icon-" + this.state.operation.action) })); }; return Bezel; }(React.Component); Bezel.propTypes = propTypes$4; Bezel.displayName = 'Bezel'; /** * Offset Left * getBoundingClientRect technique from * John Resig http://ejohn.org/blog/getboundingclientrect-is-awesome/ * * @function findElPosition * @param {ReactNodeRef} el React Node ref from which to get offset * @return {Object} */ function findElPosition(el) { var box; if (el.getBoundingClientRect && el.parentNode) { box = el.getBoundingClientRect(); } if (!box) { return { left: 0, top: 0 }; } var _document = document, body = _document.body, docEl = _document.documentElement; var clientLeft = docEl.clientLeft || body.clientLeft || 0; var scrollLeft = window.pageXOffset || body.scrollLeft; var left = box.left + scrollLeft - clientLeft; var clientTop = docEl.clientTop || body.clientTop || 0; var scrollTop = window.pageYOffset || body.scrollTop; var top = box.top + scrollTop - clientTop; // Android sometimes returns slightly off decimal values, so need to round return { left: Math.round(left), top: Math.round(top) }; } /** * Get pointer position in a React Node ref * Returns an object with x and y coordinates. * The base on the coordinates are the bottom left of the element. * * @function getPointerPosition * @param {ReactNodeRef} el React Node ref on which to get the pointer position on * @param {Event} event Event object * @return {Object} This object will have x and y coordinates corresponding to the mouse position */ function getPointerPosition(el, event) { var position = {}; var box = findElPosition(el); var boxW = el.offsetWidth; var boxH = el.offsetHeight; var boxY = box.top; var boxX = box.left; var evtPageY = event.pageY; var evtPageX = event.pageX; if (event.changedTouches) { evtPageX = event.changedTouches[0].pageX; evtPageY = event.changedTouches[0].pageY; } position.y = Math.max(0, Math.min(1, (boxY - evtPageY + boxH) / boxH)); position.x = Math.max(0, Math.min(1, (evtPageX - boxX) / boxW)); return position; } // blur an element function focusNode(reactNode)