diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index e90d1c19..9bfcf0d2 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -40,11 +40,9 @@ class Editor extends React.Component { this.widgets = []; this._cm = CodeMirror(this.refs.container, { // eslint-disable-line theme: `p5-${this.props.theme}`, - value: this.props.file.content, lineNumbers: true, styleActiveLine: true, inputStyle: 'contenteditable', - mode: 'javascript', lineWrapping: false, fixedGutter: false, gutters: ['CodeMirror-lint-markers'], @@ -64,6 +62,9 @@ class Editor extends React.Component { } }); + this.initializeDocuments(this.props.files); + this._cm.swapDoc(this._docs[this.props.file.id]); + this._cm.on('change', debounce(() => { this.props.setUnsavedChanges(true); this.props.updateFileContent(this.props.file.name, this._cm.getValue()); @@ -89,10 +90,20 @@ class Editor extends React.Component { this._cm.setOption('tabSize', this.props.indentationAmount); } + componentWillUpdate(nextProps) { + // check if files have changed + if (this.props.files[0].id !== nextProps.files[0].id) { + // then need to make CodeMirror documents + this.initializeDocuments(nextProps.files); + } + } + componentDidUpdate(prevProps) { if (this.props.file.content !== prevProps.file.content && this.props.file.content !== this._cm.getValue()) { - this._cm.setValue(this.props.file.content); // eslint-disable-line no-underscore-dangle + const oldDoc = this._cm.swapDoc(this._docs[this.props.file.id]); + this._docs[prevProps.file.id] = oldDoc; + this._cm.focus(); if (!prevProps.unsavedChanges) { setTimeout(() => this.props.setUnsavedChanges(false), 400); } @@ -106,20 +117,6 @@ class Editor extends React.Component { if (this.props.isTabIndent !== prevProps.isTabIndent) { this._cm.setOption('indentWithTabs', this.props.isTabIndent); } - if (this.props.file.name !== prevProps.name) { - if (this.props.file.name.match(/.+\.js$/i)) { - this._cm.setOption('mode', 'javascript'); - } else if (this.props.file.name.match(/.+\.css$/i)) { - this._cm.setOption('mode', 'css'); - } else if (this.props.file.name.match(/.+\.html$/i)) { - this._cm.setOption('mode', 'htmlmixed'); - } else if (this.props.file.name.match(/.+\.json$/i)) { - this._cm.setOption('mode', 'application/json'); - } else { - this._cm.setOption('mode', 'text/plain'); - } - } - if (this.props.theme !== prevProps.theme) { this._cm.setOption('theme', `p5-${this.props.theme}`); } @@ -129,6 +126,31 @@ class Editor extends React.Component { this._cm = null; } + getFileMode(fileName) { + let mode; + if (fileName.match(/.+\.js$/i)) { + mode = 'javascript'; + } else if (fileName.match(/.+\.css$/i)) { + mode = 'css'; + } else if (fileName.match(/.+\.html$/i)) { + mode = 'htmlmixed'; + } else if (fileName.match(/.+\.json$/i)) { + mode = 'application/json'; + } else { + mode = 'text/plain'; + } + return mode; + } + + initializeDocuments(files) { + this._docs = {}; + files.forEach(file => { + if (file.fileType === 'file') { + this._docs[file.id] = CodeMirror.Doc(file.content, this.getFileMode(file.name)); // eslint-disable-line + } + }); + } + tidyCode() { const beautifyOptions = { indent_size: this.props.indentationAmount, @@ -211,7 +233,8 @@ Editor.propTypes = { fontSize: PropTypes.number.isRequired, file: PropTypes.shape({ name: PropTypes.string.isRequired, - content: PropTypes.string.isRequired + content: PropTypes.string.isRequired, + id: PropTypes.string.isRequired }), editorOptionsVisible: PropTypes.bool.isRequired, showEditorOptions: PropTypes.func.isRequired, @@ -223,7 +246,8 @@ Editor.propTypes = { isPlaying: PropTypes.bool.isRequired, theme: PropTypes.string.isRequired, unsavedChanges: PropTypes.bool.isRequired, - projectSavedTime: PropTypes.string.isRequired + projectSavedTime: PropTypes.string.isRequired, + files: PropTypes.array.isRequired }; export default Editor;