rerender through callback instead of after modifying model
this way rendering is centralized and we can better rerender from interaction in the autocompleter (we didn't have access to caret before)pull/21833/head
parent
aa1b4bb91e
commit
64b171198c
|
@ -44,7 +44,11 @@ export default class MessageEditor extends React.Component {
|
||||||
() => this._autocompleteRef,
|
() => this._autocompleteRef,
|
||||||
query => this.setState({query}),
|
query => this.setState({query}),
|
||||||
);
|
);
|
||||||
this.model = new EditorModel(parseEvent(this.props.event), partCreator);
|
this.model = new EditorModel(
|
||||||
|
parseEvent(this.props.event),
|
||||||
|
partCreator,
|
||||||
|
this._updateEditorState,
|
||||||
|
);
|
||||||
const room = this.context.matrixClient.getRoom(this.props.event.getRoomId());
|
const room = this.context.matrixClient.getRoom(this.props.event.getRoomId());
|
||||||
this.state = {
|
this.state = {
|
||||||
autoComplete: null,
|
autoComplete: null,
|
||||||
|
@ -54,20 +58,25 @@ export default class MessageEditor extends React.Component {
|
||||||
this._autocompleteRef = null;
|
this._autocompleteRef = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onInput = (event) => {
|
_updateEditorState = (caret) => {
|
||||||
const caretOffset = getCaretOffset(this._editorRef);
|
const shouldRerender = false; //event.inputType === "insertFromDrop" || event.inputType === "insertFromPaste";
|
||||||
const caret = this.model.update(this._editorRef.textContent, event.inputType, caretOffset);
|
|
||||||
// const parts = this.model.serializeParts();
|
|
||||||
const shouldRerender = event.inputType === "insertFromDrop" || event.inputType === "insertFromPaste";
|
|
||||||
if (shouldRerender) {
|
if (shouldRerender) {
|
||||||
rerenderModel(this._editorRef, this.model);
|
rerenderModel(this._editorRef, this.model);
|
||||||
} else {
|
} else {
|
||||||
renderModel(this._editorRef, this.model);
|
renderModel(this._editorRef, this.model);
|
||||||
}
|
}
|
||||||
|
if (caret) {
|
||||||
setCaretPosition(this._editorRef, caret);
|
setCaretPosition(this._editorRef, caret);
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({autoComplete: this.model.autoComplete});
|
this.setState({autoComplete: this.model.autoComplete});
|
||||||
this._updateModelOutput();
|
const modelOutput = this._editorRef.parentElement.querySelector(".model");
|
||||||
|
modelOutput.textContent = JSON.stringify(this.model.serializeParts(), undefined, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onInput = (event) => {
|
||||||
|
const caretOffset = getCaretOffset(this._editorRef);
|
||||||
|
this.model.update(this._editorRef.textContent, event.inputType, caretOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyDown = (event) => {
|
_onKeyDown = (event) => {
|
||||||
|
@ -109,25 +118,14 @@ export default class MessageEditor extends React.Component {
|
||||||
|
|
||||||
_onAutoCompleteConfirm = (completion) => {
|
_onAutoCompleteConfirm = (completion) => {
|
||||||
this.model.autoComplete.onComponentConfirm(completion);
|
this.model.autoComplete.onComponentConfirm(completion);
|
||||||
renderModel(this._editorRef, this.model);
|
|
||||||
this._updateModelOutput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onAutoCompleteSelectionChange = (completion) => {
|
_onAutoCompleteSelectionChange = (completion) => {
|
||||||
this.model.autoComplete.onComponentSelectionChange(completion);
|
this.model.autoComplete.onComponentSelectionChange(completion);
|
||||||
renderModel(this._editorRef, this.model);
|
|
||||||
this._updateModelOutput();
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateModelOutput() {
|
|
||||||
const modelOutput = this._editorRef.parentElement.querySelector(".model");
|
|
||||||
modelOutput.textContent = JSON.stringify(this.model.serializeParts(), undefined, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const editor = this._editorRef;
|
this._updateEditorState();
|
||||||
rerenderModel(editor, this.model);
|
|
||||||
this._updateModelOutput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -17,12 +17,13 @@ limitations under the License.
|
||||||
import {diffAtCaret, diffDeletion} from "./diff";
|
import {diffAtCaret, diffDeletion} from "./diff";
|
||||||
|
|
||||||
export default class EditorModel {
|
export default class EditorModel {
|
||||||
constructor(parts, partCreator) {
|
constructor(parts, partCreator, updateCallback) {
|
||||||
this._parts = parts;
|
this._parts = parts;
|
||||||
this._partCreator = partCreator;
|
this._partCreator = partCreator;
|
||||||
this._activePartIdx = null;
|
this._activePartIdx = null;
|
||||||
this._autoComplete = null;
|
this._autoComplete = null;
|
||||||
this._autoCompletePartIdx = null;
|
this._autoCompletePartIdx = null;
|
||||||
|
this._updateCallback = updateCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
_insertPart(index, part) {
|
_insertPart(index, part) {
|
||||||
|
@ -90,7 +91,7 @@ export default class EditorModel {
|
||||||
const caretOffset = diff.at + (diff.added ? diff.added.length : 0);
|
const caretOffset = diff.at + (diff.added ? diff.added.length : 0);
|
||||||
const newPosition = this._positionForOffset(caretOffset, true);
|
const newPosition = this._positionForOffset(caretOffset, true);
|
||||||
this._setActivePart(newPosition);
|
this._setActivePart(newPosition);
|
||||||
return newPosition;
|
this._updateCallback(newPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
_setActivePart(pos) {
|
_setActivePart(pos) {
|
||||||
|
@ -116,10 +117,12 @@ export default class EditorModel {
|
||||||
|
|
||||||
_onAutoComplete = ({replacePart, replaceCaret, close}) => {
|
_onAutoComplete = ({replacePart, replaceCaret, close}) => {
|
||||||
this._replacePart(this._autoCompletePartIdx, replacePart);
|
this._replacePart(this._autoCompletePartIdx, replacePart);
|
||||||
|
const index = this._autoCompletePartIdx;
|
||||||
if (close) {
|
if (close) {
|
||||||
this._autoComplete = null;
|
this._autoComplete = null;
|
||||||
this._autoCompletePartIdx = null;
|
this._autoCompletePartIdx = null;
|
||||||
}
|
}
|
||||||
|
this._updateCallback(new DocumentPosition(index, replaceCaret));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue