wrolpi/app/src/components/FilePreview.js

179 lines
6.2 KiB
JavaScript
Raw Normal View History

2023-02-15 20:58:07 -07:00
import React from "react";
2023-02-15 17:40:57 -07:00
import _ from "lodash";
2023-02-22 11:48:25 -07:00
import {
Button as SButton,
Header as SHeader,
Image,
Modal,
ModalActions,
ModalContent,
ModalHeader
} from "semantic-ui-react";
2023-02-15 17:40:57 -07:00
function getMediaPathURL(path) {
return `/media/${encodeURIComponent(path['path'])}`;
}
function getDownloadPathURL(path) {
return `/download/${encodeURIComponent(path['path'])}`;
}
function getEpubViewerURL(path) {
2023-02-15 20:58:07 -07:00
return `/epub.html?url=download/${encodeURIComponent(path['path'])}`;
2023-02-15 17:40:57 -07:00
}
function getIframeModal(path) {
const url = getMediaPathURL(path);
return <ModalContent>
<div className='full-height'>
<iframe title='textModal' src={url}
style={{
height: '100%', width: '100%', border: 'none', position: 'absolute', top: 0,
}}/>
</div>
</ModalContent>
}
function getImageModal(path) {
const url = getMediaPathURL(path);
const name = path['path'].replace(/^.*[\\\/]/, '');
2023-02-22 11:48:25 -07:00
return <React.Fragment>
<ModalHeader>
{name}
2023-02-22 11:48:25 -07:00
</ModalHeader>
<ModalContent>
<a href={url}>
<Image src={url}/>
</a>
</ModalContent>
</React.Fragment>
2023-02-15 17:40:57 -07:00
}
function getEpubModal(path) {
const downloadURL = getDownloadPathURL(path);
const viewerUrl = `/epub.html?url=${downloadURL}`;
return <ModalContent>
<div className='full-height'>
<iframe title='textModal' src={viewerUrl}
style={{
height: '100%', width: '100%', border: 'none', position: 'absolute', top: 0,
}}/>
</div>
</ModalContent>
}
function getVideoModal(path) {
const url = getMediaPathURL(path);
const name = path['path'].replace(/^.*[\\\/]/, '');
2023-02-22 11:48:25 -07:00
const type = path['mimetype'] ? path['mimetype'] : 'video/mp4';
return <React.Fragment>
<ModalHeader>
{name}
2023-02-22 11:48:25 -07:00
</ModalHeader>
<ModalContent>
<SHeader as='h5'>{path['path']}</SHeader>
<video controls
autoPlay={true}
id="player"
playsInline={true}
style={{maxWidth: '100%'}}
>
<source src={url} type={type}/>
</video>
</ModalContent>
</React.Fragment>
}
function getAudioModal(path) {
const url = getMediaPathURL(path);
const name = path['path'].replace(/^.*[\\\/]/, '');
2023-02-22 17:58:36 -07:00
// Some audio files may not have the correct mimetype. Trust the suffix identifies an audio file.
const type = path['mimetype'] !== 'application/octet-stream' ? path['mimetype'] : 'audio/mpeg';
2023-02-22 11:48:25 -07:00
return <React.Fragment>
<ModalHeader>
{name}
2023-02-22 11:48:25 -07:00
</ModalHeader><ModalContent>
<audio controls
2023-02-15 17:40:57 -07:00
autoPlay={true}
id="player"
playsInline={true}
2023-02-22 11:48:25 -07:00
style={{width: '90%', maxWidth: '95%'}}
2023-02-15 17:40:57 -07:00
>
2023-02-22 11:48:25 -07:00
<source src={url} type={type}/>
</audio>
2023-02-15 17:40:57 -07:00
</ModalContent>
2023-02-22 11:48:25 -07:00
</React.Fragment>
2023-02-15 17:40:57 -07:00
}
2023-02-15 20:58:07 -07:00
export const FilePreviewContext = React.createContext({
previewFile: null, setPreviewFile: null, previewModal: null, setPreviewModal: null,
2023-02-15 20:58:07 -07:00
});
2023-02-15 21:20:23 -07:00
const MAXIMUM_TEXT_SIZE = 5_000_000;
2023-02-15 20:58:07 -07:00
export function FilePreviewWrapper({children}) {
const [previewFile, setPreviewFile] = React.useState(null);
2023-02-15 20:58:07 -07:00
const [previewModal, setPreviewModal] = React.useState(null);
const value = {
previewFile, setPreviewFile, previewModal, setPreviewModal,
2023-02-15 20:58:07 -07:00
};
2023-02-15 17:40:57 -07:00
function setModalContent(content, url, downloadURL) {
2023-02-15 20:58:07 -07:00
setPreviewModal(<Modal closeIcon
size='fullscreen'
open={true}
onClose={() => setPreviewModal(null)}
2023-02-15 17:40:57 -07:00
>
{content}
<ModalActions>
{downloadURL &&
<SButton color='yellow' onClick={() => window.open(downloadURL)} floated='left'>Download</SButton>}
<SButton color='blue' onClick={() => window.open(url)}>Open</SButton>
<SButton onClick={() => setPreviewFile(null)}>Close</SButton>
2023-02-15 17:40:57 -07:00
</ModalActions>
</Modal>);
}
2023-02-15 20:58:07 -07:00
React.useEffect(() => {
setPreviewModal(null);
if (previewFile && !_.isObject(previewFile)) {
console.error(`Unknown previewFile type: ${typeof previewFile}`);
return;
}
if (previewFile && !_.isEmpty(previewFile)) {
const {mimetype, size, path} = previewFile;
const lowerPath = path.toLowerCase();
console.debug(`useFilePreview path=${previewFile['path']} mimetype=${mimetype}`);
const url = getMediaPathURL(previewFile);
const downloadURL = getDownloadPathURL(previewFile);
2023-02-15 21:20:23 -07:00
if (mimetype.startsWith('text/') && size > MAXIMUM_TEXT_SIZE) {
2023-02-15 17:40:57 -07:00
// Large text files should be downloaded.
window.open(downloadURL);
} else if (mimetype.startsWith('text/') || mimetype.startsWith('application/json')) {
setModalContent(getIframeModal(previewFile), url, downloadURL);
2023-02-15 17:40:57 -07:00
} else if (mimetype.startsWith('video/')) {
setModalContent(getVideoModal(previewFile), url, downloadURL);
2023-02-22 11:48:25 -07:00
} else if (mimetype.startsWith('audio/')) {
setModalContent(getAudioModal(previewFile), url, downloadURL);
2023-02-15 17:40:57 -07:00
} else if (mimetype.startsWith('application/epub')) {
const viewerURL = getEpubViewerURL(previewFile);
setModalContent(getEpubModal(previewFile), viewerURL, downloadURL);
2023-02-15 17:40:57 -07:00
} else if (mimetype.startsWith('image/')) {
setModalContent(getImageModal(previewFile), url);
} else if (mimetype.startsWith('application/octet-stream') && lowerPath.endsWith('.mp3')) {
setModalContent(getAudioModal(previewFile), url, downloadURL);
2023-02-15 17:40:57 -07:00
} else {
// No special handler for this file type, just open it.
window.open(downloadURL);
}
}
}, [previewFile]);
2023-02-15 17:40:57 -07:00
2023-02-15 20:58:07 -07:00
return <FilePreviewContext.Provider value={value}>
{children}
{previewModal}
</FilePreviewContext.Provider>
2023-02-15 17:40:57 -07:00
}