organism-react-video
Version:
327 lines (316 loc) • 10.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("reshow-runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("reshow-runtime/helpers/interopRequireWildcard");
exports.__esModule = true;
exports["default"] = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("reshow-runtime/helpers/objectWithoutPropertiesLoose"));
var _createClass2 = _interopRequireDefault(require("reshow-runtime/helpers/createClass"));
var _classCallCheck2 = _interopRequireDefault(require("reshow-runtime/helpers/classCallCheck"));
var _defineProperty2 = _interopRequireDefault(require("reshow-runtime/helpers/defineProperty"));
var _objectSpread2 = _interopRequireDefault(require("reshow-runtime/helpers/objectSpread2"));
var React = _interopRequireWildcard(require("react"));
var _organismReactIframe = require("organism-react-iframe");
var _winDoc = require("win-doc");
var _reshowConstant = require("reshow-constant");
var _reshowHooks = require("reshow-hooks");
var _callFunc = _interopRequireDefault(require("call-func"));
var _getRandomId = require("get-random-id");
var _ResponsiveVideo = _interopRequireDefault(require("../organisms/ResponsiveVideo.js"));
var _jsxRuntime = require("react/jsx-runtime");
var _excluded = ["videoId", "videoParams", "hostname", "onStateChange", "onClick", "onLoad"],
_excluded2 = ["loading", "onError"]; // @ts-check
var useEffect = React.useEffect,
useImperativeHandle = React.useImperativeHandle,
forwardRef = React.forwardRef,
useRef = React.useRef,
useState = React.useState;
/**
* Iframe api
* https://www.youtube.com/iframe_api
* https://www.youtube.com/s/player/eff63141/www-widgetapi.vflset/www-widgetapi.js
*
* Play State
* https://developers.google.com/youtube/iframe_api_reference#Playback_status
*/
/**
* @typedef {import('organism-react-iframe').IframeContainerExpose} IframeContainerExpose
*/
/**
* @param {string} func
* @param {any[]=} args
* @param {string=} id
* @returns {string}
*/
var message = function message(func, args, id) {
return JSON.stringify({
event: "command",
id: id,
func: func,
args: args
});
};
var defaultVideoParams = {
autoplay: 1,
loop: 1,
showinfo: 0,
controls: 0,
rel: 0,
mute: 1,
modestbranding: 1,
iv_load_policy: 3,
enablejsapi: 1
};
/**
* @typedef {import("../organisms/ResponsiveVideo").ResponsiveVideoProps} ResponsiveVideoProps
*/
/**
* @typedef {object} YoutubeRWDExtendsProps
* @property {"eager"|"lazy"} [loading]
* @property {string} [videoId]
* @property {{[key: string]: any}} [videoParams]
* @property {string|boolean} [hostname]
* @property {boolean} [disable]
* @property {string} [id]
* @property {Function} [onStateChange]
* @property {Function} [onLoad]
* @property {Function} [onError]
*/
/**
* @typedef {ResponsiveVideoProps & YoutubeRWDExtendsProps} YoutubeRWDProps
*/
/**
* @param {YoutubeRWDExtendsProps} props
* @see https://developers.google.com/youtube/player_parameters
*/
var getYoutubeUrl = function getYoutubeUrl(_ref) {
var videoId = _ref.videoId,
videoParams = _ref.videoParams,
hostname = _ref.hostname;
var nextVideoParams = (0, _objectSpread2["default"])({}, videoParams);
if (nextVideoParams["enablejsapi"] && hostname) {
nextVideoParams["origin"] = hostname;
}
if (nextVideoParams["loop"]) {
nextVideoParams.playlist = videoId;
}
var aParams = [];
(0, _reshowConstant.KEYS)(nextVideoParams).forEach(function (key) {
return aParams.push(key + "=" + encodeURIComponent(nextVideoParams[key]));
});
var src = "https://www.youtube.com/embed/" + videoId + "?" + aParams.join("&");
return src;
};
/**
* @interface
*/
var PlayerState = /*#__PURE__*/(0, _createClass2["default"])(function PlayerState() {
(0, _classCallCheck2["default"])(this, PlayerState);
/**
* @type number
*/
(0, _defineProperty2["default"])(this, "state", void 0);
/**
* @type boolean
*/
(0, _defineProperty2["default"])(this, "isPlaying", void 0);
});
/**
* @typedef {object} YoutubeRWDExpose
* @property {Function} restart
* @property {Function} pause
* @property {function():PlayerState} togglePlayback
* @property {function(string):void} postMessage
* @property {ExecPost} exec
* @property {function():HTMLIFrameElement|undefined} getIframe
* @property {function():PlayerState} getPlayerState
*/
/**
* @callback ExecPost
* @param {string} cmd
* @param {any[]=} args
*/
/**
* @param {YoutubeRWDProps} props
*/
var useYoutubeRWD = function useYoutubeRWD(props) {
var lastProps = (0, _reshowHooks.useRefUpdate)(props);
var _lastProps$current = lastProps.current,
videoId = _lastProps$current.videoId,
videoParams = _lastProps$current.videoParams,
propsHostname = _lastProps$current.hostname,
onStateChange = _lastProps$current.onStateChange,
onClick = _lastProps$current.onClick,
onLoad = _lastProps$current.onLoad,
restProps = (0, _objectWithoutPropertiesLoose2["default"])(_lastProps$current, _excluded);
var lastPlayerState = useRef({
state: -1,
isPlaying: false
});
var lastMessageId = useRef(lastProps.current.id);
if (null == lastMessageId.current) {
lastMessageId.current = (0, _getRandomId.getSN)("youtube-widget");
}
var thisVideoParams = (0, _reshowHooks.useRefUpdate)((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, defaultVideoParams), videoParams));
var lastHostname = /**@type React.RefObject<string|boolean|undefined>*/
useRef(undefined);
var lastIframe = /**@type {React.RefObject<IframeContainerExpose|null>}*/
useRef(null);
var _useState = useState({
load: false
}),
state = _useState[0],
setState = _useState[1];
useEffect(function () {
var loc = (0, _winDoc.doc)().location;
var strLoc = loc.protocol + "//" + loc.hostname;
if (loc.port) {
strLoc += ":" + loc.port;
}
lastHostname.current = null == propsHostname ? strLoc : propsHostname;
setState({
load: true
});
var gWin = (0, _winDoc.win)();
gWin.addEventListener("message", handler.message);
return function () {
gWin.removeEventListener("message", handler.message);
};
}, []);
/**
* @type {YoutubeRWDExpose}
*/
var expose = {
restart: function restart() {
expose.exec("playVideo");
},
pause: function pause() {
expose.exec("pauseVideo");
},
togglePlayback: function togglePlayback() {
if (lastPlayerState.current.isPlaying) {
expose.pause();
} else {
expose.restart();
}
return lastPlayerState.current;
},
postMessage: function postMessage(message) {
var _lastIframe$current;
var iframe = (_lastIframe$current = lastIframe.current) === null || _lastIframe$current === void 0 ? void 0 : _lastIframe$current.getEl();
if (iframe) {
var _iframe$contentWindow;
var origin = /**@type string*/
lastHostname.current ? lastHostname.current : "*";
return (_iframe$contentWindow = iframe.contentWindow) === null || _iframe$contentWindow === void 0 ? void 0 : _iframe$contentWindow.window.postMessage(message, origin);
}
},
exec: function exec(cmd, args) {
var cmdMessage = message(cmd, args, lastMessageId.current);
return expose.postMessage(cmdMessage);
},
getIframe: function getIframe() {
var _lastIframe$current2;
return (_lastIframe$current2 = lastIframe.current) === null || _lastIframe$current2 === void 0 ? void 0 : _lastIframe$current2.getEl();
},
getPlayerState: function getPlayerState() {
return lastPlayerState.current;
}
};
var handler = {
listening: function listening() {
var message = JSON.stringify({
event: "listening",
channel: "widget",
id: lastMessageId.current
});
expose.postMessage(message);
expose.exec("addEventListener", ["onStateChange"]);
},
load: function load(/**@type Event*/e) {
if (thisVideoParams.current.autoplay) {
expose.restart();
}
handler.listening();
(0, _callFunc["default"])(lastProps.current.onLoad, [e]);
},
click: function click(/**@type React.MouseEvent*/e) {
(0, _callFunc["default"])(lastProps.current.onClick, [e]);
},
message: function message(/**@type MessageEvent*/e) {
var _data;
if (null == e) {
return null;
}
var data = e.data;
if ("string" === typeof data) {
try {
data = JSON.parse(e.data);
} catch (e) {}
}
if (((_data = data) === null || _data === void 0 ? void 0 : _data.id) === lastMessageId.current) {
var _data2;
var playerState = (_data2 = data) === null || _data2 === void 0 || (_data2 = _data2.info) === null || _data2 === void 0 ? void 0 : _data2.playerState;
if (null != playerState) {
var isPlaying = false;
switch (playerState) {
case 1:
case 3:
isPlaying = true;
break;
}
lastPlayerState.current = {
state: playerState,
isPlaying: isPlaying
};
}
(0, _callFunc["default"])(lastProps.current.onStateChange, [data]);
}
}
};
return {
expose: expose,
handler: handler,
nextProps: restProps,
lastIframe: lastIframe,
state: state,
src: state.load ? getYoutubeUrl({
videoId: videoId,
videoParams: thisVideoParams.current,
hostname: lastHostname.current
}) : undefined
};
};
/**
* @type React.ForwardRefExoticComponent<?, YoutubeRWDProps>
*/
var YoutubeRWD = forwardRef(function (props, ref) {
var _useYoutubeRWD = useYoutubeRWD(props),
expose = _useYoutubeRWD.expose,
handler = _useYoutubeRWD.handler,
nextProps = _useYoutubeRWD.nextProps,
lastIframe = _useYoutubeRWD.lastIframe,
state = _useYoutubeRWD.state,
src = _useYoutubeRWD.src;
var loading = nextProps.loading,
onError = nextProps.onError,
restProps = (0, _objectWithoutPropertiesLoose2["default"])(nextProps, _excluded2);
useImperativeHandle(ref, function () {
return expose;
}, []);
if (!state.load) {
return null;
}
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ResponsiveVideo["default"], (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, restProps), {}, {
onClick: handler.click,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_organismReactIframe.IframeContainer, {
loading: loading,
allow: "autoplay; fullscreen; encrypted-media",
src: src,
ref: lastIframe,
onLoad: handler.load,
onError: onError
})
}));
});
var _default = exports["default"] = YoutubeRWD;
module.exports = exports.default;