Skip to content

Commit

Permalink
fix(Editor): poor performance when typing rapidly
Browse files Browse the repository at this point in the history
  • Loading branch information
luolonghao committed Jul 14, 2024
1 parent 2f5808b commit 017560d
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 47 deletions.
92 changes: 50 additions & 42 deletions src/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,56 +348,64 @@ export class Editor {
this.unsavedInputCount = 0;
}

// Binds events about input.
// Handles input event.
private handleInputEvent(event: InputEvent | CompositionEvent) {
this.selection.updateByRange();
const range = this.selection.range;
if (range.isInsideBox) {
return;
}
if (range.isBoxStart || range.isBoxEnd) {
this.moveBoxStripText();
this.history.save();
return;
}
const inputType = event instanceof CompositionEvent ? 'insertText' : event.inputType;
if (inputType === 'insertText') {
const inputData = event.data ?? '';
if (inputData.length > 1) {
this.history.save({
inputType: 'insertText',
update: false,
});
return;
}
this.unsavedInputData += inputData;
this.unsavedInputCount++;
if (this.unsavedInputData.length < this.config.minChangeSize) {
this.history.save({
inputType: 'insertText',
update: this.unsavedInputCount > 1,
});
} else {
this.history.save({
inputType: 'insertText',
update: true,
});
this.resetUnsavedInputData();
}
return;
}
this.history.save();
}

// Binds events about inputting text.
private bindInputEvents(): void {
this.container.on('compositionstart', () => {
this.isComposing = true;
this.container.removeClass('lake-placeholder');
});
this.container.on('compositionend', () => {
this.container.on('compositionend', event => {
this.isComposing = false;
this.handleInputEvent(event as CompositionEvent);
});
this.container.on('input', event => {
const inputEvent = event as InputEvent;
// Here setTimeout is necessary because isComposing is not false after ending composition.
window.setTimeout(() => {
const range = this.selection.range;
if (range.isInsideBox) {
return;
}
// isComposing is false after ending composition because compositionend event has been emitted.
if (this.isComposing) {
if (inputEvent.inputType === 'insertCompositionText') {
this.container.removeClass('lake-placeholder');
}
return;
}
if (range.isBoxStart || range.isBoxEnd) {
this.moveBoxStripText();
this.history.save();
return;
}
if (
inputEvent.inputType === 'insertText' ||
inputEvent.inputType === 'insertCompositionText'
) {
this.unsavedInputData += inputEvent.data ?? '';
this.unsavedInputCount++;
if (this.unsavedInputData.length < this.config.minChangeSize) {
this.history.save({
inputType: 'insertText',
update: this.unsavedInputCount > 1,
});
} else {
this.history.save({
inputType: 'insertText',
update: true,
});
this.resetUnsavedInputData();
}
return;
}
this.history.save();
}, 0);
this.isComposing = inputEvent.isComposing;
if (this.isComposing) {
return;
}
this.handleInputEvent(event as InputEvent);
});
}

Expand Down
13 changes: 8 additions & 5 deletions tests/editor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Editor } from '../src/editor';
import { click, getContainerValue } from './utils';

function insertText(editor: Editor, data: string) {
const event = new InputEvent('input', {
const inputEvent = new InputEvent('input', {
data,
inputType: 'insertText',
isComposing: false,
Expand All @@ -18,21 +18,24 @@ function insertText(editor: Editor, data: string) {
if (prevNode.length > 0 && prevNode.name === 'br') {
prevNode.remove();
}
editor.container.emit('input', event);
editor.container.emit('input', inputEvent);
}

function insertCompositionText(editor: Editor, data: string) {
editor.container.emit('compositionstart');
const event = new InputEvent('input', {
const inputEvent = new InputEvent('input', {
data,
inputType: 'insertCompositionText',
isComposing: true,
});
const compositionEvent = new CompositionEvent('compositionend', {
data,
});
const nativeRange = editor.selection.range.get();
nativeRange.insertNode(document.createTextNode(data));
nativeRange.collapse(false);
editor.container.emit('input', event);
editor.container.emit('compositionend');
editor.container.emit('input', inputEvent);
editor.container.emit('compositionend', compositionEvent);
}

function deleteContentBackward(editor: Editor) {
Expand Down

0 comments on commit 017560d

Please sign in to comment.