Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from "react";
- import * as Sentry from "@sentry/nextjs";
- import classnames from "classnames";
- import classnamesBind from "classnames/bind";
- import isEqual from "lodash/isEqual";
- import videojs from "video.js";
- import "videojs-contrib-quality-levels";
- import "videojs-hls-quality-selector";
- import "videojs-seek-buttons";
- require("videojs-hotkeys");
- // todo use import after rewriting to ts
- require("../../../helpers/videojs-thumbnails");
- import { getCookiesLocalStorageValue, setCookiesLocalStorageValue } from "../../../helpers/CookiesLocalStorage";
- import Loader from "../Loader";
- import styles from "./VideoPlayer.module.scss";
- const cx = classnamesBind.bind(styles);
- const initialOptions: videojs.PlayerOptions = {
- controls: true,
- fluid: true,
- preload: "auto",
- controlBar: {
- volumePanel: {
- inline: false,
- },
- },
- };
- interface VideoPlayerProps extends React.VideoHTMLAttributes<HTMLVideoElement> {
- options: videojs.PlayerOptions;
- thumbnailTemplate?: string;
- onReady?: (player: videojs.Player) => void;
- seekSeconds?: number;
- isLoading?: boolean;
- }
- function VideoPlayer(props: VideoPlayerProps): React.ReactElement {
- const { options, thumbnailTemplate, onReady, seekSeconds, isLoading = false, ...rest } = props;
- const videoRef = React.useRef<HTMLVideoElement>(null);
- const playerRef = React.useRef<videojs.Player | null>(null);
- React.useEffect(() => {
- // Make sure Video.js player is only initialized once
- if (!playerRef.current) {
- const videoElement = videoRef.current;
- if (!videoElement) return;
- const allOptions = {
- ...initialOptions,
- ...options,
- };
- if (allOptions.sources && allOptions.sources.length > 0) {
- try {
- const player = playerRef.current = videojs(videoElement, allOptions, () => {
- onReady && onReady(player);
- });
- const playerSavedVolume = getCookiesLocalStorageValue("videojs:volume");
- if (playerSavedVolume !== null) {
- if (playerSavedVolume === "muted") {
- player.muted(true);
- } else if (playerSavedVolume) {
- player.volume(parseFloat(playerSavedVolume));
- }
- }
- } catch (e) {
- Sentry.captureException(e);
- }
- try {
- playerRef.current?.on("error", (err) => {
- Sentry.captureException(err);
- });
- } catch (e) {
- console.error(e);
- }
- try {
- playerRef.current?.on("volumechange", function() {
- if (playerRef.current) {
- setCookiesLocalStorageValue(
- "videojs:volume",
- playerRef.current.muted() ? "muted" : playerRef.current.volume().toString()
- );
- }
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- try {
- playerRef.current?.hlsQualitySelector({
- vjsIconClass: "vjs-icon-cog",
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- if (thumbnailTemplate) {
- try {
- playerRef.current?.thumbnails({
- width: 142,
- height: 80,
- preload: true,
- interval: 5,
- template: thumbnailTemplate,
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- }
- try {
- playerRef.current?.seekButtons({
- back: seekSeconds ?? 15,
- forward: seekSeconds ?? 30,
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- try {
- playerRef.current?.on("ended", () => {
- if (playerRef.current?.isFullscreen()) {
- playerRef.current?.exitFullscreen();
- }
- playerRef.current?.currentTime(0);
- playerRef.current?.hasStarted(false);
- playerRef.current?.trigger("ready");
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- try {
- playerRef.current?.on("touchstart", (e) => {
- if (e.target.nodeName === "VIDEO") {
- if (playerRef.current?.paused()) {
- playerRef.current?.play();
- } else {
- playerRef.current?.pause();
- }
- }
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- try {
- playerRef.current?.hotkeys({
- volumeStep: 0.1,
- seekStep: seekSeconds ?? 5,
- enableModifiersForNumbers: false,
- enableHoverScroll: true,
- });
- } catch (e) {
- Sentry.captureException(e);
- }
- }
- } else {
- // update already initialized player
- if (options.autoplay) {
- playerRef.current.autoplay(options.autoplay);
- }
- if (options.sources) {
- if (options.sources.length === 0) {
- playerRef.current.pause();
- } else {
- playerRef.current.src(options.sources);
- }
- }
- if (options.poster) {
- playerRef.current.poster(options.poster);
- }
- }
- }, [onReady, options, seekSeconds, thumbnailTemplate]);
- // Dispose the Video.js player when the functional component unmounts
- React.useEffect(() => {
- return () => {
- if (playerRef.current) {
- playerRef.current.dispose();
- playerRef.current = null;
- }
- };
- }, []);
- const containerClassName = cx({
- container: true,
- isLoading: isLoading,
- });
- const videoClassName = classnames({
- [styles.videoPlayer]: true,
- "video-js": true,
- "vjs-big-play-centered": true,
- });
- return (
- <div className={ containerClassName }>
- <div className={ styles.loaderWrapper }>
- <Loader isLoading={ isLoading } />
- </div>
- <div data-vjs-player="">
- { /* eslint-disable-next-line jsx-a11y/media-has-caption */ }
- <video
- ref={ videoRef }
- className={ videoClassName }
- { ...rest }
- />
- </div>
- </div>
- );
- }
- export default React.memo(VideoPlayer, (prevProps, nextProps): boolean => {
- const { options: prevPropsOptions, seekSeconds: prevPropsSeekSeconds, ...prevPropsRest } = prevProps;
- const { options: nextPropsOptions, seekSeconds: nextPropsSeekSeconds, ...nextPropsRest } = nextProps;
- return isEqual(prevPropsOptions, nextPropsOptions)
- && prevPropsSeekSeconds === nextPropsSeekSeconds
- && isEqual(prevPropsRest, nextPropsRest);
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement