Merge pull request #2983 from matrix-org/bwindels/editor-cursor-fixes

Message editing: fix some bugs in cursor behaviour
This commit is contained in:
Bruno Windels 2019-05-16 20:05:48 +00:00 committed by GitHub
commit 9744cbd448
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 22 deletions

View file

@ -144,12 +144,7 @@ export default class MessageEditor extends React.Component {
componentDidMount() { componentDidMount() {
this._updateEditorState(); this._updateEditorState();
const sel = document.getSelection(); setCaretPosition(this._editorRef, this.model, this.model.getPositionAtEnd());
const range = document.createRange();
range.selectNodeContents(this._editorRef);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
this._editorRef.focus(); this._editorRef.focus();
} }

View file

@ -61,6 +61,16 @@ export default class EditorModel {
return null; return null;
} }
getPositionAtEnd() {
if (this._parts.length) {
const index = this._parts.length - 1;
const part = this._parts[index];
return new DocumentPosition(index, part.text.length);
} else {
return new DocumentPosition(0, 0);
}
}
serializeParts() { serializeParts() {
return this._parts.map(({type, text}) => {return {type, text};}); return this._parts.map(({type, text}) => {return {type, text};});
} }
@ -88,7 +98,8 @@ export default class EditorModel {
} }
this._mergeAdjacentParts(); this._mergeAdjacentParts();
const caretOffset = diff.at - removedOffsetDecrease + addedLen; const caretOffset = diff.at - removedOffsetDecrease + addedLen;
const newPosition = this._positionForOffset(caretOffset, true); let newPosition = this._positionForOffset(caretOffset, true);
newPosition = newPosition.skipUneditableParts(this._parts);
this._setActivePart(newPosition); this._setActivePart(newPosition);
this._updateCallback(newPosition); this._updateCallback(newPosition);
} }
@ -172,6 +183,8 @@ export default class EditorModel {
// part might be undefined here // part might be undefined here
let part = this._parts[index]; let part = this._parts[index];
const amount = Math.min(len, part.text.length - offset); const amount = Math.min(len, part.text.length - offset);
// don't allow 0 amount deletions
if (amount) {
if (part.canEdit) { if (part.canEdit) {
const replaceWith = part.remove(offset, amount); const replaceWith = part.remove(offset, amount);
if (typeof replaceWith === "string") { if (typeof replaceWith === "string") {
@ -188,6 +201,9 @@ export default class EditorModel {
removedOffsetDecrease += offset; removedOffsetDecrease += offset;
this._removePart(index); this._removePart(index);
} }
} else {
index += 1;
}
len -= amount; len -= amount;
offset = 0; offset = 0;
} }
@ -261,4 +277,13 @@ class DocumentPosition {
get offset() { get offset() {
return this._offset; return this._offset;
} }
skipUneditableParts(parts) {
const part = parts[this.index];
if (part && !part.canEdit) {
return new DocumentPosition(this.index + 1, 0);
} else {
return this;
}
}
} }

View file

@ -57,7 +57,7 @@ class BasePart {
appendUntilRejected(str) { appendUntilRejected(str) {
for (let i = 0; i < str.length; ++i) { for (let i = 0; i < str.length; ++i) {
const chr = str.charAt(i); const chr = str.charAt(i);
if (!this.acceptsInsertion(chr)) { if (!this.acceptsInsertion(chr, i)) {
this._text = this._text + str.substr(0, i); this._text = this._text + str.substr(0, i);
return str.substr(i); return str.substr(i);
} }
@ -180,8 +180,8 @@ class PillPart extends BasePart {
} }
export class NewlinePart extends BasePart { export class NewlinePart extends BasePart {
acceptsInsertion(chr) { acceptsInsertion(chr, i) {
return this.text.length === 0 && chr === "\n"; return (this.text.length + i) === 0 && chr === "\n";
} }
acceptsRemoval(position, chr) { acceptsRemoval(position, chr) {
@ -205,6 +205,14 @@ export class NewlinePart extends BasePart {
get type() { get type() {
return "newline"; return "newline";
} }
// this makes the cursor skip this part when it is inserted
// rather than trying to append to it, which is what we want.
// As a newline can also be only one character, it makes sense
// as it can only be one character long. This caused #9741.
get canEdit() {
return false;
}
} }
export class RoomPillPart extends PillPart { export class RoomPillPart extends PillPart {