don't update model while doing IME composition

this prevents the composition from being disrupted because
the DOM is modified, and also complete compositions are added
to the undo history like this.
This commit is contained in:
Bruno Windels 2019-08-29 13:56:21 +02:00
parent 599fccd9ce
commit 891ccf0f4c

View file

@ -75,6 +75,7 @@ export default class BasicMessageEditor extends React.Component {
this._editorRef = null;
this._autocompleteRef = null;
this._modifiedFlag = false;
this._isIMEComposing = false;
}
_replaceEmoticon = (caretPosition, inputType, diff) => {
@ -119,11 +120,9 @@ export default class BasicMessageEditor extends React.Component {
if (this.props.placeholder) {
const {isEmpty} = this.props.model;
if (isEmpty) {
this._editorRef.style.setProperty("--placeholder", `'${this.props.placeholder}'`);
this._editorRef.classList.add("mx_BasicMessageComposer_inputEmpty");
this._showPlaceholder();
} else {
this._editorRef.classList.remove("mx_BasicMessageComposer_inputEmpty");
this._editorRef.style.removeProperty("--placeholder");
this._hidePlaceholder();
}
}
this.setState({autoComplete: this.props.model.autoComplete});
@ -135,7 +134,31 @@ export default class BasicMessageEditor extends React.Component {
}
}
_showPlaceholder() {
this._editorRef.style.setProperty("--placeholder", `'${this.props.placeholder}'`);
this._editorRef.classList.add("mx_BasicMessageComposer_inputEmpty");
}
_hidePlaceholder() {
this._editorRef.classList.remove("mx_BasicMessageComposer_inputEmpty");
this._editorRef.style.removeProperty("--placeholder");
}
_onCompositionStart = (event) => {
this._isIMEComposing = true;
// even if the model is empty, the composition text shouldn't be mixed with the placeholder
this._hidePlaceholder();
}
_onCompositionEnd = (event) => {
this._isIMEComposing = false;
}
_onInput = (event) => {
// ignore any input while doing IME compositions
if (this._isIMEComposing) {
return;
}
this._modifiedFlag = true;
const sel = document.getSelection();
const {caret, text} = getCaretOffsetAndText(this._editorRef, sel);
@ -323,6 +346,8 @@ export default class BasicMessageEditor extends React.Component {
componentWillUnmount() {
this._editorRef.removeEventListener("input", this._onInput, true);
this._editorRef.removeEventListener("compositionstart", this._onCompositionStart, true);
this._editorRef.removeEventListener("compositionend", this._onCompositionEnd, true);
}
componentDidMount() {
@ -344,6 +369,8 @@ export default class BasicMessageEditor extends React.Component {
// attach input listener by hand so React doesn't proxy the events,
// as the proxied event doesn't support inputType, which we need.
this._editorRef.addEventListener("input", this._onInput, true);
this._editorRef.addEventListener("compositionstart", this._onCompositionStart, true);
this._editorRef.addEventListener("compositionend", this._onCompositionEnd, true);
this._editorRef.focus();
}