File viewer v2 #1826

Merged
btzr-io merged 17 commits from fix-viewer into master 2018-08-06 03:53:57 +02:00
4 changed files with 44 additions and 15 deletions
Showing only changes of commit 1f554c8e20 - Show all commits

View file

@ -6,7 +6,7 @@ import MarkdownPreview from 'component/common/markdown-preview';
import SimpleMDE from 'react-simplemde-editor'; import SimpleMDE from 'react-simplemde-editor';
import 'simplemde/dist/simplemde.min.css'; import 'simplemde/dist/simplemde.min.css';
import Toggle from 'react-toggle'; import Toggle from 'react-toggle';
import { openEditorMenu } from 'util/contextMenu'; import { openEditorMenu, stopContextMenu } from 'util/contextMenu';
type Props = { type Props = {
name: string, name: string,
@ -55,15 +55,10 @@ export class FormField extends React.PureComponent<Props> {
</select> </select>
); );
} else if (type === 'markdown') { } else if (type === 'markdown') {
const stopContextMenu = event => {
event.preventDefault();
event.stopPropagation();
};
const handleEvents = { const handleEvents = {
contextmenu(codeMirror, event) { contextmenu: openEditorMenu,
openEditorMenu(event, codeMirror);
},
}; };
input = ( input = (
<div className="form-field--SimpleMDE" onContextMenu={stopContextMenu}> <div className="form-field--SimpleMDE" onContextMenu={stopContextMenu}>
<SimpleMDE <SimpleMDE

View file

@ -2,6 +2,7 @@
import React from 'react'; import React from 'react';
import CodeMirror from 'codemirror/lib/codemirror'; import CodeMirror from 'codemirror/lib/codemirror';
import { openSnippetMenu, stopContextMenu } from 'util/contextMenu';
// Addons // Addons
import 'codemirror/addon/selection/mark-selection'; import 'codemirror/addon/selection/mark-selection';
@ -26,21 +27,29 @@ class CodeViewer extends React.PureComponent<Props> {
componentDidMount() { componentDidMount() {
const { theme, contentType } = this.props; const { theme, contentType } = this.props;
// Init CodeMirror
this.codeMirror = CodeMirror.fromTextArea(this.textarea.current, { this.codeMirror = CodeMirror.fromTextArea(this.textarea.current, {
// Auto detect syntax with file contentType
mode: contentType, mode: contentType,
// Adaptive theme
theme: theme === 'dark' ? 'dark' : 'default', theme: theme === 'dark' ? 'dark' : 'default',
readOnly: 'nocursor', // Hide the cursor
readOnly: true,
// Styled text selection
styleSelectedText: true,
// Additional config opts
dragDrop: false, dragDrop: false,
lineNumbers: true, lineNumbers: true,
lineWrapping: true, lineWrapping: true,
styleSelectedText: true,
}); });
// Add events
this.codeMirror.on('contextmenu', openSnippetMenu);
} }
render() { render() {
const { value } = this.props; const { value } = this.props;
return ( return (
<div className="code-viewer"> <div className="code-viewer" onContextMenu={stopContextMenu}>
<textarea ref={this.textarea} disabled value={value} /> <textarea ref={this.textarea} disabled value={value} />
</div> </div>
); );

View file

@ -23,9 +23,9 @@ function injectDevelopmentTemplate(event, templates) {
export function openContextMenu(event, templates = [], canEdit = false, selection = '') { export function openContextMenu(event, templates = [], canEdit = false, selection = '') {
const { type, value } = event.target; const { type, value } = event.target;
const isSomethingSelected = selection.length > 0 || window.getSelection().toString().length > 0;
const isInput = event.target.matches('input') && (type === 'text' || type === 'number'); const isInput = event.target.matches('input') && (type === 'text' || type === 'number');
const isTextField = canEdit || isInput || event.target.matches('textarea'); const isTextField = canEdit || isInput || event.target.matches('textarea');
const isSomethingSelected = selection.length > 0 || window.getSelection().toString().length > 0;
templates.push({ templates.push({
label: 'Copy', label: 'Copy',
@ -63,7 +63,7 @@ export function openContextMenu(event, templates = [], canEdit = false, selectio
} }
// This function is used for the markdown description on the publish page // This function is used for the markdown description on the publish page
export function openEditorMenu(event, codeMirror) { export function openEditorMenu(codeMirror, event) {
const value = codeMirror.doc.getValue(); const value = codeMirror.doc.getValue();
const selection = codeMirror.doc.getSelection(); const selection = codeMirror.doc.getSelection();
const templates = [ const templates = [
@ -86,6 +86,25 @@ export function openEditorMenu(event, codeMirror) {
openContextMenu(event, templates, true, selection); openContextMenu(event, templates, true, selection);
} }
// This function is used for the CodeViewer component
export function openSnippetMenu(codeMirror, event) {
const value = codeMirror.doc.getValue();
const selection = codeMirror.doc.getSelection();
const templates = [
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall',
click: () => {
codeMirror.execCommand('selectAll');
},
// Enabled if there is text to select
enabled: value.length > 0,
},
];
openContextMenu(event, templates, false, selection);
}
export function openCopyLinkMenu(text, event) { export function openCopyLinkMenu(text, event) {
const templates = [ const templates = [
{ {
@ -97,3 +116,9 @@ export function openCopyLinkMenu(text, event) {
]; ];
openContextMenu(event, templates); openContextMenu(event, templates);
} }
// Block context menu
export function stopContextMenu(event) {
event.preventDefault();
event.stopPropagation();
}

View file

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