Skip to content
This repository has been archived by the owner on Feb 12, 2022. It is now read-only.

馃毃PERFORMANCE ISSUE 馃毃 #113

Open
seokju-na opened this issue Dec 18, 2018 · 0 comments
Open

馃毃PERFORMANCE ISSUE 馃毃 #113

seokju-na opened this issue Dec 18, 2018 · 0 comments

Comments

@seokju-na
Copy link
Owner

seokju-na commented Dec 18, 2018

As the number of snippets increases, performance decreases. Currently we implemented snippet editor with CodeMirror. Although I have not yet understood the source code, CodeMirros seems that the size of the editor is recalculated each keydown.

To solve this problem, I suggest options:

  1. Improve layout re-calculate process
  2. Replace with other editor library

You can see performance profile via Google Drive.

Suggestion editor integration

Monaco Editor

code-snippet.component.ts

Very very old version of code snippet editor. We need to adapt to the latest interface.

Ace Editor

Below code implements NoteSnippetEditor with AceEditor.

import { BACKSPACE, DOWN_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
import { Ace } from 'ace-builds';
import { NoteSnippetEditor, NoteSnippetEditorBlurredEvent, NoteSnippetEditorFocusedEvent } from './note-snippet-editor';


export type AceEditor = Ace.Editor;
export type AceEditorOptions = Ace.EditorOptions;

const _ace = (window as any).ace;
const _createEditor: (
    element: HTMLElement,
    options?: Partial<AceEditorOptions>,
) => AceEditor = _ace.edit;
const _Range = _ace.Range as {
    new(startRow: number, startColumn: number, endRow: number, endColumn: number): Ace.Range;
};


export abstract class NoteSnippetAceEditor extends NoteSnippetEditor<AceEditor> {
    _editor: AceEditor;

    abstract editorHostEl: HTMLElement;

    private changeEventListener: () => void;
    private focusEventListener: () => void;
    private blurEventListener: () => void;

    abstract getEditorOptions(): Partial<AceEditorOptions>;

    initialize(): void {
        this._editor = _createEditor(this.editorHostEl, this.getEditorOptions());

        this.changeEventListener = () => {
            this.onValueChanged();
        };

        this.focusEventListener = () => {
            this.handleFocus(true);
            this.emitEvent(new NoteSnippetEditorFocusedEvent(this._ref));
        };

        this.blurEventListener = () => {
            this.handleFocus(false);
            this.emitEvent(new NoteSnippetEditorBlurredEvent(this._ref));
        };

        // FIXME
        this._editor.commands.addCommand({
            name: 'removeSnippetIfEmpty',
            bindKey: 'Delete',
            exec: () => this.onKeyDown({ keyCode: BACKSPACE } as KeyboardEvent),
        });

        // FIXME
        this._editor.commands.addCommand({
            name: 'moveFocusToPreviousSnippet',
            bindKey: 'Up',
            exec: () => this.onKeyDown({ keyCode: UP_ARROW } as KeyboardEvent),
        });

        // FIXME
        this._editor.commands.addCommand({
            name: 'moveFocusToNextSnippet',
            bindKey: 'Down',
            exec: () => this.onKeyDown({ keyCode: DOWN_ARROW } as KeyboardEvent),
        });

        this._editor.on('change', this.changeEventListener);
        this._editor.on('focus', this.focusEventListener);
        this._editor.on('blur', this.blurEventListener);
    }

    dispose(): void {
        if (this._editor) {
            this._editor.off('change', this.changeEventListener);
            this._editor.off('focus', this.focusEventListener);
            this._editor.off('blur', this.blurEventListener);
            this._editor.destroy();
        }
    }

    focus(): void {
        this._editor.focus();
    }

    blur(): void {
        if (this._editor.isFocused() && document.activeElement) {
            (document.activeElement as HTMLElement).blur();
        }
    }

    getRawValue(): string {
        return this._editor.session.getValue();
    }

    setRawValue(value: string): void {
        this._editor.session.setValue(value);
    }

    insertValueAtCursor(value: string): void {
        const { row, column } = this._editor.selection.getCursor();
        const range = new _Range(row, column, row, column);

        this._editor.session.replace(range, value);
    }

    isCurrentPositionTop(): boolean {
        const { row } = this._editor.selection.getCursor();
        return row === 0;
    }

    isCurrentPositionBottom(): boolean {
        const { row } = this._editor.selection.getCursor();
        const linesCount = this._editor.session.getLength();

        return row === linesCount - 1;
    }

    setPositionToTop(): void {
        this._editor.moveCursorTo(0, 0);
    }

    setPositionToBottom(): void {
        const linesCount = this._editor.session.getLength();
        this._editor.moveCursorTo(linesCount - 1, 0);
    }

    abstract handleFocus(focused: boolean): void;
}
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant