Fix autocomplete not resetting properly on message send (#10741)
This commit is contained in:
parent
0d1020c66f
commit
f819853cad
3 changed files with 49 additions and 13 deletions
|
@ -99,10 +99,10 @@ export default class EditorModel {
|
||||||
|
|
||||||
private insertPart(index: number, part: Part): void {
|
private insertPart(index: number, part: Part): void {
|
||||||
this._parts.splice(index, 0, part);
|
this._parts.splice(index, 0, part);
|
||||||
if (this.activePartIdx && this.activePartIdx >= index) {
|
if (this.activePartIdx !== null && this.activePartIdx >= index) {
|
||||||
++this.activePartIdx;
|
++this.activePartIdx;
|
||||||
}
|
}
|
||||||
if (this.autoCompletePartIdx && this.autoCompletePartIdx >= index) {
|
if (this.autoCompletePartIdx !== null && this.autoCompletePartIdx >= index) {
|
||||||
++this.autoCompletePartIdx;
|
++this.autoCompletePartIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,12 +111,12 @@ export default class EditorModel {
|
||||||
this._parts.splice(index, 1);
|
this._parts.splice(index, 1);
|
||||||
if (index === this.activePartIdx) {
|
if (index === this.activePartIdx) {
|
||||||
this.activePartIdx = null;
|
this.activePartIdx = null;
|
||||||
} else if (this.activePartIdx && this.activePartIdx > index) {
|
} else if (this.activePartIdx !== null && this.activePartIdx > index) {
|
||||||
--this.activePartIdx;
|
--this.activePartIdx;
|
||||||
}
|
}
|
||||||
if (index === this.autoCompletePartIdx) {
|
if (index === this.autoCompletePartIdx) {
|
||||||
this.autoCompletePartIdx = null;
|
this.autoCompletePartIdx = null;
|
||||||
} else if (this.autoCompletePartIdx && this.autoCompletePartIdx > index) {
|
} else if (this.autoCompletePartIdx !== null && this.autoCompletePartIdx > index) {
|
||||||
--this.autoCompletePartIdx;
|
--this.autoCompletePartIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { Caret } from "../../src/editor/caret";
|
||||||
import { PillPart, Part, PartCreator } from "../../src/editor/parts";
|
import { PillPart, Part, PartCreator } from "../../src/editor/parts";
|
||||||
import DocumentPosition from "../../src/editor/position";
|
import DocumentPosition from "../../src/editor/position";
|
||||||
|
|
||||||
class MockAutoComplete {
|
export class MockAutoComplete {
|
||||||
public _updateCallback;
|
public _updateCallback;
|
||||||
public _partCreator;
|
public _partCreator;
|
||||||
public _completions;
|
public _completions;
|
||||||
|
@ -44,7 +44,7 @@ class MockAutoComplete {
|
||||||
});
|
});
|
||||||
if (matches.length === 1 && this._part && this._part.text.length > 1) {
|
if (matches.length === 1 && this._part && this._part.text.length > 1) {
|
||||||
const match = matches[0];
|
const match = matches[0];
|
||||||
let pill;
|
let pill: PillPart;
|
||||||
if (match.resourceId[0] === "@") {
|
if (match.resourceId[0] === "@") {
|
||||||
pill = this._partCreator.userPill(match.text, match.resourceId);
|
pill = this._partCreator.userPill(match.text, match.resourceId);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import EditorModel from "../../src/editor/model";
|
import EditorModel from "../../src/editor/model";
|
||||||
import { createPartCreator, createRenderer } from "./mock";
|
import { createPartCreator, createRenderer, MockAutoComplete } from "./mock";
|
||||||
import DocumentOffset from "../../src/editor/offset";
|
import DocumentOffset from "../../src/editor/offset";
|
||||||
import { PillPart } from "../../src/editor/parts";
|
import { PillPart } from "../../src/editor/parts";
|
||||||
import DocumentPosition from "../../src/editor/position";
|
import DocumentPosition from "../../src/editor/position";
|
||||||
|
@ -186,8 +186,7 @@ describe("editor/model", function () {
|
||||||
expect(model.parts[1].text).toBe("@a");
|
expect(model.parts[1].text).toBe("@a");
|
||||||
|
|
||||||
// this is a hacky mock function
|
// this is a hacky mock function
|
||||||
// @ts-ignore
|
(model.autoComplete as unknown as MockAutoComplete).tryComplete();
|
||||||
model.autoComplete.tryComplete(); // see MockAutoComplete
|
|
||||||
|
|
||||||
expect(renderer.count).toBe(2);
|
expect(renderer.count).toBe(2);
|
||||||
expect((renderer.caret as DocumentPosition).index).toBe(1);
|
expect((renderer.caret as DocumentPosition).index).toBe(1);
|
||||||
|
@ -216,8 +215,7 @@ describe("editor/model", function () {
|
||||||
expect(model.parts[1].text).toBe("#r");
|
expect(model.parts[1].text).toBe("#r");
|
||||||
|
|
||||||
// this is a hacky mock function
|
// this is a hacky mock function
|
||||||
// @ts-ignore
|
(model.autoComplete as unknown as MockAutoComplete).tryComplete();
|
||||||
model.autoComplete.tryComplete(); // see MockAutoComplete
|
|
||||||
|
|
||||||
expect(renderer.count).toBe(2);
|
expect(renderer.count).toBe(2);
|
||||||
expect((renderer.caret as DocumentPosition).index).toBe(1);
|
expect((renderer.caret as DocumentPosition).index).toBe(1);
|
||||||
|
@ -236,8 +234,7 @@ describe("editor/model", function () {
|
||||||
|
|
||||||
model.update("hello #r", "insertText", new DocumentOffset(8, true));
|
model.update("hello #r", "insertText", new DocumentOffset(8, true));
|
||||||
// this is a hacky mock function
|
// this is a hacky mock function
|
||||||
// @ts-ignore
|
(model.autoComplete as unknown as MockAutoComplete).tryComplete();
|
||||||
model.autoComplete.tryComplete(); // see MockAutoComplete
|
|
||||||
model.update("hello #riot-dev!!", "insertText", new DocumentOffset(17, true));
|
model.update("hello #riot-dev!!", "insertText", new DocumentOffset(17, true));
|
||||||
|
|
||||||
expect(renderer.count).toBe(3);
|
expect(renderer.count).toBe(3);
|
||||||
|
@ -314,6 +311,45 @@ describe("editor/model", function () {
|
||||||
expect(model.parts[0].type).toBe("plain");
|
expect(model.parts[0].type).toBe("plain");
|
||||||
expect(model.parts[0].text).toBe("foo@a");
|
expect(model.parts[0].text).toBe("foo@a");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should allow auto-completing multiple times with resets between them", () => {
|
||||||
|
const renderer = createRenderer();
|
||||||
|
const pc = createPartCreator([{ resourceId: "#riot-dev" } as PillPart]);
|
||||||
|
const model = new EditorModel([pc.plain("")], pc, renderer);
|
||||||
|
|
||||||
|
model.update("#r", "insertText", new DocumentOffset(8, true));
|
||||||
|
|
||||||
|
expect(renderer.count).toBe(1);
|
||||||
|
expect((renderer.caret as DocumentPosition).index).toBe(0);
|
||||||
|
expect((renderer.caret as DocumentPosition).offset).toBe(2);
|
||||||
|
expect(model.parts.length).toBe(1);
|
||||||
|
expect(model.parts[0].type).toBe("pill-candidate");
|
||||||
|
expect(model.parts[0].text).toBe("#r");
|
||||||
|
|
||||||
|
// this is a hacky mock function
|
||||||
|
(model.autoComplete as unknown as MockAutoComplete).tryComplete();
|
||||||
|
|
||||||
|
expect(renderer.count).toBe(2);
|
||||||
|
expect((renderer.caret as DocumentPosition).index).toBe(0);
|
||||||
|
expect((renderer.caret as DocumentPosition).offset).toBe(9);
|
||||||
|
expect(model.parts.length).toBe(1);
|
||||||
|
expect(model.parts[0].type).toBe("room-pill");
|
||||||
|
expect(model.parts[0].text).toBe("#riot-dev");
|
||||||
|
|
||||||
|
model.reset([]);
|
||||||
|
model.update("#r", "insertText", new DocumentOffset(8, true));
|
||||||
|
|
||||||
|
expect(model.parts.length).toBe(1);
|
||||||
|
expect(model.parts[0].type).toBe("pill-candidate");
|
||||||
|
expect(model.parts[0].text).toBe("#r");
|
||||||
|
|
||||||
|
// this is a hacky mock function
|
||||||
|
(model.autoComplete as unknown as MockAutoComplete).tryComplete();
|
||||||
|
|
||||||
|
expect(model.parts.length).toBe(1);
|
||||||
|
expect(model.parts[0].type).toBe("room-pill");
|
||||||
|
expect(model.parts[0].text).toBe("#riot-dev");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("emojis", function () {
|
describe("emojis", function () {
|
||||||
it("regional emojis should be separated to prevent them to be converted to flag", () => {
|
it("regional emojis should be separated to prevent them to be converted to flag", () => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue