2022-10-12 18:05:33 +00:00
|
|
|
import * as React from "react";
|
|
|
|
import * as ReactDOM from "react-dom";
|
|
|
|
import {
|
|
|
|
StyledViewer,
|
|
|
|
StyledViewerContainer,
|
2022-12-01 14:02:23 +00:00
|
|
|
StyledSwitchToolbar,
|
2022-10-12 18:05:33 +00:00
|
|
|
StyledButtonScroll,
|
2023-01-10 15:58:43 +00:00
|
|
|
StyledMobileDetails,
|
2022-10-12 18:05:33 +00:00
|
|
|
} from "./styled-viewer";
|
|
|
|
import ControlBtn from "./sub-components/control-btn";
|
|
|
|
import Text from "@docspace/components/text";
|
|
|
|
import IconButton from "@docspace/components/icon-button";
|
|
|
|
|
2022-10-31 15:07:20 +00:00
|
|
|
import { isMobileOnly } from "react-device-detect";
|
|
|
|
|
2022-12-01 14:02:23 +00:00
|
|
|
import MediaNextIcon from "../../../public/images/viewer.next.react.svg";
|
|
|
|
import MediaPrevIcon from "../../../public/images/viewer.prew.react.svg";
|
2022-10-12 18:05:33 +00:00
|
|
|
import ViewerPlayer from "./sub-components/viewer-player";
|
|
|
|
|
2022-11-02 15:07:05 +00:00
|
|
|
import MediaContextMenu from "../../../public/images/vertical-dots.react.svg";
|
|
|
|
import ContextMenu from "@docspace/components/context-menu";
|
2023-01-10 15:58:43 +00:00
|
|
|
import BackArrow from "../../../public/images/viewer.media.back.react.svg";
|
2022-11-02 15:07:05 +00:00
|
|
|
|
2022-10-12 18:05:33 +00:00
|
|
|
export const Viewer = (props) => {
|
|
|
|
const {
|
|
|
|
visible,
|
|
|
|
onMaskClick,
|
|
|
|
title,
|
|
|
|
onNextClick,
|
|
|
|
onPrevClick,
|
|
|
|
playlistPos,
|
|
|
|
playlist,
|
|
|
|
isImage,
|
2022-12-05 15:32:16 +00:00
|
|
|
isAudio,
|
|
|
|
audioIcon,
|
2022-10-27 06:56:42 +00:00
|
|
|
contextModel,
|
2022-10-27 11:07:09 +00:00
|
|
|
generateContextMenu,
|
2023-01-09 15:22:04 +00:00
|
|
|
headerIcon,
|
|
|
|
onSetSelectionFile,
|
2022-10-12 18:05:33 +00:00
|
|
|
} = props;
|
|
|
|
|
2022-11-25 14:07:30 +00:00
|
|
|
let timer;
|
|
|
|
|
2022-10-12 18:05:33 +00:00
|
|
|
const defaultContainer = React.useRef(
|
|
|
|
typeof document !== "undefined" ? document.createElement("div") : null
|
|
|
|
);
|
|
|
|
const [container, setContainer] = React.useState(props.container);
|
2022-11-25 14:07:30 +00:00
|
|
|
const [panelVisible, setPanelVisible] = React.useState(true);
|
2023-01-17 07:45:05 +00:00
|
|
|
const [isOpenContextMenu, setIsOpenContextMenu] = React.useState(false);
|
2023-01-16 13:18:18 +00:00
|
|
|
const [isPlay, setIsPlay] = React.useState(null);
|
|
|
|
const [globalTimer, setGlobalTimer] = React.useState(null);
|
2022-10-12 18:05:33 +00:00
|
|
|
const [init, setInit] = React.useState(false);
|
|
|
|
|
|
|
|
const detailsContainerRef = React.useRef(null);
|
2023-01-16 13:18:18 +00:00
|
|
|
const videoControls = React.useRef(null);
|
2022-10-12 18:05:33 +00:00
|
|
|
const videoElement = React.useRef(null);
|
2022-11-02 15:07:05 +00:00
|
|
|
const cm = React.useRef(null);
|
2022-10-12 18:05:33 +00:00
|
|
|
|
2022-10-14 13:59:08 +00:00
|
|
|
const [isFullscreen, setIsFullScreen] = React.useState(false);
|
2022-10-12 18:05:33 +00:00
|
|
|
React.useEffect(() => {
|
|
|
|
document.body.appendChild(defaultContainer.current);
|
|
|
|
}, []);
|
|
|
|
|
2022-11-25 14:07:30 +00:00
|
|
|
React.useEffect(() => {
|
2023-01-17 10:55:10 +00:00
|
|
|
if ((!isPlay || isOpenContextMenu) && (!isImage || isOpenContextMenu))
|
|
|
|
return clearTimeout(timer);
|
2023-01-12 16:31:40 +00:00
|
|
|
document.addEventListener("touchstart", onTouch);
|
|
|
|
if (!isMobileOnly) {
|
|
|
|
document.addEventListener("mousemove", resetTimer);
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
document.removeEventListener("mousemove", resetTimer);
|
|
|
|
clearTimeout(timer);
|
|
|
|
setPanelVisible(true);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return () => document.removeEventListener("touchstart", onTouch);
|
2023-01-17 07:45:05 +00:00
|
|
|
}, [isPlay, isOpenContextMenu]);
|
2022-11-25 14:07:30 +00:00
|
|
|
|
|
|
|
function resetTimer() {
|
|
|
|
setPanelVisible(true);
|
|
|
|
clearTimeout(timer);
|
|
|
|
timer = setTimeout(() => setPanelVisible(false), 5000);
|
|
|
|
}
|
|
|
|
|
2023-01-12 16:31:40 +00:00
|
|
|
const onTouch = (e) => {
|
|
|
|
if (e.target === videoElement.current) {
|
|
|
|
setPanelVisible((visible) => !visible);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-12 18:05:33 +00:00
|
|
|
React.useEffect(() => {
|
|
|
|
if (props.visible && !init) {
|
|
|
|
setInit(true);
|
|
|
|
}
|
|
|
|
}, [props.visible, init]);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (props.container) {
|
|
|
|
setContainer(props.container);
|
|
|
|
} else {
|
|
|
|
setContainer(defaultContainer.current);
|
|
|
|
}
|
|
|
|
}, [props.container]);
|
|
|
|
|
|
|
|
if (!init) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-11-02 15:07:05 +00:00
|
|
|
const onContextMenu = (e) => {
|
2023-01-17 07:45:05 +00:00
|
|
|
setIsOpenContextMenu((open) => !open);
|
2023-01-09 15:22:04 +00:00
|
|
|
onSetSelectionFile();
|
2022-11-02 15:07:05 +00:00
|
|
|
cm.current.show(e);
|
|
|
|
};
|
|
|
|
|
2023-01-09 15:22:04 +00:00
|
|
|
const contextMenuHeader = {
|
|
|
|
icon: headerIcon,
|
|
|
|
title: title,
|
|
|
|
};
|
|
|
|
|
2022-11-02 15:07:05 +00:00
|
|
|
const mobileDetails = (
|
2023-01-10 15:58:43 +00:00
|
|
|
<StyledMobileDetails>
|
|
|
|
<BackArrow className="mobile-close" onClick={onMaskClick} />
|
|
|
|
<Text fontSize="14px" color={"#fff"} className="title">
|
2022-11-02 15:07:05 +00:00
|
|
|
{title}
|
|
|
|
</Text>
|
2023-01-12 16:31:40 +00:00
|
|
|
{!props.isPreviewFile && (
|
|
|
|
<div className="details-context">
|
|
|
|
<MediaContextMenu
|
|
|
|
className="mobile-context"
|
|
|
|
onClick={onContextMenu}
|
|
|
|
/>
|
|
|
|
<ContextMenu
|
|
|
|
getContextModel={contextModel}
|
|
|
|
ref={cm}
|
|
|
|
withBackdrop={true}
|
|
|
|
header={contextMenuHeader}
|
2023-01-17 07:45:05 +00:00
|
|
|
onHide={() => setIsOpenContextMenu(false)}
|
2023-01-12 16:31:40 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
2023-01-10 15:58:43 +00:00
|
|
|
</StyledMobileDetails>
|
2022-11-02 15:07:05 +00:00
|
|
|
);
|
2022-10-12 18:05:33 +00:00
|
|
|
|
2023-01-17 10:32:58 +00:00
|
|
|
const displayUI = (isMobileOnly && isAudio) || panelVisible;
|
2022-11-25 14:07:30 +00:00
|
|
|
|
2022-10-12 18:05:33 +00:00
|
|
|
const viewerPortal = ReactDOM.createPortal(
|
2022-11-02 15:07:05 +00:00
|
|
|
<StyledViewer
|
|
|
|
{...props}
|
2022-12-29 15:56:17 +00:00
|
|
|
displayUI={displayUI}
|
2022-11-02 15:07:05 +00:00
|
|
|
mobileDetails={mobileDetails}
|
2023-01-17 10:55:10 +00:00
|
|
|
setIsOpenContextMenu={setIsOpenContextMenu}
|
2022-11-14 14:54:31 +00:00
|
|
|
container={container}
|
2022-11-25 14:07:30 +00:00
|
|
|
onMaskClick={onMaskClick}
|
2023-01-13 13:13:42 +00:00
|
|
|
setPanelVisible={setPanelVisible}
|
2022-11-02 15:07:05 +00:00
|
|
|
generateContextMenu={generateContextMenu}
|
|
|
|
/>,
|
2022-10-12 18:05:33 +00:00
|
|
|
container
|
|
|
|
);
|
|
|
|
|
|
|
|
const videoPortal = ReactDOM.createPortal(
|
|
|
|
<ViewerPlayer
|
2022-12-27 10:05:33 +00:00
|
|
|
{...props}
|
2022-11-14 12:29:35 +00:00
|
|
|
onNextClick={onNextClick}
|
|
|
|
onPrevClick={onPrevClick}
|
2022-12-05 15:32:16 +00:00
|
|
|
isAudio={isAudio}
|
|
|
|
audioIcon={audioIcon}
|
2022-10-31 15:07:20 +00:00
|
|
|
contextModel={contextModel}
|
2022-11-02 15:07:05 +00:00
|
|
|
mobileDetails={mobileDetails}
|
2022-11-25 14:07:30 +00:00
|
|
|
displayUI={displayUI}
|
2023-01-17 07:45:05 +00:00
|
|
|
isOpenContextMenu={isOpenContextMenu}
|
2023-01-16 13:18:18 +00:00
|
|
|
globalTimer={globalTimer}
|
|
|
|
setGlobalTimer={setGlobalTimer}
|
|
|
|
videoControls={videoControls}
|
2023-01-16 09:07:12 +00:00
|
|
|
onTouch={onTouch}
|
2022-10-31 15:07:20 +00:00
|
|
|
title={title}
|
2023-01-16 13:18:18 +00:00
|
|
|
setIsPlay={setIsPlay}
|
2023-01-17 07:45:05 +00:00
|
|
|
setIsOpenContextMenu={setIsOpenContextMenu}
|
2023-01-16 13:18:18 +00:00
|
|
|
isPlay={isPlay}
|
2022-10-31 15:07:20 +00:00
|
|
|
onMaskClick={onMaskClick}
|
2023-01-12 16:31:40 +00:00
|
|
|
setPanelVisible={setPanelVisible}
|
2022-10-27 11:07:09 +00:00
|
|
|
generateContextMenu={generateContextMenu}
|
2022-10-14 13:59:08 +00:00
|
|
|
setIsFullScreen={setIsFullScreen}
|
|
|
|
videoRef={videoElement}
|
2022-10-12 18:05:33 +00:00
|
|
|
video={playlist[playlistPos]}
|
2022-10-14 13:59:08 +00:00
|
|
|
activeIndex={playlistPos}
|
2022-10-12 18:05:33 +00:00
|
|
|
/>,
|
|
|
|
container
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<StyledViewerContainer visible={visible}>
|
2022-11-25 14:07:30 +00:00
|
|
|
{!isFullscreen && !isMobileOnly && displayUI && (
|
2022-10-14 13:59:08 +00:00
|
|
|
<div>
|
|
|
|
<div className="details" ref={detailsContainerRef}>
|
|
|
|
<Text isBold fontSize="14px" className="title">
|
|
|
|
{title}
|
|
|
|
</Text>
|
|
|
|
<ControlBtn
|
|
|
|
onClick={onMaskClick && onMaskClick}
|
|
|
|
className="mediaPlayerClose"
|
|
|
|
>
|
|
|
|
<IconButton
|
2022-10-27 14:12:15 +00:00
|
|
|
color={"#fff"}
|
2023-01-10 15:58:43 +00:00
|
|
|
iconName="/static/images/viewer.media.close.svg"
|
|
|
|
size={28}
|
2022-10-14 13:59:08 +00:00
|
|
|
isClickable
|
|
|
|
/>
|
|
|
|
</ControlBtn>
|
|
|
|
</div>
|
2022-10-12 18:05:33 +00:00
|
|
|
</div>
|
2022-10-14 13:59:08 +00:00
|
|
|
)}
|
|
|
|
|
2022-11-25 14:07:30 +00:00
|
|
|
{playlist.length > 1 && !isFullscreen && displayUI && (
|
2022-10-12 18:05:33 +00:00
|
|
|
<>
|
2022-11-16 14:53:57 +00:00
|
|
|
{playlistPos !== 0 && (
|
2022-12-01 14:02:23 +00:00
|
|
|
<StyledSwitchToolbar left onClick={onPrevClick}>
|
2022-11-16 14:53:57 +00:00
|
|
|
<StyledButtonScroll orientation="left">
|
|
|
|
<MediaPrevIcon />
|
|
|
|
</StyledButtonScroll>
|
2022-12-01 14:02:23 +00:00
|
|
|
</StyledSwitchToolbar>
|
2022-11-16 14:53:57 +00:00
|
|
|
)}
|
2022-10-12 18:05:33 +00:00
|
|
|
{playlistPos < playlist.length - 1 && (
|
|
|
|
<>
|
2022-12-01 14:02:23 +00:00
|
|
|
<StyledSwitchToolbar onClick={onNextClick}>
|
2022-10-12 18:05:33 +00:00
|
|
|
<StyledButtonScroll orientation="right">
|
|
|
|
<MediaNextIcon />
|
|
|
|
</StyledButtonScroll>
|
2022-12-01 14:02:23 +00:00
|
|
|
</StyledSwitchToolbar>
|
2022-10-12 18:05:33 +00:00
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
|
2022-11-14 14:54:31 +00:00
|
|
|
{isImage ? <>{viewerPortal}</> : <>{videoPortal}</>}
|
2022-10-12 18:05:33 +00:00
|
|
|
</StyledViewerContainer>
|
|
|
|
);
|
|
|
|
};
|