RED-6786: fix editor performance issue

This commit is contained in:
Dan Percic 2023-05-24 19:42:59 +03:00
parent d73b460e82
commit db6eefbee7
3 changed files with 47 additions and 40 deletions

View File

@ -27,8 +27,8 @@
<iqser-circle-button
(action)="download()"
*ngIf="canDownload"
[matTooltip]="'dictionary-overview.download' | translate"
[attr.help-mode-key]="helpModeKey"
[matTooltip]="'dictionary-overview.download' | translate"
class="ml-8"
icon="iqser:download"
></iqser-circle-button>
@ -83,7 +83,6 @@
[diffEditorText]="diffEditorText"
[initialEntries]="initialEntries"
[showDiffEditor]="compare && showDiffEditor"
(enableSaveButton)="onEnableSaveButton($event)"
></redaction-editor>
<div *ngIf="compare && optionNotSelected" class="no-dictionary-selected">
@ -97,7 +96,6 @@
(action)="saveDictionary.emit()"
[label]="'dictionary-overview.save-changes' | translate"
[type]="iconButtonTypes.primary"
[disabled]="!saveButtonEnabled()"
icon="iqser:check"
></iqser-icon-button>
<div (click)="revert()" class="all-caps-label cancel" translate="dictionary-overview.revert-changes"></div>

View File

