add code-viewer

This commit is contained in:
btzr-io 2018-07-26 18:24:00 -06:00
parent 1c50b71f14
commit c622314eff
8 changed files with 140 additions and 48 deletions

View file

@ -36,6 +36,7 @@
"dependencies": {
"bluebird": "^3.5.1",
"classnames": "^2.2.5",
"codemirror": "^5.39.2",
"country-data": "^0.0.31",
"dom-scroll-into-view": "^1.2.1",
"electron-dl": "^1.11.0",

View file

@ -0,0 +1,38 @@
// @flow
import React from 'react';
import CodeMirror from 'codemirror';
type Props = {
value: string,
};
class CodeViewer extends React.PureComponent<Props> {
constructor(props) {
super(props);
this.codeMirror = null;
this.textarea = React.createRef();
}
componentDidMount() {
this.codeMirror = CodeMirror.fromTextArea(this.textarea.current, {
mode: 'markdown',
readOnly: true,
dragDrop: false,
lineNumbers: true,
lineWrapping: true,
});
}
render() {
const { value } = this.props;
return (
<div className="document-viewer__content">
<textarea ref={this.textarea} disabled="true" value={value} />
</div>
);
}
}
export default CodeViewer;

View file

@ -3,6 +3,7 @@
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';
type Props = {
@ -34,7 +35,7 @@ class DocumentViewer extends React.PureComponent<Props> {
});
stream.on('end', () => {
this.setState({ content: data });
this.setState({ content: data, loading: false });
});
stream.on('error', error => {
@ -42,36 +43,34 @@ class DocumentViewer extends React.PureComponent<Props> {
});
}
renderDocument(data) {
renderDocument() {
let viewer = null;
const { source } = this.props;
const { fileType } = source;
const { content, error } = this.state;
const isReady = content && !error;
const markdownType = ['md', 'markdown'];
// Match supported documents
const docs = {
md: content => <MarkdownPreview content={content} promptLinks />,
};
if (docs[fileType]) {
// Use custom parser
return docs[fileType](data);
if (isReady && markdownType.includes(source.fileType)) {
// Render markdown
viewer = <MarkdownPreview content={content} promptLinks />;
} else if (isReady) {
// Render plain text
viewer = <CodeViewer value={content} />;
}
// Render plain text
this.setState({ loading: false });
return <textarea disabled="true" value={data} />;
return viewer;
}
render() {
const { content, error, loading } = this.state;
const { 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">
<div className="file-render__viewer document-viewer">
{loading && !error && <LoadingScreen status={loadingMessage} spinner />}
{error && <LoadingScreen status={errorMessage} spinner={false} />}
{content && (
<div className="document-viewer__content">{content && this.renderDocument(content)}</div>
)}
{this.renderDocument()}
</div>
);
}

View file

@ -96,25 +96,6 @@
}
}
.file-render {
width: 100%;
height: 100%;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
overflow: hidden;
.file-render__viewer {
width: 100%;
height: 100%;
background: black;
}
}
img {
max-height: 100%;
max-width: 100%;

View file

@ -9,17 +9,80 @@
bottom: 0;
z-index: 1;
overflow: hidden;
}
.file-render__viewer {
margin: 0;
.file-render__viewer {
margin: 0;
width: 100%;
height: 100%;
background-color: black;
iframe,
webview {
width: 100%;
height: 100%;
background: black;
iframe,
webview {
width: 100%;
height: 100%;
}
}
}
.document-viewer {
overflow: auto;
background-color: var(--card-bg);
}
.document-viewer .markdown-preview {
padding: 32px 16px;
}
.document-viewer .CodeMirror {
height: 100%;
width: 100%;
min-height: 100px;
padding: 0;
margin: 0;
.CodeMirror-code {
font-size: calc(var(--font-size-subtext-multiple) * 1em);
font-family: monospace;
}
.CodeMirror-linenumber {
color: var(--card-text-color);
}
.CodeMirror-line {
padding-left: 16px;
}
.CodeMirror-gutters {
border-right: 1px solid var(--color-divider);
background: var(--color-bg-alt);
}
.cm-invalidchar {
display: none;
}
}
.document-viewer__content {
overflow: auto;
width: 100%;
height: 100%;
.markdown-preview {
padding: 32px 16px;
height: 100%;
overflow: auto;
}
textarea {
/*
resize: none;
background: transparent;
color: var(--card-text-color);
border: 0;
outline: none;
font-family: monospace;
*/
display: none;
}
}

View file

@ -63,6 +63,11 @@
}
}
/* Image */
img {
margin: 16px 0;
}
/* Horizontal Rule */
hr {
border: 1px solid var(--color-divider);

View file

@ -3,7 +3,8 @@ import mime from 'mime';
const formats = [
[/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'],
[/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'],
[/\.(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'],
[/\.(json|csv|txt|log|md|markdown|rtf|xml|yml|yaml)$/i, 'document'],
[/\.(pdf|odf|doc|docx|epub|org)$/i, 'e-book'],
[/\.(stl|obj|fbx|gcode)$/i, '3D-file'],
];

View file

@ -1893,6 +1893,10 @@ codemirror@*:
version "5.39.0"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.39.0.tgz#4654f7d2f7e525e04a62e72d9482348ccb37dce5"
codemirror@^5.39.2:
version "5.39.2"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.39.2.tgz#778aa13b55ebf280745c309cb1b148e3fc06f698"
collapse-white-space@^1.0.0, collapse-white-space@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091"