panjareh
Version:
Panjareh using aparat and phoenix-video-player to play videos on desktops and tvs.
262 lines (241 loc) • 6.84 kB
JavaScript
import React, { useEffect, useRef } from "react";
import { isObject } from "../utils";
import VJSPlayer from "@filmgardi/phoenix-video-player";
import PropTypes from "prop-types";
import QueryParameter from "../utils/queryParameter";
import cookiesName from "../enums/cookies-name";
import "@filmgardi/phoenix-video-player/dist/phoenix-video-player.min.css";
import "@filmgardi/videojs-phoenix-theme/dist/videojs-phoenix-theme.css";
const DEFAULT_OPTIONS = {
autoplay: false,
controls: true,
playbackRates: [0.5, 1, 1.25, 1.5],
language: "fa",
// addLanguage: { fa: fa },
poster: "",
sources: [],
info: { title: null, subTitle: null },
returnUrl: null,
html5: {
nativeTextTracks: !1,
hlsjsConfig: {
// Put your hls.js config here
// debug: true,
enableWorker: false,
lowLatencyMode: true,
backBufferLength: 60,
// maxBufferSize: 60 * 1000 * 1000,
// startLevel: 0,
},
},
pluginOptions: {
seekThumbnailSrc: null,
seekButtons: {
forward: 10,
back: 10,
forwardIndex: 1,
backIndex: 1,
},
nextEpisode: {
url: "",
autoAdvance: true,
showAutoAdvanceButton: true,
autoAdvanceButtonText: "قسمت بعدی",
nextEpisodeDisplayTime: null,
nextEpisodeDisplayDuration: 10,
dialogData: {
title: "",
description: "",
url: ``,
},
dialogTemplate: ({ title, description, url }) => {
const container = document.createElement("div");
container.className = "vjs-next-episode-dialog-content";
container.style.flexDirection = "row";
container.style.alignItems = "self-end";
container.style.width = "420px";
container.style.padding = "12px 24px";
const img = document.createElement("img");
img.className = "vjs-next-episode-dialog-poster";
img.src = url;
img.style.width = "140px";
img.style.height = "65px";
img.style.marginLeft = "24px";
container.appendChild(img);
const episodeContent = document.createElement("div");
episodeContent.className = "vjs-next-episode-content";
episodeContent.style.display = "flex";
episodeContent.style.flexDirection = "column";
episodeContent.style.justifyContent = "end";
episodeContent.style.textAlign = "right";
container.appendChild(episodeContent);
const titleEl = document.createElement("span");
titleEl.className = "vjs-next-episode-dialog-title";
titleEl.innerHTML = title;
episodeContent.appendChild(titleEl);
const descriptionEl = document.createElement("span");
descriptionEl.className = "vjs-next-episode-dialog-description";
descriptionEl.innerHTML = description;
episodeContent.appendChild(descriptionEl);
return container;
},
// placementIndex: 9,
},
skipButton: {
text: "skipOpeningCredits",
from: null,
to: null,
position: "bottom-right",
offsetH: 46,
offsetV: 167,
},
trafficUsage: {
title: null,
message: null,
expireTime: 5, // minute
position: "top-right",
offsetH: 46,
offsetV: 46,
},
subtitleSettings: {},
seasonPlaylist: {
seasons: null, // array of number
getEpisode: (season, page, callback) => {
callback({
alias: "",
duration: 0,
link: "",
part: 0,
season: 0,
thumbnail: "",
title: null,
});
},
},
vote: {
submitVote: ({ likeStatus, callback }) => {
return { likeStatus, callback };
}, //Tips: likeStatus returns 1 if liked and 2 if disliked
from: null,
to: null,
position: "bottom-right",
offsetH: 46,
offsetV: 167,
},
collectData: {
token: "",
},
markers: {
markerTip: {
display: false,
skip: true,
},
onMarkerReached: (marker, index) => {
console.log(marker, index);
},
onMarkerSkipZone: (marker, index) => {
console.log("onMarkerSkipZone", marker, index);
},
markers: [{ time: null, duration: null }],
},
},
// initPlugins: {
// seekButtons,
// vttThumbnails
// },
// controlBar: { children: ['playToggle'] },
};
const VideoPlayer = ({
className = "",
options,
onReady = () => {},
videoProgress = () => {},
}) => {
const videoRef = useRef(null);
useEffect(() => {
const observeVideoProgress = setInterval(() => {
const video = (videoRef && videoRef.current) || null;
if (video && !video.paused) {
const { duration, currentTime } = video;
videoProgress({
duration,
currentTime,
});
}
}, 500);
return () => {
clearInterval(observeVideoProgress);
};
});
useEffect(() => {
// assign default plugin options to existing given plugin options
const pluginConfig = {};
for (const [key, value] of Object.entries(options.pluginOptions)) {
pluginConfig[key] = isObject(value)
? Object.assign({}, DEFAULT_OPTIONS.pluginOptions[key], value)
: value;
}
DEFAULT_OPTIONS.html5.hlsjsConfig["xhrSetup"] = function (xhr, url) {
const { extraData } = options;
url = QueryParameter.append(
cookiesName.UuidUnderLine,
extraData[cookiesName.UuidUnderLine],
url
);
xhr.open("GET", url, true);
};
Object.assign(options.pluginOptions, pluginConfig);
const playerOptions = Object.assign(
{},
// consts.PLAYER_CONFIG,
DEFAULT_OPTIONS,
options
);
const player = new VJSPlayer(videoRef.current, playerOptions, (player) => {
onReady(player);
});
return () => {
if (player) {
player.dispose();
}
};
});
return (
<div className={["wrapper", ...className].join(" ")}>
<div data-vjs-player>
<video
ref={videoRef}
className={[
"video-js",
"vjs-big-play-centered",
"fullscreen",
"fullScreen-fixed",
"vjs-fill",
].join(" ")}
/>
</div>
</div>
);
};
VideoPlayer.defaultProps = {
className: [],
autoplay: false,
controls: true,
playbackRates: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
poster: "",
sources: [],
videoProgress: () => null,
onReady: () => null,
};
VideoPlayer.propTypes = {
className: PropTypes.array,
options: PropTypes.object,
autoplay: PropTypes.bool,
controls: PropTypes.bool,
playbackRates: PropTypes.array,
poster: PropTypes.string,
sources: PropTypes.array,
videoProgress: PropTypes.func,
onReady: PropTypes.func,
};
export default VideoPlayer;