@ -1,4 +1,4 @@
import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, signal, SimpleChanges, ViewChild } from '@angular/core';
import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core';
import { Debounce, IconButtonTypes, List, LoadingService } from '@iqser/common-ui';
import { firstValueFrom, Observable, of } from 'rxjs';
import { catchError, map, take, tap } from 'rxjs/operators';
@ -26,9 +26,6 @@ const HELP_MODE_KEYS = {
styleUrls: ['./dictionary-manager.component.scss'],
})
export class DictionaryManagerComponent implements OnChanges {
readonly iconButtonTypes = IconButtonTypes;
readonly saveButtonEnabled = signal(true);
@Input() type: DictionaryType = 'dictionary';
@Input() entityType?: string;
@Input() withFloatingActions = true;
@ -39,6 +36,9 @@ export class DictionaryManagerComponent implements OnChanges {
@Input() isLeavingPage = false;
@Output() readonly saveDictionary = new EventEmitter<string[]>();
@ViewChild(EditorComponent) readonly editor: EditorComponent;
readonly iconButtonTypes = IconButtonTypes;
currentMatch = 0;
findMatches: FindMatch[] = [];
diffEditorText = '';
@ -212,10 +212,6 @@ export class DictionaryManagerComponent implements OnChanges {
}
}
onEnableSaveButton(value: boolean) {
this.saveButtonEnabled.set(value);
}
private _applySearchDecorations() {
this._searchDecorations = this.editor.codeEditor?.deltaDecorations(this._searchDecorations, []) || [];

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Debounce, List, LoadingService, OnChange } from '@iqser/common-ui';
import { EditorThemeService } from '@services/editor-theme.service';
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
@ -30,7 +30,6 @@ export class EditorComponent implements OnInit, OnChanges {
@Input() diffEditorText: string;
@Input() @OnChange<List, EditorComponent>('revert') initialEntries: List;
@Input() canEdit = false;
@Output() enableSaveButton = new EventEmitter<boolean>();
/**
* Used as [modified] input on diff editor
@ -53,10 +52,18 @@ export class EditorComponent implements OnInit, OnChanges {
return this.currentEntries.toString() !== this.initialEntries.toString();
}
private get _currentEntriesCount(): number {
get #currentEntriesCount(): number {
return this.currentEntries.length;
}
@Debounce()
codeEditorTextChanged() {
const newDecorations = this.#getDecorations();
this._decorations = this.codeEditor.deltaDecorations(this._decorations, newDecorations);
this.diffValue = this.value;
this._loadingService.stop();
}
ngOnChanges(changes: SimpleChanges) {
if (changes.diffEditorText) {
this._diffEditor?.getOriginalEditor().setValue(this.diffEditorText);
@ -79,26 +86,17 @@ export class EditorComponent implements OnInit, OnChanges {
onDiffEditorInit(editor: IDiffEditor): void {
this._diffEditor = editor;
this.codeEditor = editor.getModifiedEditor();
this._addMarginButtons();
this._diffEditor.getOriginalEditor().onMouseDown(event => this._handleMarginButtonClick(event));
this.#addMarginButtons();
this._diffEditor.getOriginalEditor().onMouseDown(event => this.#handleMarginButtonClick(event));
this._diffEditor.getModifiedEditor().onDidChangeModelContent(() => {
this.value = this._diffEditor.getModel().modified.getValue();
});
this._setTheme();
this.#setTheme();
}
onCodeEditorInit(editor: ICodeEditor): void {
this.codeEditor = editor;
this._setTheme();
}
@Debounce()
codeEditorTextChanged() {
const newDecorations = this.currentEntries.filter(entry => this._isNew(entry)).map(entry => this._getDecoration(entry));
this._decorations = this.codeEditor.deltaDecorations(this._decorations, newDecorations);
this.diffValue = this.value;
this._loadingService.stop();
this.enableSaveButton.emit(true);
this.#setTheme();
}
revert() {
@ -109,28 +107,44 @@ export class EditorComponent implements OnInit, OnChanges {
onPaste() {
this._loadingService.start();
this.enableSaveButton.emit(false);
}
private _defineThemes(): void {
#getDecorations() {
const currentEntries = this.currentEntries;
const newDecorations: IModelDeltaDecoration[] = [];
for (let index = 0; index < currentEntries.length; ++index) {
const entry = currentEntries.at(index);
if (!this.#isNew(entry)) {
continue;
}
const line = index + 1;
newDecorations.push(this.#getDecoration(entry, line));
}
return newDecorations;
}
#defineThemes(): void {
for (const theme of this._editorThemeService.themes) {
(window as any).monaco.editor.defineTheme(theme, this._editorThemeService.configurations[theme]);
}
}
private _setTheme(): void {
this._defineThemes();
#setTheme(): void {
this.#defineThemes();
(window as any).monaco.editor.setTheme(this._editorThemeService.getTheme(this.canEdit));
}
private _handleMarginButtonClick(event: IEditorMouseEvent) {
#handleMarginButtonClick(event: IEditorMouseEvent) {
const isMarginButtonClick = event.target.detail.glyphMarginWidth && event.target.detail.glyphMarginWidth !== 0;
if (isMarginButtonClick) {
this._addContentFromOriginalAtLine(event.target.position.lineNumber);
this.#addContentFromOriginalAtLine(event.target.position.lineNumber);
}
}
private _addContentFromOriginalAtLine(lineNumber: number) {
#addContentFromOriginalAtLine(lineNumber: number) {
const lineContent = this._diffEditor.getOriginalEditor().getModel().getLineContent(lineNumber) + '\n';
const lineChanges = this._diffEditor.getLineChanges();
let targetLineNumber = lineNumber;
@ -141,13 +155,13 @@ export class EditorComponent implements OnInit, OnChanges {
break;
}
}
const prefix =
targetLineNumber > this._currentEntriesCount && this.currentEntries[this._currentEntriesCount - 1] !== '' ? '\n' : '';
const currentEntriesCount = this.#currentEntriesCount;
const prefix = targetLineNumber > currentEntriesCount && this.currentEntries[currentEntriesCount - 1] !== '' ? '\n' : '';
const range = new monaco.Range(targetLineNumber, 1, targetLineNumber, 1);
this._diffEditor.getModifiedEditor().executeEdits(null, [{ range, text: prefix + lineContent, forceMoveMarkers: true }]);
}
private _addMarginButtons() {
#addMarginButtons() {
let glyphDecorations = [];
this._diffEditor.onDidUpdateDiff(() => {
/**
@ -164,12 +178,11 @@ export class EditorComponent implements OnInit, OnChanges {
});
}
private _isNew(entry: string): boolean {
#isNew(entry: string): boolean {
return this.initialEntries.indexOf(entry) < 0 && entry?.trim().length > 0;
}
private _getDecoration(entry: string): IModelDeltaDecoration {
const line = this.currentEntries.indexOf(entry) + 1;
#getDecoration(entry: string, line: number): IModelDeltaDecoration {
const cssClass = entry.length < MIN_WORD_LENGTH ? 'too-short-marker' : 'changed-row-marker';
const range = new monaco.Range(line, 1, line, 1);