improve and optimize renderFile method (fileSource)
This commit is contained in:
parent
2109685d5a
commit
2c8f11750a
7 changed files with 60 additions and 70 deletions
|
@ -9,33 +9,36 @@ import DocxViewer from 'component/viewers/docxViewer';
|
|||
type Props = {
|
||||
mediaType: string,
|
||||
source: {
|
||||
filePath: string,
|
||||
fileName: string,
|
||||
fileType: string,
|
||||
downloadPath: string,
|
||||
stream: opts => void,
|
||||
blob: callback => void,
|
||||
},
|
||||
currentTheme: string,
|
||||
};
|
||||
|
||||
class FileRender extends React.PureComponent<Props> {
|
||||
renderViewer() {
|
||||
const { source, mediaType, currentTheme: theme } = this.props;
|
||||
const viewerProps = { source, theme };
|
||||
const { source, mediaType, currentTheme } = this.props;
|
||||
|
||||
// Extract relevant data to render file
|
||||
const { blob, stream, fileName, fileType, contentType, downloadPath } = source;
|
||||
|
||||
// Supported mediaTypes
|
||||
const mediaTypes = {
|
||||
'3D-file': <ThreeViewer {...viewerProps} />,
|
||||
document: <DocumentViewer {...viewerProps} />,
|
||||
'3D-file': <ThreeViewer source={{ fileType, downloadPath }} theme={currentTheme} />,
|
||||
document: <DocumentViewer source={{ stream, fileType, contentType }} theme={currentTheme} />,
|
||||
// Add routes to viewer...
|
||||
};
|
||||
|
||||
// Supported fileType
|
||||
const fileTypes = {
|
||||
pdf: <PdfViewer {...viewerProps} />,
|
||||
docx: <DocxViewer {...viewerProps} />,
|
||||
pdf: <PdfViewer source={downloadPath} />,
|
||||
docx: <DocxViewer source={downloadPath} />,
|
||||
// Add routes to viewer...
|
||||
};
|
||||
|
||||
const { fileType } = source;
|
||||
const viewer = mediaType && source && (fileTypes[fileType] || mediaTypes[mediaType]);
|
||||
const unsupportedMessage = __("Sorry, looks like we can't preview this file.");
|
||||
const unsupported = <LoadingScreen status={unsupportedMessage} spinner={false} />;
|
||||
|
|
|
@ -9,7 +9,7 @@ import FileRender from 'component/fileRender';
|
|||
import Thumbnail from 'component/common/thumbnail';
|
||||
import LoadingScreen from 'component/common/loading-screen';
|
||||
|
||||
class VideoPlayer extends React.PureComponent {
|
||||
class MediaPlayer extends React.PureComponent {
|
||||
static MP3_CONTENT_TYPES = ['audio/mpeg3', 'audio/mpeg'];
|
||||
static FILE_MEDIA_TYPES = ['e-book', 'comic-book', 'document', '3D-file'];
|
||||
|
||||
|
@ -54,7 +54,7 @@ class VideoPlayer extends React.PureComponent {
|
|||
};
|
||||
|
||||
// use renderAudio override for mp3
|
||||
if (VideoPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
|
||||
if (MediaPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
|
||||
this.renderAudio(container, null, false);
|
||||
}
|
||||
// Render custom viewer: FileRender
|
||||
|
@ -105,7 +105,7 @@ class VideoPlayer extends React.PureComponent {
|
|||
if (this.playableType() && !startedPlaying && downloadCompleted) {
|
||||
const container = this.media.children[0];
|
||||
|
||||
if (VideoPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
|
||||
if (MediaPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
|
||||
this.renderAudio(this.media, true);
|
||||
} else {
|
||||
player.render(this.file(), container, {
|
||||
|
@ -183,30 +183,30 @@ class VideoPlayer extends React.PureComponent {
|
|||
// This files are supported using a custom viewer
|
||||
const { mediaType } = this.props;
|
||||
|
||||
return VideoPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1;
|
||||
return MediaPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1;
|
||||
}
|
||||
|
||||
renderFile() {
|
||||
// This is what render-media does with unplayable files
|
||||
const { fileName, downloadPath, contentType, mediaType } = this.props;
|
||||
|
||||
toBlobURL(fs.createReadStream(downloadPath), contentType, (err, url) => {
|
||||
if (err) {
|
||||
this.setState({ unsupported: true });
|
||||
return false;
|
||||
}
|
||||
// File to render
|
||||
const fileSource = {
|
||||
fileName,
|
||||
contentType,
|
||||
downloadPath,
|
||||
fileType: path.extname(fileName).substring(1),
|
||||
};
|
||||
|
||||
// File to render
|
||||
const fileSource = {
|
||||
fileName,
|
||||
contentType,
|
||||
downloadPath,
|
||||
filePath: url,
|
||||
fileType: path.extname(fileName).substring(1),
|
||||
};
|
||||
// Update state
|
||||
this.setState({ fileSource });
|
||||
});
|
||||
// Readable stream from file
|
||||
fileSource.stream = opts => fs.createReadStream(downloadPath, opts);
|
||||
|
||||
// Blob url from stream
|
||||
fileSource.blob = callback =>
|
||||
toBlobURL(fs.createReadStream(downloadPath), contentType, callback);
|
||||
|
||||
// Update state
|
||||
this.setState({ fileSource });
|
||||
}
|
||||
|
||||
renderAudio(container, autoplay) {
|
||||
|
@ -287,5 +287,5 @@ class VideoPlayer extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
export default VideoPlayer;
|
||||
export default MediaPlayer;
|
||||
/* eslint-disable */
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import fs from 'fs';
|
||||
import LoadingScreen from 'component/common/loading-screen';
|
||||
import CodeViewer from 'component/viewers/codeViewer';
|
||||
import MarkdownPreview from 'component/common/markdown-preview';
|
||||
|
@ -9,9 +8,9 @@ import MarkdownPreview from 'component/common/markdown-preview';
|
|||
type Props = {
|
||||
theme: string,
|
||||
source: {
|
||||
stream: opts => void,
|
||||
fileType: string,
|
||||
filePath: string,
|
||||
downloadPath: string,
|
||||
contentType: string,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -27,7 +26,7 @@ class DocumentViewer extends React.PureComponent<Props> {
|
|||
|
||||
componentDidMount() {
|
||||
const { source } = this.props;
|
||||
const stream = fs.createReadStream(source.downloadPath, 'utf8');
|
||||
const stream = source.stream('utf8');
|
||||
|
||||
let data = '';
|
||||
|
||||
|
@ -40,23 +39,20 @@ class DocumentViewer extends React.PureComponent<Props> {
|
|||
});
|
||||
|
||||
stream.on('error', error => {
|
||||
this.setState({ error });
|
||||
this.setState({ error: true, loading: false });
|
||||
});
|
||||
}
|
||||
|
||||
renderDocument() {
|
||||
renderDocument(content = null) {
|
||||
let viewer = null;
|
||||
const { source, theme } = this.props;
|
||||
const { fileType, contentType } = source;
|
||||
const { content, error } = this.state;
|
||||
|
||||
const isReady = content && !error;
|
||||
const markdownType = ['md', 'markdown'];
|
||||
|
||||
if (isReady && markdownType.includes(fileType)) {
|
||||
if (markdownType.includes(fileType)) {
|
||||
// Render markdown
|
||||
viewer = <MarkdownPreview content={content} promptLinks />;
|
||||
} else if (isReady) {
|
||||
} else {
|
||||
// Render plain text
|
||||
viewer = <CodeViewer value={content} contentType={contentType} theme={theme} />;
|
||||
}
|
||||
|
@ -65,15 +61,16 @@ class DocumentViewer extends React.PureComponent<Props> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { error, loading } = this.state;
|
||||
const { error, loading, content } = this.state;
|
||||
const isReady = content && !error;
|
||||
const loadingMessage = __('Rendering document.');
|
||||
const errorMessage = __("Sorry, looks like we can't load the document.");
|
||||
|
||||
return (
|
||||
<div className="file-render__viewer document-viewer">
|
||||
{loading && !error && <LoadingScreen status={loadingMessage} spinner />}
|
||||
{error && <LoadingScreen status={errorMessage} spinner={false} />}
|
||||
{this.renderDocument()}
|
||||
{error && <LoadingScreen status={errorMessage} spinner={!error} />}
|
||||
{isReady && this.renderDocument(content)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,11 +7,7 @@ import LoadingScreen from 'component/common/loading-screen';
|
|||
import MarkdownPreview from 'component/common/markdown-preview';
|
||||
|
||||
type Props = {
|
||||
source: {
|
||||
fileType: string,
|
||||
filePath: string,
|
||||
downloadPath: string,
|
||||
},
|
||||
source: string,
|
||||
};
|
||||
|
||||
class DocxViewer extends React.PureComponent<Props> {
|
||||
|
@ -26,6 +22,7 @@ class DocxViewer extends React.PureComponent<Props> {
|
|||
componentDidMount() {
|
||||
const { source } = this.props;
|
||||
|
||||
// Overwrite element and styles
|
||||
const options = {
|
||||
styleMap: [
|
||||
"p[style-name='Title'] => h1:fresh",
|
||||
|
@ -38,15 +35,19 @@ class DocxViewer extends React.PureComponent<Props> {
|
|||
"p[style-name='Aside Text'] => div.aside > p:fresh",
|
||||
],
|
||||
};
|
||||
|
||||
// Parse docx to html
|
||||
mammoth
|
||||
.convertToHtml({ path: source.downloadPath }, options)
|
||||
.convertToHtml({ path: source }, options)
|
||||
.then(result => {
|
||||
// Remove images and tables
|
||||
const breakdance = new Breakdance({ omit: ['table', 'img'] });
|
||||
// Convert html to markdown
|
||||
const markdown = breakdance.render(result.value);
|
||||
this.setState({ content: markdown, loading: false });
|
||||
})
|
||||
.catch(error => {
|
||||
this.setState({ error, loading: false });
|
||||
this.setState({ error: true, loading: false });
|
||||
})
|
||||
.done();
|
||||
}
|
||||
|
@ -54,11 +55,12 @@ class DocxViewer extends React.PureComponent<Props> {
|
|||
render() {
|
||||
const { content, error, loading } = this.state;
|
||||
const loadingMessage = __('Rendering document.');
|
||||
const errorMessage = __("Sorry, looks like we can't load the document.");
|
||||
|
||||
return (
|
||||
<div className="document-viewer file-render__viewer">
|
||||
{loading && <LoadingScreen status={loadingMessage} spinner />}
|
||||
{error && <LoadingScreen status={error} spinner={false} />}
|
||||
{error && <LoadingScreen status={errorMessage} spinner={false} />}
|
||||
{content && (
|
||||
<div className="document-viewer__content">
|
||||
<MarkdownPreview content={content} promptLinks />
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
// @flow
|
||||
import React from 'react';
|
||||
import { stopContextMenu } from 'util/contextMenu';
|
||||
|
||||
type Props = {
|
||||
source: {
|
||||
fileType: string,
|
||||
filePath: string,
|
||||
downloadPath: string,
|
||||
},
|
||||
source: string,
|
||||
};
|
||||
|
||||
class PdfViewer extends React.PureComponent<Props> {
|
||||
|
@ -15,20 +12,11 @@ class PdfViewer extends React.PureComponent<Props> {
|
|||
this.viewer = React.createRef();
|
||||
}
|
||||
|
||||
// TODO: Enable context-menu
|
||||
stopContextMenu = event => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { source } = this.props;
|
||||
return (
|
||||
<div className="file-render__viewer" onContextMenu={this.stopContextMenu}>
|
||||
<webview
|
||||
ref={this.viewer}
|
||||
src={`chrome://pdf-viewer/index.html?src=file://${source.downloadPath}`}
|
||||
/>
|
||||
<div className="file-render__viewer" onContextMenu={stopContextMenu}>
|
||||
<webview ref={this.viewer} src={`chrome://pdf-viewer/index.html?src=file://${source}`} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ type Props = {
|
|||
autoRotate: boolean,
|
||||
source: {
|
||||
fileType: string,
|
||||
filePath: string,
|
||||
downloadPath: string,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -17,13 +17,13 @@ const Loader = (fileType, manager) => {
|
|||
return fileTypes[fileType] ? fileTypes[fileType]() : null;
|
||||
};
|
||||
|
||||
const ThreeLoader = ({ fileType, filePath }, renderModel, managerEvents) => {
|
||||
const ThreeLoader = ({ fileType = null, downloadPath = null }, renderModel, managerEvents) => {
|
||||
if (fileType) {
|
||||
const manager = Manager(managerEvents);
|
||||
const loader = Loader(fileType, manager);
|
||||
|
||||
if (loader) {
|
||||
loader.load(filePath, data => {
|
||||
loader.load(`file://${downloadPath}`, data => {
|
||||
renderModel(fileType, data);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue