2021-06-10 21:52:22 +02:00
|
|
|
import { h } from 'preact';
|
2021-06-10 21:02:43 +02:00
|
|
|
import { useRef, useEffect } from 'preact/hooks';
|
2021-05-28 19:13:48 +02:00
|
|
|
import videojs from 'video.js';
|
|
|
|
import 'videojs-playlist';
|
|
|
|
import 'video.js/dist/video-js.css';
|
|
|
|
|
2023-04-16 14:09:51 +02:00
|
|
|
export default function VideoPlayer({ children, options, seekOptions = {forward:30, backward: 10}, onReady = () => {}, onDispose = () => {} }) {
|
2021-06-10 21:02:43 +02:00
|
|
|
const playerRef = useRef();
|
2022-05-16 13:49:47 +02:00
|
|
|
|
2021-06-10 21:02:43 +02:00
|
|
|
useEffect(() => {
|
2022-05-16 13:49:47 +02:00
|
|
|
const defaultOptions = {
|
|
|
|
controls: true,
|
2023-04-16 14:09:51 +02:00
|
|
|
controlBar: {
|
|
|
|
skipButtons: seekOptions,
|
|
|
|
},
|
2022-05-16 13:49:47 +02:00
|
|
|
playbackRates: [0.5, 1, 2, 4, 8],
|
|
|
|
fluid: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (!videojs.browser.IS_FIREFOX) {
|
|
|
|
defaultOptions.playbackRates.push(16);
|
|
|
|
}
|
|
|
|
|
2021-06-10 21:02:43 +02:00
|
|
|
const player = videojs(playerRef.current, { ...defaultOptions, ...options }, () => {
|
|
|
|
onReady(player);
|
2021-06-04 01:38:05 +02:00
|
|
|
});
|
2021-05-28 19:13:48 +02:00
|
|
|
|
2022-12-18 00:53:34 +01:00
|
|
|
// Allows player to continue on error
|
|
|
|
player.reloadSourceOnError();
|
|
|
|
|
2021-06-10 21:02:43 +02:00
|
|
|
// Disable fullscreen on iOS if we have children
|
|
|
|
if (
|
|
|
|
children &&
|
|
|
|
videojs.browser.IS_IOS &&
|
|
|
|
videojs.browser.IOS_VERSION > 9 &&
|
|
|
|
!player.el_.ownerDocument.querySelector('.bc-iframe')
|
|
|
|
) {
|
|
|
|
player.tech_.el_.setAttribute('playsinline', 'playsinline');
|
|
|
|
player.tech_.supportsFullScreen = function () {
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
const screen = window.screen;
|
|
|
|
|
|
|
|
const angle = () => {
|
|
|
|
// iOS
|
|
|
|
if (typeof window.orientation === 'number') {
|
|
|
|
return window.orientation;
|
|
|
|
}
|
|
|
|
// Android
|
|
|
|
if (screen && screen.orientation && screen.orientation.angle) {
|
|
|
|
return window.orientation;
|
|
|
|
}
|
|
|
|
videojs.log('angle unknown');
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const rotationHandler = () => {
|
|
|
|
const currentAngle = angle();
|
|
|
|
|
|
|
|
if (currentAngle === 90 || currentAngle === 270 || currentAngle === -90) {
|
|
|
|
if (player.paused() === false) {
|
|
|
|
player.requestFullscreen();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((currentAngle === 0 || currentAngle === 180) && player.isFullscreen()) {
|
|
|
|
player.exitFullscreen();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (videojs.browser.IS_IOS) {
|
|
|
|
window.addEventListener('orientationchange', rotationHandler);
|
|
|
|
} else if (videojs.browser.IS_ANDROID && screen.orientation) {
|
|
|
|
// addEventListener('orientationchange') is not a user interaction on Android
|
|
|
|
screen.orientation.onchange = rotationHandler;
|
2021-05-28 19:13:48 +02:00
|
|
|
}
|
2021-06-10 21:02:43 +02:00
|
|
|
|
|
|
|
return () => {
|
|
|
|
if (videojs.browser.IS_IOS) {
|
|
|
|
window.removeEventListener('orientationchange', rotationHandler);
|
|
|
|
}
|
|
|
|
player.dispose();
|
|
|
|
onDispose();
|
|
|
|
};
|
2021-06-10 21:52:22 +02:00
|
|
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
2021-06-10 21:02:43 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div data-vjs-player>
|
2022-06-02 14:06:39 +02:00
|
|
|
{/* Setting an empty data-setup is required to override the default values and allow video to be fit the size of its parent */}
|
|
|
|
<video ref={playerRef} className="small-player video-js vjs-default-skin" data-setup="{}" controls playsinline />
|
2021-06-10 21:02:43 +02:00
|
|
|
{children}
|
|
|
|
</div>
|
|
|
|
);
|
2022-11-02 12:36:09 +01:00
|
|
|
}
|