mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-04 10:22:38 +00:00
use CodeMirror Documents
Instead of re-building the whole editor box with every tab switch, we just swap in and out CodeMirror "documents". Maintains undo history, scroll position, highlight coloring, etc.
This commit is contained in:
@@ -60,6 +60,10 @@ const Editor = createClass({
|
|||||||
window.removeEventListener('resize', this.updateEditorSize);
|
window.removeEventListener('resize', this.updateEditorSize);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
componentDidUpdate : function() {
|
||||||
|
this.highlightCustomMarkdown();
|
||||||
|
},
|
||||||
|
|
||||||
updateEditorSize : function() {
|
updateEditorSize : function() {
|
||||||
if(this.refs.codeEditor) {
|
if(this.refs.codeEditor) {
|
||||||
let paneHeight = this.refs.main.parentNode.clientHeight;
|
let paneHeight = this.refs.main.parentNode.clientHeight;
|
||||||
@@ -177,25 +181,44 @@ const Editor = createClass({
|
|||||||
this.refs.codeEditor?.updateSize();
|
this.refs.codeEditor?.updateSize();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//Called by CodeEditor after document switch, so Snippetbar can refresh UndoHistory
|
||||||
|
rerenderParent : function (){
|
||||||
|
this.forceUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
renderEditor : function(){
|
renderEditor : function(){
|
||||||
if(this.isText()){
|
if(this.isText()){
|
||||||
return <CodeEditor key='text'
|
return <>
|
||||||
ref='codeEditor'
|
<CodeEditor key='codeEditor'
|
||||||
language='gfm'
|
ref='codeEditor'
|
||||||
value={this.props.brew.text}
|
language='gfm'
|
||||||
onChange={this.props.onTextChange} />;
|
view={this.state.view}
|
||||||
|
value={this.props.brew.text}
|
||||||
|
onChange={this.props.onTextChange}
|
||||||
|
rerenderParent={this.rerenderParent} />
|
||||||
|
</>;
|
||||||
}
|
}
|
||||||
if(this.isStyle()){
|
if(this.isStyle()){
|
||||||
return <CodeEditor key='style'
|
return <>
|
||||||
ref='codeEditor'
|
<CodeEditor key='codeEditor'
|
||||||
language='css'
|
ref='codeEditor'
|
||||||
value={this.props.brew.style ?? DEFAULT_STYLE_TEXT}
|
language='css'
|
||||||
onChange={this.props.onStyleChange} />;
|
view={this.state.view}
|
||||||
|
value={this.props.brew.style ?? DEFAULT_STYLE_TEXT}
|
||||||
|
onChange={this.props.onStyleChange}
|
||||||
|
rerenderParent={this.rerenderParent} />
|
||||||
|
</>;
|
||||||
}
|
}
|
||||||
if(this.isMeta()){
|
if(this.isMeta()){
|
||||||
return <MetadataEditor
|
return <>
|
||||||
metadata={this.props.brew}
|
<CodeEditor key='codeEditor'
|
||||||
onChange={this.props.onMetaChange} />;
|
view={this.state.view}
|
||||||
|
style={{ display: 'none', width: '600px' }}
|
||||||
|
rerenderParent={this.rerenderParent} />
|
||||||
|
<MetadataEditor
|
||||||
|
metadata={this.props.brew}
|
||||||
|
onChange={this.props.onMetaChange} />
|
||||||
|
</>;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -212,7 +235,6 @@ const Editor = createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
render : function(){
|
render : function(){
|
||||||
this.highlightCustomMarkdown();
|
|
||||||
return (
|
return (
|
||||||
<div className='editor' ref='main'>
|
<div className='editor' ref='main'>
|
||||||
<SnippetBar
|
<SnippetBar
|
||||||
@@ -224,7 +246,7 @@ const Editor = createClass({
|
|||||||
renderer={this.props.renderer}
|
renderer={this.props.renderer}
|
||||||
undo={this.undo}
|
undo={this.undo}
|
||||||
redo={this.redo}
|
redo={this.redo}
|
||||||
historySize={this.historySize} />
|
historySize={this.historySize()} />
|
||||||
|
|
||||||
{this.renderEditor()}
|
{this.renderEditor()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ const Snippetbar = createClass({
|
|||||||
if(!this.props.showEditButtons) return;
|
if(!this.props.showEditButtons) return;
|
||||||
|
|
||||||
return <div className='editors'>
|
return <div className='editors'>
|
||||||
<div className={`editorTool undo ${this.props.historySize()?.undo ? 'active' : ''}`}
|
<div className={`editorTool undo ${this.props.historySize.undo ? 'active' : ''}`}
|
||||||
onClick={this.props.undo} >
|
onClick={this.props.undo} >
|
||||||
<i className='fas fa-undo' />
|
<i className='fas fa-undo' />
|
||||||
</div>
|
</div>
|
||||||
<div className={`editorTool redo ${this.props.historySize()?.redo ? 'active' : ''}`}
|
<div className={`editorTool redo ${this.props.historySize.redo ? 'active' : ''}`}
|
||||||
onClick={this.props.redo} >
|
onClick={this.props.redo} >
|
||||||
<i className='fas fa-redo' />
|
<i className='fas fa-redo' />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,25 +25,44 @@ const CodeEditor = createClass({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getInitialState : function() {
|
||||||
|
return {
|
||||||
|
docs : {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
componentDidMount : function() {
|
componentDidMount : function() {
|
||||||
this.buildEditor();
|
this.buildEditor();
|
||||||
|
this.codeMirror.setValue(this.props.value);
|
||||||
|
this.codeMirror.clearHistory();
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate : function(prevProps) {
|
componentDidUpdate : function(prevProps) {
|
||||||
if(prevProps.language !== this.props.language){ //rebuild editor when switching tabs
|
if(prevProps.view !== this.props.view){ //view changed; swap documents
|
||||||
this.buildEditor();
|
let newDoc;
|
||||||
}
|
|
||||||
if(this.codeMirror && this.codeMirror.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
|
if(!this.state.docs[this.props.view]) {
|
||||||
|
newDoc = CodeMirror.Doc(this.props.value, this.props.language);
|
||||||
|
} else {
|
||||||
|
newDoc = this.state.docs[this.props.view];
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldDoc = { [prevProps.view]: this.codeMirror.swapDoc(newDoc) };
|
||||||
|
|
||||||
|
this.setState((prevState)=>({
|
||||||
|
docs : _.merge({}, prevState.docs, oldDoc)
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.props.rerenderParent();
|
||||||
|
} else if(this.codeMirror?.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
|
||||||
this.codeMirror.setValue(this.props.value);
|
this.codeMirror.setValue(this.props.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
buildEditor : function() {
|
buildEditor : function() {
|
||||||
this.codeMirror = CodeMirror(this.refs.editor, {
|
this.codeMirror = CodeMirror(this.refs.editor, {
|
||||||
value : this.props.value,
|
|
||||||
lineNumbers : true,
|
lineNumbers : true,
|
||||||
lineWrapping : this.props.wrap,
|
lineWrapping : this.props.wrap,
|
||||||
mode : this.props.language, //TODO: CSS MODE DOESN'T SEEM TO LOAD PROPERLY
|
|
||||||
indentWithTabs : true,
|
indentWithTabs : true,
|
||||||
tabSize : 2,
|
tabSize : 2,
|
||||||
historyEventDelay : 250,
|
historyEventDelay : 250,
|
||||||
@@ -125,7 +144,7 @@ const CodeEditor = createClass({
|
|||||||
//----------------------//
|
//----------------------//
|
||||||
|
|
||||||
render : function(){
|
render : function(){
|
||||||
return <div className='codeEditor' ref='editor' />;
|
return <div className='codeEditor' ref='editor' style={this.props.style}/>;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user