2022-10-12 18:17:07 +00:00
|
|
|
import * as React from "react";
|
2022-10-31 15:08:29 +00:00
|
|
|
import styled, { css } from "styled-components";
|
|
|
|
import { isMobileOnly } from "react-device-detect";
|
2022-10-27 06:58:19 +00:00
|
|
|
import { tablet } from "@docspace/components/utils/device";
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
import IconPlay from "../../../../public/images/videoplayer.play.react.svg";
|
|
|
|
import IconStop from "../../../../public/images/videoplayer.stop.react.svg";
|
|
|
|
|
|
|
|
import IconSound from "../../../../public/images/videoplayer.sound.react.svg";
|
|
|
|
import IconMuted from "../../../../public/images/videoplayer.mute.react.svg";
|
|
|
|
|
|
|
|
import IconFullScreen from "../../../../public/images/videoplayer.full.react.svg";
|
|
|
|
import IconExitFullScreen from "../../../../public/images/videoplayer.exit.react.svg";
|
2022-10-14 14:00:03 +00:00
|
|
|
import IconSpeed from "../../../../public/images/videoplayer.speed.react.svg";
|
|
|
|
import MediaContextMenu from "../../../../public/images/vertical-dots.react.svg";
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
import BigIconPlay from "../../../../public/images/videoplayer.bgplay.react.svg";
|
2022-11-14 12:31:19 +00:00
|
|
|
import { useSwipeable } from "react-swipeable";
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
let iconWidth = 80;
|
|
|
|
let iconHeight = 60;
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const ACTION_TYPES = {
|
|
|
|
setActiveIndex: "setActiveIndex",
|
|
|
|
update: "update",
|
|
|
|
};
|
|
|
|
|
|
|
|
function createAction(type, payload) {
|
|
|
|
return {
|
|
|
|
type,
|
|
|
|
payload: payload || {},
|
|
|
|
};
|
|
|
|
}
|
2022-10-13 08:52:24 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const StyledVideoPlayer = styled.div`
|
2022-10-27 06:58:19 +00:00
|
|
|
&:focus-visible,
|
|
|
|
#videoPlayer:focus-visible {
|
|
|
|
outline: none;
|
|
|
|
}
|
2022-10-13 08:52:24 +00:00
|
|
|
.video-wrapper {
|
|
|
|
position: fixed;
|
2022-10-27 06:58:19 +00:00
|
|
|
z-index: 305;
|
2022-10-13 08:52:24 +00:00
|
|
|
top: 0;
|
2022-10-31 15:08:29 +00:00
|
|
|
${isMobileOnly &&
|
|
|
|
css`
|
|
|
|
top: 0;
|
|
|
|
`}
|
2022-10-13 08:52:24 +00:00
|
|
|
bottom: 0;
|
|
|
|
right: 0;
|
|
|
|
left: 0;
|
2022-10-14 14:00:03 +00:00
|
|
|
${(props) =>
|
|
|
|
props.isFullScreen ? "background: #000" : "background: transparent"};
|
|
|
|
}
|
|
|
|
|
2022-11-02 15:07:05 +00:00
|
|
|
svg {
|
|
|
|
path {
|
|
|
|
fill: #fff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
.dropdown-speed {
|
|
|
|
position: relative;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
.dropdown-item {
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
justify-content: center;
|
|
|
|
border-radius: 3px 3px 0px 0px;
|
|
|
|
height: 30px;
|
|
|
|
width: 40px;
|
|
|
|
&:hover {
|
|
|
|
cursor: pointer;
|
|
|
|
background: #222;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.dropdown-content {
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: center;
|
|
|
|
position: absolute;
|
|
|
|
bottom: 52px;
|
|
|
|
color: #fff;
|
|
|
|
background: #000;
|
|
|
|
text-align: center;
|
|
|
|
border-radius: 3px 3px 0px 0px;
|
2022-10-13 08:52:24 +00:00
|
|
|
}
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
.bg-play {
|
|
|
|
position: fixed;
|
|
|
|
&:hover {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
input[type="range"] {
|
2022-10-14 14:00:03 +00:00
|
|
|
-webkit-appearance: none;
|
|
|
|
margin-right: 15px;
|
|
|
|
width: 80%;
|
2022-10-27 06:58:19 +00:00
|
|
|
height: 8px;
|
2022-10-12 18:17:07 +00:00
|
|
|
background: #4d4d4d;
|
|
|
|
border: 1px solid rgba(0, 0, 0, 0.4);
|
2022-10-14 14:00:03 +00:00
|
|
|
border-radius: 5px;
|
|
|
|
background-image: linear-gradient(#d1d1d1, #d1d1d1);
|
|
|
|
background-repeat: no-repeat;
|
2022-10-27 06:58:19 +00:00
|
|
|
|
|
|
|
@media ${tablet} {
|
|
|
|
width: 63%;
|
|
|
|
}
|
2022-10-12 18:17:07 +00:00
|
|
|
}
|
|
|
|
input[type="range"]::-webkit-slider-thumb {
|
2022-10-14 14:00:03 +00:00
|
|
|
-webkit-appearance: none;
|
|
|
|
height: 14px;
|
|
|
|
width: 14px;
|
|
|
|
border-radius: 50%;
|
|
|
|
background: #fff;
|
|
|
|
border: 1px solid rgba(0, 0, 0);
|
2022-10-12 18:17:07 +00:00
|
|
|
}
|
2022-10-18 12:36:36 +00:00
|
|
|
|
2022-11-14 12:31:19 +00:00
|
|
|
.mobile-video-progress {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
position: fixed;
|
|
|
|
right: 0;
|
|
|
|
bottom: 48px;
|
|
|
|
left: 0;
|
|
|
|
z-index: 307;
|
|
|
|
padding: 0 20px;
|
|
|
|
height: 30px;
|
2022-11-14 14:52:57 +00:00
|
|
|
background: RGB(110, 110, 110);
|
2022-11-14 12:31:19 +00:00
|
|
|
|
|
|
|
input[type="range"] {
|
|
|
|
width: 100%;
|
|
|
|
margin-right: 0px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const StyledVideoActions = styled.div`
|
|
|
|
.actions-container {
|
|
|
|
display: flex;
|
|
|
|
justify-content: start;
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
${isMobileOnly &&
|
|
|
|
css`
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
.fullscreen-button {
|
|
|
|
order: -1;
|
|
|
|
}
|
|
|
|
`}
|
|
|
|
}
|
|
|
|
|
|
|
|
.controller {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
min-width: 48px;
|
|
|
|
height: 48px;
|
|
|
|
&:hover {
|
|
|
|
cursor: pointer;
|
|
|
|
background: rgb(77, 77, 77);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const StyledVideoControls = styled.div`
|
|
|
|
position: fixed;
|
|
|
|
right: 0;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
|
|
|
z-index: 307;
|
|
|
|
height: 48px;
|
2022-11-14 14:52:57 +00:00
|
|
|
background: RGB(110, 110, 110);
|
2022-10-18 12:36:36 +00:00
|
|
|
.volume-container {
|
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
2022-10-27 06:58:19 +00:00
|
|
|
.volume-wrapper {
|
|
|
|
background: #000;
|
2022-10-18 12:36:36 +00:00
|
|
|
position: absolute;
|
2022-10-27 06:58:19 +00:00
|
|
|
bottom: 78px;
|
|
|
|
padding: 9px;
|
2022-10-18 12:36:36 +00:00
|
|
|
transform: rotate(270deg);
|
2022-10-27 06:58:19 +00:00
|
|
|
// left: -4px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.volume-toolbar {
|
|
|
|
width: 50px !important;
|
2022-10-18 12:36:36 +00:00
|
|
|
}
|
2022-10-12 18:17:07 +00:00
|
|
|
`;
|
|
|
|
|
|
|
|
const getDuration = (time) => {
|
|
|
|
const timestamp = Math.floor(time);
|
|
|
|
|
|
|
|
const hours = Math.floor(timestamp / 60 / 60);
|
|
|
|
const minutes = Math.floor(timestamp / 60) - hours * 60;
|
|
|
|
const seconds = timestamp % 60;
|
|
|
|
|
|
|
|
const formatted = hours
|
|
|
|
? [
|
|
|
|
hours.toString().padStart(2, "0"),
|
|
|
|
minutes.toString().padStart(2, "0"),
|
|
|
|
seconds.toString().padStart(2, "0"),
|
|
|
|
].join(":")
|
|
|
|
: [
|
|
|
|
minutes.toString().padStart(2, "0"),
|
|
|
|
seconds.toString().padStart(2, "0"),
|
|
|
|
].join(":");
|
|
|
|
|
|
|
|
return formatted;
|
|
|
|
};
|
|
|
|
|
|
|
|
export default function ViewerPlayer(props) {
|
2022-10-31 15:08:29 +00:00
|
|
|
const {
|
|
|
|
setIsFullScreen,
|
|
|
|
videoRef,
|
|
|
|
generateContextMenu,
|
2022-11-02 15:07:05 +00:00
|
|
|
mobileDetails,
|
2022-11-14 12:31:19 +00:00
|
|
|
onPrevClick,
|
|
|
|
onNextClick,
|
2022-10-31 15:08:29 +00:00
|
|
|
} = props;
|
2022-10-14 14:00:03 +00:00
|
|
|
|
|
|
|
const initialState = {
|
|
|
|
width: 0,
|
|
|
|
height: 0,
|
|
|
|
left: 0,
|
|
|
|
top: 0,
|
|
|
|
activeIndex: props.activeIndex,
|
|
|
|
isPlaying: false,
|
|
|
|
isMuted: false,
|
|
|
|
isFullScreen: false,
|
|
|
|
speedSelection: false,
|
|
|
|
progress: 0,
|
|
|
|
duration: 0,
|
2022-10-18 12:36:36 +00:00
|
|
|
volumeSelection: false,
|
|
|
|
volume: 100,
|
2022-10-14 14:00:03 +00:00
|
|
|
size: "0%",
|
|
|
|
};
|
|
|
|
function reducer(state, action) {
|
|
|
|
switch (action.type) {
|
|
|
|
case ACTION_TYPES.setActiveIndex:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
activeIndex: action.payload.index,
|
|
|
|
startLoading: true,
|
|
|
|
};
|
|
|
|
case ACTION_TYPES.update:
|
|
|
|
return {
|
|
|
|
...state,
|
|
|
|
...action.payload,
|
|
|
|
};
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}
|
2022-10-12 18:17:07 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const inputRef = React.useRef(null);
|
2022-10-27 06:58:19 +00:00
|
|
|
const volumeRef = React.useRef(null);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const [state, dispatch] = React.useReducer(reducer, initialState);
|
2022-10-27 11:07:09 +00:00
|
|
|
const [isOpen, setIsOpen] = React.useState(false);
|
2022-11-14 12:31:19 +00:00
|
|
|
const handlers = useSwipeable({
|
|
|
|
onSwipedLeft: (e) => {
|
|
|
|
if (e.event.path[0] === inputRef.current) return;
|
|
|
|
onNextClick();
|
|
|
|
},
|
|
|
|
onSwipedRight: (e) => {
|
|
|
|
if (e.event.path[0] === inputRef.current) return;
|
|
|
|
onPrevClick();
|
|
|
|
},
|
|
|
|
});
|
2022-10-12 18:17:07 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const footerHeight = 48;
|
2022-11-14 12:31:19 +00:00
|
|
|
const titleHeight = 53;
|
2022-10-12 18:17:07 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const togglePlay = () =>
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
isPlaying: !state.isPlaying,
|
|
|
|
})
|
|
|
|
);
|
2022-10-18 12:36:36 +00:00
|
|
|
const handleVolumeUpdate = (e) => {
|
|
|
|
const volume = e.target.value / 100;
|
|
|
|
|
|
|
|
videoRef.current.volume = volume;
|
|
|
|
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
isMuted: volume ? false : true,
|
|
|
|
volume: e.target.value,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const toggleVolumeSelection = () =>
|
2022-10-14 14:00:03 +00:00
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
2022-10-18 12:36:36 +00:00
|
|
|
volumeSelection: !state.volumeSelection,
|
2022-10-14 14:00:03 +00:00
|
|
|
})
|
|
|
|
);
|
2022-10-18 12:36:36 +00:00
|
|
|
|
2022-11-14 12:31:19 +00:00
|
|
|
const toggleScreen = () => {
|
2022-10-14 14:00:03 +00:00
|
|
|
handleFullScreen(!state.isFullScreen);
|
|
|
|
setIsFullScreen(!state.isFullScreen);
|
|
|
|
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
isFullScreen: !state.isFullScreen,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
};
|
2022-10-12 18:17:07 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const toggleSpeedSelectionMenu = () =>
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
speedSelection: !state.speedSelection,
|
|
|
|
})
|
|
|
|
);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
const elem = document.documentElement;
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const handleFullScreen = (isFull) => {
|
|
|
|
if (elem.requestFullscreen && isFull) return elem.requestFullscreen();
|
|
|
|
return document.exitFullscreen();
|
|
|
|
};
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
const handleVideoProgress = (e) => {
|
|
|
|
const manualChange = Number(e.target.value);
|
2022-10-14 14:00:03 +00:00
|
|
|
videoRef.current.currentTime =
|
|
|
|
(videoRef.current.duration / 100) * manualChange;
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
progress: manualChange,
|
|
|
|
})
|
|
|
|
);
|
2022-10-12 18:17:07 +00:00
|
|
|
};
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const handleVideoSpeed = (speed) => {
|
|
|
|
const currentSpeeed = Number(speed);
|
|
|
|
videoRef.current.playbackRate = currentSpeeed;
|
|
|
|
};
|
|
|
|
|
|
|
|
const SpeedButtonComponent = () => {
|
|
|
|
const speed = ["0.5", "1", "1.5", "2"];
|
|
|
|
const items = speed.map((speed) => (
|
|
|
|
<div
|
|
|
|
className="dropdown-item"
|
|
|
|
onClick={() => {
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
speedSelection: false,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
return handleVideoSpeed(speed);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{speed}
|
|
|
|
</div>
|
|
|
|
));
|
|
|
|
return items;
|
|
|
|
};
|
|
|
|
|
|
|
|
const getVideoPosition = (video) => {
|
2022-10-12 18:17:07 +00:00
|
|
|
const [width, height] = getVideoWidthHeight(video);
|
2022-10-14 14:00:03 +00:00
|
|
|
|
2022-10-12 18:17:07 +00:00
|
|
|
let left = (window.innerWidth - width) / 2;
|
2022-10-14 14:00:03 +00:00
|
|
|
let top = !state.isFullScreen
|
2022-11-14 12:31:19 +00:00
|
|
|
? (window.innerHeight - height - (footerHeight - 53)) / 2
|
2022-10-14 14:00:03 +00:00
|
|
|
: 0;
|
|
|
|
|
|
|
|
return [width, height, left, top];
|
2022-10-12 18:17:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const getVideoWidthHeight = (video) => {
|
|
|
|
let width = 0;
|
|
|
|
let height = 0;
|
|
|
|
|
|
|
|
let maxWidth = window.innerWidth;
|
2022-10-14 14:00:03 +00:00
|
|
|
let maxHeight = !state.isFullScreen
|
|
|
|
? window.innerHeight - (footerHeight + titleHeight)
|
|
|
|
: window.innerHeight - footerHeight;
|
|
|
|
|
2022-10-31 15:08:29 +00:00
|
|
|
if (isMobileOnly) {
|
|
|
|
maxHeight = window.innerHeight;
|
|
|
|
}
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
width =
|
|
|
|
video.videoWidth > maxWidth
|
|
|
|
? maxWidth
|
2022-10-27 06:58:19 +00:00
|
|
|
: state.isFullScreen
|
|
|
|
? Math.max(maxWidth, video.videoWidth)
|
|
|
|
: Math.min(maxWidth, video.videoWidth);
|
|
|
|
|
2022-10-12 18:17:07 +00:00
|
|
|
height = (width / video.videoWidth) * video.videoHeight;
|
|
|
|
|
|
|
|
if (height > maxHeight) {
|
|
|
|
height = maxHeight;
|
|
|
|
width = (height / video.videoHeight) * video.videoWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [width, height];
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleOnTimeUpdate = () => {
|
|
|
|
const progress =
|
2022-10-14 14:00:03 +00:00
|
|
|
(videoRef.current.currentTime / videoRef.current.duration) * 100;
|
2022-10-12 18:17:07 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const currentTime = getDuration(videoRef.current.currentTime);
|
|
|
|
const duration = getDuration(videoRef.current.duration);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
const lasting = `${currentTime} / ${duration}`;
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
duration: lasting,
|
|
|
|
progress: progress,
|
|
|
|
})
|
|
|
|
);
|
2022-10-12 18:17:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const handleResize = () => {
|
2022-10-14 14:00:03 +00:00
|
|
|
let video = videoRef.current;
|
|
|
|
const [width, height, left, top] = getVideoPosition(video);
|
|
|
|
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
width: width,
|
|
|
|
height: height,
|
|
|
|
left: left,
|
|
|
|
top: top,
|
|
|
|
})
|
|
|
|
);
|
2022-10-12 18:17:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
2022-10-14 14:00:03 +00:00
|
|
|
state.isMuted
|
|
|
|
? (videoRef.current.muted = true)
|
|
|
|
: (videoRef.current.muted = false);
|
|
|
|
}, [state.isMuted, videoRef.current]);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
2022-11-14 12:31:19 +00:00
|
|
|
if (!inputRef.current) return;
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
inputRef.current.style.backgroundSize =
|
|
|
|
((state.progress - inputRef.current.min) * 100) /
|
|
|
|
(inputRef.current.max - inputRef.current.min) +
|
|
|
|
"% 100%";
|
|
|
|
}, [inputRef.current, state.progress]);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
window.addEventListener("resize", handleResize);
|
|
|
|
|
|
|
|
return () => window.removeEventListener("resize", handleResize);
|
2022-10-14 14:00:03 +00:00
|
|
|
}, [videoRef.current, state.isFullScreen]);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
2022-10-14 14:00:03 +00:00
|
|
|
state.isPlaying ? videoRef.current.play() : videoRef.current.pause();
|
|
|
|
}, [state.isPlaying, videoRef.current]);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
function loadVideo(video) {
|
2022-10-14 14:00:03 +00:00
|
|
|
const currentTime = getDuration(video.currentTime);
|
|
|
|
const duration = getDuration(video.duration);
|
2022-10-12 18:17:07 +00:00
|
|
|
|
|
|
|
const lasting = `${currentTime} / ${duration}`;
|
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
const [width, height, left, top] = getVideoPosition(video);
|
|
|
|
dispatch(
|
|
|
|
createAction(ACTION_TYPES.update, {
|
|
|
|
width: width,
|
|
|
|
height: height,
|
|
|
|
left: left,
|
|
|
|
top: top,
|
|
|
|
duration: lasting,
|
|
|
|
progress: 0,
|
|
|
|
isPlaying: false,
|
|
|
|
isMuted: false,
|
|
|
|
isFullScreen: state.isFullScreen,
|
|
|
|
speedSelection: false,
|
2022-10-18 12:36:36 +00:00
|
|
|
volume: state.volume,
|
2022-10-14 14:00:03 +00:00
|
|
|
})
|
|
|
|
);
|
2022-10-12 18:17:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
2022-10-14 14:00:03 +00:00
|
|
|
videoRef.current.addEventListener("loadedmetadata", function (e) {
|
|
|
|
loadVideo(videoRef.current);
|
2022-10-12 18:17:07 +00:00
|
|
|
});
|
2022-10-14 14:00:03 +00:00
|
|
|
}, [props.activeIndex]);
|
|
|
|
|
2022-10-27 11:07:09 +00:00
|
|
|
const contextMenu = generateContextMenu(isOpen);
|
|
|
|
|
2022-10-18 12:36:36 +00:00
|
|
|
let iconLeft = (window.innerWidth - iconWidth) / 2 + "px";
|
2022-11-14 12:31:19 +00:00
|
|
|
let iconTop = (window.innerHeight - iconHeight - (48 - 53)) / 2 + "px";
|
2022-10-18 12:36:36 +00:00
|
|
|
|
2022-10-14 14:00:03 +00:00
|
|
|
let imgStyle = {
|
|
|
|
width: `${state.width}px`,
|
|
|
|
height: `${state.height}px`,
|
|
|
|
transition: "all .26s ease-out",
|
|
|
|
transform: `
|
|
|
|
translateX(${state.left !== null ? state.left + "px" : "auto"}) translateY(${
|
|
|
|
state.top
|
|
|
|
}px)`,
|
|
|
|
};
|
2022-10-12 18:17:07 +00:00
|
|
|
return (
|
2022-11-14 12:31:19 +00:00
|
|
|
<StyledVideoPlayer
|
|
|
|
id="video-playerId"
|
|
|
|
isFullScreen={state.isFullScreen}
|
|
|
|
{...handlers}
|
|
|
|
>
|
2022-11-02 15:07:05 +00:00
|
|
|
{!state.isFullScreen && isMobileOnly && mobileDetails}
|
2022-10-12 18:17:07 +00:00
|
|
|
<div className="video-wrapper">
|
|
|
|
<video
|
|
|
|
onClick={togglePlay}
|
|
|
|
id="videoPlayer"
|
2022-10-14 14:00:03 +00:00
|
|
|
ref={videoRef}
|
2022-10-12 18:17:07 +00:00
|
|
|
src={props.video.src}
|
2022-10-14 14:00:03 +00:00
|
|
|
style={imgStyle}
|
2022-10-12 18:17:07 +00:00
|
|
|
onTimeUpdate={handleOnTimeUpdate}
|
|
|
|
></video>
|
2022-10-18 12:36:36 +00:00
|
|
|
{!state.isPlaying && (
|
|
|
|
<div
|
|
|
|
className="bg-play"
|
|
|
|
style={{ left: `${iconLeft}`, top: `${iconTop}` }}
|
|
|
|
>
|
2022-10-12 18:17:07 +00:00
|
|
|
<BigIconPlay onClick={togglePlay} />
|
|
|
|
</div>
|
2022-10-18 12:36:36 +00:00
|
|
|
)}
|
2022-10-12 18:17:07 +00:00
|
|
|
</div>
|
2022-11-14 12:31:19 +00:00
|
|
|
{isMobileOnly && state.isPlaying && (
|
|
|
|
<div className="mobile-video-progress">
|
2022-10-12 18:17:07 +00:00
|
|
|
<input
|
2022-10-14 14:00:03 +00:00
|
|
|
ref={inputRef}
|
2022-10-12 18:17:07 +00:00
|
|
|
type="range"
|
|
|
|
min="0"
|
|
|
|
max="100"
|
2022-10-14 14:00:03 +00:00
|
|
|
value={state.progress}
|
2022-10-12 18:17:07 +00:00
|
|
|
onChange={(e) => handleVideoProgress(e)}
|
|
|
|
/>
|
2022-11-14 12:31:19 +00:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<StyledVideoControls>
|
|
|
|
<StyledVideoActions>
|
|
|
|
<div className="actions-container">
|
2022-10-31 15:08:29 +00:00
|
|
|
<div
|
2022-11-14 12:31:19 +00:00
|
|
|
className="controller volume-container video-play"
|
|
|
|
onClick={togglePlay}
|
2022-10-31 15:08:29 +00:00
|
|
|
>
|
2022-11-14 12:31:19 +00:00
|
|
|
{!state.isPlaying ? <IconPlay /> : <IconStop />}
|
2022-10-31 15:08:29 +00:00
|
|
|
</div>
|
2022-11-14 12:31:19 +00:00
|
|
|
{!isMobileOnly && (
|
|
|
|
<input
|
|
|
|
ref={inputRef}
|
|
|
|
type="range"
|
|
|
|
min="0"
|
|
|
|
max="100"
|
|
|
|
value={state.progress}
|
|
|
|
onChange={(e) => handleVideoProgress(e)}
|
|
|
|
/>
|
|
|
|
)}
|
2022-10-27 06:58:19 +00:00
|
|
|
|
2022-11-14 12:31:19 +00:00
|
|
|
{!isMobileOnly && (
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
paddingLeft: "10px",
|
|
|
|
paddingRight: "14px",
|
|
|
|
width: "102px",
|
|
|
|
color: "#DDDDDD",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{state.duration}
|
2022-10-27 06:58:19 +00:00
|
|
|
</div>
|
2022-10-18 12:36:36 +00:00
|
|
|
)}
|
2022-11-14 12:31:19 +00:00
|
|
|
{!isMobileOnly && (
|
|
|
|
<div
|
|
|
|
className="controller volume-container"
|
|
|
|
onClick={toggleVolumeSelection}
|
|
|
|
>
|
|
|
|
{!state.isMuted ? <IconSound /> : <IconMuted />}
|
|
|
|
{state.volumeSelection && (
|
|
|
|
<div className="volume-wrapper">
|
|
|
|
<input
|
|
|
|
ref={volumeRef}
|
|
|
|
className="volume-toolbar"
|
|
|
|
type="range"
|
|
|
|
min="0"
|
|
|
|
max="100"
|
|
|
|
value={state.volume}
|
|
|
|
onChange={(e) => handleVolumeUpdate(e)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
|
|
|
|
<div
|
|
|
|
className="controller fullscreen-button"
|
|
|
|
onClick={toggleScreen}
|
|
|
|
>
|
2022-10-31 15:08:29 +00:00
|
|
|
{!state.isFullScreen ? (
|
|
|
|
<IconFullScreen />
|
|
|
|
) : (
|
|
|
|
<IconExitFullScreen />
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div
|
2022-11-14 12:31:19 +00:00
|
|
|
className="controller dropdown-speed"
|
|
|
|
onClick={toggleSpeedSelectionMenu}
|
2022-10-31 15:08:29 +00:00
|
|
|
>
|
2022-11-14 12:31:19 +00:00
|
|
|
<IconSpeed />
|
|
|
|
{state.speedSelection && (
|
|
|
|
<div className="dropdown-content">{SpeedButtonComponent()}</div>
|
|
|
|
)}
|
2022-10-31 15:08:29 +00:00
|
|
|
</div>
|
2022-11-14 12:31:19 +00:00
|
|
|
{!isMobileOnly && (
|
|
|
|
<div
|
|
|
|
className="controller"
|
|
|
|
onClick={() => setIsOpen((open) => !open)}
|
|
|
|
style={{ position: "relative" }}
|
|
|
|
>
|
|
|
|
<MediaContextMenu />
|
|
|
|
{contextMenu}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
2022-10-12 18:17:07 +00:00
|
|
|
</StyledVideoActions>
|
|
|
|
</StyledVideoControls>
|
|
|
|
</StyledVideoPlayer>
|
|
|
|
);
|
|
|
|
}
|