2020-04-19 20:06:17 +00:00
|
|
|
import React from "react";
|
|
|
|
import PropTypes from "prop-types";
|
2020-04-22 17:44:09 +00:00
|
|
|
import styled from "styled-components";
|
|
|
|
import { Icons } from "asc-web-components";
|
2020-04-19 20:06:17 +00:00
|
|
|
|
|
|
|
import ImageViewer from "./sub-components/image-viewer"
|
|
|
|
import VideoViewer from "./sub-components/video-viewer"
|
2020-04-24 18:53:30 +00:00
|
|
|
import MediaScrollButton from "./sub-components/scroll-button"
|
|
|
|
import ControlBtn from "./sub-components/control-btn"
|
2020-04-19 20:06:17 +00:00
|
|
|
|
2020-04-22 17:44:09 +00:00
|
|
|
const StyledVideoViewer = styled(VideoViewer)`
|
|
|
|
z-index: 4001;
|
|
|
|
`
|
|
|
|
const StyledMediaViewer = styled.div`
|
|
|
|
|
|
|
|
color: #d1d1d1;
|
2020-04-29 14:11:01 +00:00
|
|
|
display: ${props => props.visible ? "block" : "none"};
|
|
|
|
|
2020-04-22 17:44:09 +00:00
|
|
|
.videoViewerOverlay{
|
|
|
|
position: fixed;
|
|
|
|
z-index: 4000;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
background: black;
|
|
|
|
opacity: 0.5;
|
|
|
|
}
|
|
|
|
.mediaViewerToolbox{
|
|
|
|
z-index: 4001;
|
|
|
|
padding-top: 14px;
|
|
|
|
padding-bottom: 14px;
|
|
|
|
height: 20px;
|
|
|
|
width: 100%;
|
|
|
|
background-color: rgba(11,11,11,0.7);
|
|
|
|
position: fixed;
|
|
|
|
bottom: 0;
|
|
|
|
left: 0;
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
span{
|
|
|
|
position: absolute;
|
|
|
|
right: 0;
|
|
|
|
bottom: 5px;
|
|
|
|
margin-right: 10px;
|
|
|
|
z-index: 4005;
|
2020-05-05 13:15:33 +00:00
|
|
|
|
|
|
|
.deleteBtnContainer{
|
|
|
|
display: block;
|
|
|
|
width: 20px;
|
|
|
|
margin: 3px 10px;
|
|
|
|
line-height: 19px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.downloadBtnContainer{
|
|
|
|
display: block;
|
|
|
|
width: 20px;
|
|
|
|
margin: 3px 10px;
|
|
|
|
line-height: 19px;
|
|
|
|
}
|
2020-04-22 17:44:09 +00:00
|
|
|
}
|
|
|
|
.details{
|
|
|
|
z-index: 4001;
|
|
|
|
font-size: 14px;
|
|
|
|
font-weight: bold;
|
|
|
|
text-align: center;
|
|
|
|
white-space: nowrap;
|
|
|
|
padding-top: 14px;
|
|
|
|
padding-bottom: 14px;
|
|
|
|
height: 20px;
|
|
|
|
width: 100%;
|
|
|
|
background: rgba(17,17,17,0.867);
|
|
|
|
position: fixed;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.mediaPlayerClose{
|
|
|
|
position: fixed;
|
|
|
|
top: 4px;
|
|
|
|
right: 10px;
|
|
|
|
height: 30px;
|
|
|
|
}
|
|
|
|
|
|
|
|
`;
|
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
var audio = 1;
|
|
|
|
var video = 2;
|
2020-04-22 17:44:09 +00:00
|
|
|
|
2020-04-19 20:06:17 +00:00
|
|
|
class MediaViewer extends React.Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.state = {
|
2020-04-29 14:11:01 +00:00
|
|
|
visible: this.props.visible,
|
2020-04-23 21:44:47 +00:00
|
|
|
allowConvert: true,
|
|
|
|
playlist: this.props.playlist,
|
|
|
|
playlistPos: 0,
|
|
|
|
};
|
2020-05-05 13:15:33 +00:00
|
|
|
|
|
|
|
this.detailsContainer = React.createRef();
|
|
|
|
this.viewerToolbox = React.createRef();
|
2020-04-19 20:06:17 +00:00
|
|
|
}
|
2020-04-29 14:11:01 +00:00
|
|
|
|
|
|
|
componentDidUpdate(prevProps) {
|
|
|
|
if (this.props.visible !== prevProps.visible) {
|
2020-04-30 08:37:16 +00:00
|
|
|
this.setState(
|
|
|
|
{
|
|
|
|
visible: this.props.visible
|
|
|
|
}
|
|
|
|
);
|
2020-04-29 14:11:01 +00:00
|
|
|
}
|
2020-05-05 13:15:33 +00:00
|
|
|
|
2020-04-30 08:37:16 +00:00
|
|
|
}
|
2020-04-23 21:44:47 +00:00
|
|
|
mapSupplied = {
|
|
|
|
".aac": { supply: "m4a", type: audio },
|
|
|
|
".flac": { supply: "mp3", type: audio },
|
|
|
|
".m4a": { supply: "m4a", type: audio },
|
|
|
|
".mp3": { supply: "mp3", type: audio },
|
|
|
|
".oga": { supply: "oga", type: audio },
|
|
|
|
".ogg": { supply: "oga", type: audio },
|
|
|
|
".wav": { supply: "wav", type: audio },
|
|
|
|
|
|
|
|
".f4v": { supply: "m4v", type: video },
|
|
|
|
".m4v": { supply: "m4v", type: video },
|
|
|
|
".mov": { supply: "m4v", type: video },
|
|
|
|
".mp4": { supply: "m4v", type: video },
|
|
|
|
".ogv": { supply: "ogv", type: video },
|
|
|
|
".webm": { supply: "webmv", type: video },
|
|
|
|
".wmv": { supply: "m4v", type: video, convertable: true },
|
|
|
|
".avi": { supply: "m4v", type: video, convertable: true },
|
|
|
|
".mpeg": { supply: "m4v", type: video, convertable: true },
|
|
|
|
".mpg": { supply: "m4v", type: video, convertable: true }
|
|
|
|
};
|
2020-04-24 18:53:30 +00:00
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
canImageView = function (ext) {
|
|
|
|
return this.props.extsImagePreviewed.indexOf(ext) != -1;
|
|
|
|
};
|
|
|
|
canPlay = (fileTitle, allowConvert) => {
|
|
|
|
|
|
|
|
var ext = fileTitle[0] === "." ? fileTitle : this.getFileExtension(fileTitle);
|
|
|
|
|
|
|
|
var supply = this.mapSupplied[ext];
|
|
|
|
|
|
|
|
var canConv = allowConvert || this.props.allowConvert;
|
|
|
|
|
2020-04-29 14:11:01 +00:00
|
|
|
return !!supply && this.props.extsMediaPreviewed.indexOf(ext) != -1
|
2020-04-23 21:44:47 +00:00
|
|
|
&& (!supply.convertable || canConv);
|
|
|
|
};
|
2020-04-24 18:53:30 +00:00
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
getFileExtension = (fileTitle) => {
|
|
|
|
if (typeof fileTitle == "undefined" || fileTitle == null) {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
fileTitle = fileTitle.trim();
|
|
|
|
var posExt = fileTitle.lastIndexOf(".");
|
|
|
|
return 0 <= posExt ? fileTitle.substring(posExt).trim().toLowerCase() : "";
|
|
|
|
};
|
|
|
|
|
|
|
|
prevMedia = () => {
|
2020-04-29 14:11:01 +00:00
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
let currentPlaylistPos = this.state.playlistPos;
|
|
|
|
currentPlaylistPos--;
|
|
|
|
if (currentPlaylistPos < 0)
|
2020-04-29 14:11:01 +00:00
|
|
|
currentPlaylistPos = this.state.playlist.length - 1;
|
2020-04-23 21:44:47 +00:00
|
|
|
|
|
|
|
this.setState({
|
|
|
|
playlistPos: currentPlaylistPos
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
2020-04-24 18:53:30 +00:00
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
nextMedia = () => {
|
|
|
|
|
|
|
|
let currentPlaylistPos = this.state.playlistPos;
|
|
|
|
currentPlaylistPos = (currentPlaylistPos + 1) % this.state.playlist.length;
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
playlistPos: currentPlaylistPos
|
|
|
|
});
|
|
|
|
};
|
2020-05-05 13:15:33 +00:00
|
|
|
getOffset = () => {
|
|
|
|
if (this.detailsContainer.current && this.viewerToolbox.current) {
|
|
|
|
return this.detailsContainer.current.offsetHeight + this.viewerToolbox.current.offsetHeight;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2020-04-29 14:11:01 +00:00
|
|
|
render() {
|
2020-04-24 18:53:30 +00:00
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
let currentPlaylistPos = this.state.playlistPos;
|
|
|
|
let fileTitle = this.state.playlist[currentPlaylistPos].title;
|
|
|
|
let url = this.state.playlist[currentPlaylistPos].src;
|
|
|
|
let isImage = false;
|
2020-04-29 14:11:01 +00:00
|
|
|
let isVideo = false;
|
|
|
|
let canOpen = true;
|
2020-04-24 12:28:17 +00:00
|
|
|
|
2020-04-23 21:44:47 +00:00
|
|
|
var ext = this.getFileExtension(fileTitle) ? this.getFileExtension(fileTitle) : this.getFileExtension(url);
|
|
|
|
|
|
|
|
if (!this.canPlay(ext) && !this.canImageView(ext)) {
|
2020-04-29 14:11:01 +00:00
|
|
|
canOpen = false;
|
|
|
|
this.props.onError && this.props.onError();
|
2020-04-23 21:44:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (this.canImageView(ext)) {
|
|
|
|
isImage = true;
|
|
|
|
} else {
|
2020-04-29 14:11:01 +00:00
|
|
|
isImage = false;
|
2020-04-24 12:28:17 +00:00
|
|
|
isVideo = this.mapSupplied[ext] ? this.mapSupplied[ext].type == video : false;
|
2020-04-23 21:44:47 +00:00
|
|
|
}
|
2020-04-30 08:37:16 +00:00
|
|
|
|
2020-04-29 14:11:01 +00:00
|
|
|
return (
|
|
|
|
<StyledMediaViewer visible={this.state.visible}>
|
2020-04-23 21:44:47 +00:00
|
|
|
|
2020-04-29 14:11:01 +00:00
|
|
|
<div className="videoViewerOverlay"></div>
|
|
|
|
<MediaScrollButton orientation="right" onClick={this.prevMedia} />
|
|
|
|
<MediaScrollButton orientation="left" onClick={this.nextMedia} />
|
2020-04-22 17:44:09 +00:00
|
|
|
<div>
|
2020-05-05 13:15:33 +00:00
|
|
|
<div className="details" ref={this.detailsContainer}>
|
2020-04-29 14:11:01 +00:00
|
|
|
<div className="title">{fileTitle}</div>
|
2020-04-30 08:37:16 +00:00
|
|
|
<ControlBtn onClick={this.props.onClose && (() => { this.props.onClose() })} className="mediaPlayerClose">
|
2020-04-22 17:44:09 +00:00
|
|
|
<Icons.CrossIcon size="medium" isfill={true} color="#fff" />
|
2020-04-24 18:53:30 +00:00
|
|
|
</ControlBtn>
|
2020-04-22 17:44:09 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2020-04-29 14:11:01 +00:00
|
|
|
{canOpen &&
|
|
|
|
(
|
|
|
|
isImage ?
|
|
|
|
<ImageViewer
|
|
|
|
visible={this.state.visible}
|
|
|
|
onClose={() => { this.setState({ visible: false }); }}
|
|
|
|
images={[
|
|
|
|
{ src: url, alt: '' }
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
:
|
2020-05-05 13:15:33 +00:00
|
|
|
<StyledVideoViewer url={url} playing={this.state.visible} isVideo={isVideo} getOffset={this.getOffset} />
|
2020-04-29 14:11:01 +00:00
|
|
|
)
|
2020-04-23 21:44:47 +00:00
|
|
|
}
|
2020-05-05 13:15:33 +00:00
|
|
|
<div className="mediaViewerToolbox" ref={this.viewerToolbox}></div>
|
2020-04-22 17:44:09 +00:00
|
|
|
<span>
|
2020-05-05 13:15:33 +00:00
|
|
|
{
|
|
|
|
this.props.canDelete(currentPlaylistPos) &&
|
|
|
|
<ControlBtn onClick={this.props.onDelete && (() => { this.props.onDelete(this.state.playlistPos) })}>
|
|
|
|
<div className="deleteBtnContainer">
|
|
|
|
<Icons.MediaDeleteIcon size="scale" />
|
|
|
|
</div>
|
|
|
|
</ControlBtn>
|
|
|
|
}
|
2020-04-19 20:06:17 +00:00
|
|
|
|
2020-04-30 08:37:16 +00:00
|
|
|
<ControlBtn onClick={this.props.onDownload && (() => { this.props.onDownload(this.state.playlistPos) })}>
|
2020-05-05 13:15:33 +00:00
|
|
|
<div className="downloadBtnContainer">
|
|
|
|
<Icons.MediaDownloadIcon size="scale" />
|
|
|
|
</div>
|
2020-04-24 18:53:30 +00:00
|
|
|
</ControlBtn>
|
2020-04-22 17:44:09 +00:00
|
|
|
</span>
|
|
|
|
</StyledMediaViewer>
|
2020-04-19 20:06:17 +00:00
|
|
|
)
|
2020-04-29 14:11:01 +00:00
|
|
|
}
|
2020-04-19 20:06:17 +00:00
|
|
|
}
|
|
|
|
|
2020-04-29 14:11:01 +00:00
|
|
|
MediaViewer.propTypes = {
|
|
|
|
allowConvert: PropTypes.bool,
|
|
|
|
visible: PropTypes.bool,
|
|
|
|
playlist: PropTypes.arrayOf(PropTypes.object),
|
|
|
|
extsImagePreviewed: PropTypes.arrayOf(PropTypes.string),
|
|
|
|
extsMediaPreviewed: PropTypes.arrayOf(PropTypes.string),
|
|
|
|
onError: PropTypes.func,
|
|
|
|
canDelete: PropTypes.func,
|
|
|
|
onDelete: PropTypes.func,
|
|
|
|
onDownload: PropTypes.func,
|
|
|
|
onClose: PropTypes.func
|
|
|
|
}
|
2020-04-19 20:06:17 +00:00
|
|
|
|
2020-04-29 14:11:01 +00:00
|
|
|
MediaViewer.defaultProps = {
|
|
|
|
allowConvert: true,
|
|
|
|
canDelete: () => { return true }
|
|
|
|
}
|
2020-04-19 20:06:17 +00:00
|
|
|
|
|
|
|
export default MediaViewer;
|