update last caret from update callback instead of input event

many editor updates are not caused by an input event, so
the last caret wasn't always up to date.

Updating the caret from the update callback ensures that every
time the editor contents is changed, the last caret is updated.
pull/21833/head
Bruno Windels 2019-09-06 11:09:01 +02:00
parent 124b7135cd
commit 2596281a7c
2 changed files with 23 additions and 7 deletions

View File

@ -116,6 +116,9 @@ export default class BasicMessageEditor extends React.Component {
} catch (err) {
console.error(err);
}
// if caret is a range, take the end position
const position = caret.end || caret;
this._setLastCaretFromPosition(position);
}
if (this.props.placeholder) {
const {isEmpty} = this.props.model;
@ -165,7 +168,6 @@ export default class BasicMessageEditor extends React.Component {
this._modifiedFlag = true;
const sel = document.getSelection();
const {caret, text} = getCaretOffsetAndText(this._editorRef, sel);
this._setLastCaret(caret, text, sel);
this.props.model.update(text, event.inputType, caret);
}
@ -183,10 +185,11 @@ export default class BasicMessageEditor extends React.Component {
// we don't need to. But if the user is navigating the caret without input
// we need to recalculate it, to be able to know where to insert content after
// losing focus
_setLastCaret(caret, text, selection) {
this._lastSelection = cloneSelection(selection);
this._lastCaret = caret;
this._lastTextLength = text.length;
_setLastCaretFromPosition(position) {
const {model} = this.props;
this._isCaretAtEnd = position.isAtEnd(model);
this._lastCaret = position.asOffset(model);
this._lastSelection = cloneSelection(document.getSelection());
}
_refreshLastCaretIfNeeded() {
@ -201,7 +204,7 @@ export default class BasicMessageEditor extends React.Component {
this._lastSelection = cloneSelection(selection);
const {caret, text} = getCaretOffsetAndText(this._editorRef, selection);
this._lastCaret = caret;
this._lastTextLength = text.length;
this._isCaretAtEnd = caret.offset === text.length;
}
return this._lastCaret;
}
@ -223,7 +226,7 @@ export default class BasicMessageEditor extends React.Component {
}
isCaretAtEnd() {
return this.getCaret().offset === this._lastTextLength;
return this._isCaretAtEnd;
}
_onBlur = () => {

View File

@ -120,4 +120,17 @@ export default class DocumentPosition {
const atEnd = offset >= lastPart.text.length;
return new DocumentOffset(offset, atEnd);
}
isAtEnd(model) {
if (model.parts.length === 0) {
return true;
}
const lastPartIdx = model.parts.length - 1;
const lastPart = model.parts[lastPartIdx];
return this.index === lastPartIdx && this.offset === lastPart.text.length;
}
isAtStart() {
return this.index === 0 && this.offset === 0;
}
}