RED-6786: faster text editor
This commit is contained in:
parent
5bbcdac4df
commit
45d6ca6166
@ -94,6 +94,7 @@
|
||||
<div *ngIf="withFloatingActions && !!editor?.hasChanges && canEdit && !isLeavingPage" [class.offset]="compare" class="changes-box">
|
||||
<iqser-icon-button
|
||||
(action)="saveDictionary.emit()"
|
||||
[disabled]="!!(_loadingService.isLoading$ | async)"
|
||||
[label]="'dictionary-overview.save-changes' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:check"
|
||||
|
||||
@ -56,7 +56,7 @@ export class DictionaryManagerComponent implements OnChanges {
|
||||
constructor(
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
protected readonly _loadingService: LoadingService,
|
||||
private readonly _changeRef: ChangeDetectorRef,
|
||||
readonly activeDossiersService: ActiveDossiersService,
|
||||
readonly dossierTemplatesService: DossierTemplatesService,
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<ngx-monaco-editor
|
||||
(init)="onCodeEditorInit($event)"
|
||||
(ngModelChange)="codeEditorTextChanged()"
|
||||
(ngModelChange)="_editorTextChanged$.next($event)"
|
||||
(paste)="onPaste()"
|
||||
*ngIf="!showDiffEditor"
|
||||
[(ngModel)]="value"
|
||||
[options]="editorOptions"
|
||||
(paste)="onPaste()"
|
||||
></ngx-monaco-editor>
|
||||
|
||||
<ngx-monaco-diff-editor
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { Debounce, List, LoadingService, OnChange } from '@iqser/common-ui';
|
||||
import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { List, LoadingService, OnChange } from '@iqser/common-ui';
|
||||
import { EditorThemeService } from '@services/editor-theme.service';
|
||||
import { debounceTime, filter, tap } from 'rxjs/operators';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
|
||||
import ICodeEditor = monaco.editor.ICodeEditor;
|
||||
import IDiffEditor = monaco.editor.IDiffEditor;
|
||||
@ -25,7 +27,7 @@ const notZero = (lineChange: ILineChange) => lineChange.originalEndLineNumber !=
|
||||
templateUrl: './editor.component.html',
|
||||
styleUrls: ['./editor.component.scss'],
|
||||
})
|
||||
export class EditorComponent implements OnInit, OnChanges {
|
||||
export class EditorComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@Input() showDiffEditor = false;
|
||||
@Input() diffEditorText: string;
|
||||
@Input() @OnChange<List, EditorComponent>('revert') initialEntries: List;
|
||||
@ -39,10 +41,25 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
editorOptions: IStandaloneEditorConstructionOptions = {};
|
||||
codeEditor: ICodeEditor;
|
||||
value: string;
|
||||
protected readonly _editorTextChanged$ = new Subject<string>();
|
||||
private _diffEditor: IDiffEditor;
|
||||
private _decorations: string[] = [];
|
||||
private readonly _sub$ = new Subscription();
|
||||
private _initialEntriesSet = new Set<string>();
|
||||
|
||||
constructor(private readonly _loadingService: LoadingService, private readonly _editorThemeService: EditorThemeService) {}
|
||||
constructor(private readonly _loadingService: LoadingService, private readonly _editorThemeService: EditorThemeService) {
|
||||
const textChanged$ = this._editorTextChanged$.pipe(
|
||||
debounceTime(300), // prevent race condition with onPaste event
|
||||
filter(text => text.length > 0),
|
||||
tap(newText => {
|
||||
const newDecorations = this._getDecorations(newText);
|
||||
this._decorations = this.codeEditor.deltaDecorations(this._decorations, newDecorations);
|
||||
this.diffValue = this.value;
|
||||
this._loadingService.stop();
|
||||
}),
|
||||
);
|
||||
this._sub$.add(textChanged$.subscribe());
|
||||
}
|
||||
|
||||
get currentEntries(): string[] {
|
||||
return this.value.split('\n');
|
||||
@ -56,6 +73,10 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
return this.currentEntries.length;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._sub$.unsubscribe();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes.diffEditorText) {
|
||||
this._diffEditor?.getOriginalEditor().setValue(this.diffEditorText);
|
||||
@ -91,21 +112,17 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
this._setTheme();
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
codeEditorTextChanged() {
|
||||
const newDecorations = this._getDecorations();
|
||||
this._decorations = this.codeEditor.deltaDecorations(this._decorations, newDecorations);
|
||||
this.diffValue = this.value;
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
_getDecorations() {
|
||||
const currentEntries = this.currentEntries;
|
||||
_getDecorations(text: string) {
|
||||
const currentEntries = text.split('\n');
|
||||
const newDecorations: IModelDeltaDecoration[] = [];
|
||||
|
||||
for (let index = 0; index < currentEntries.length; ++index) {
|
||||
const entry = currentEntries.at(index);
|
||||
if (!this._isNew(entry)) {
|
||||
for (let index = 0; index < currentEntries.length; index++) {
|
||||
const entry = currentEntries.at(index)?.trim();
|
||||
if (!entry || entry.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this._initialEntriesSet.has(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -118,8 +135,10 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
|
||||
revert() {
|
||||
this.value = this.initialEntries.join('\n');
|
||||
this._initialEntriesSet = new Set<string>(this.initialEntries);
|
||||
this.diffValue = this.value;
|
||||
this._diffEditor?.getModifiedEditor().setValue(this.diffValue);
|
||||
this._editorTextChanged$.next(this.value);
|
||||
}
|
||||
|
||||
onPaste() {
|
||||
@ -178,10 +197,6 @@ export class EditorComponent implements OnInit, OnChanges {
|
||||
});
|
||||
}
|
||||
|
||||
private _isNew(entry: string): boolean {
|
||||
return this.initialEntries.indexOf(entry) < 0 && entry?.trim().length > 0;
|
||||
}
|
||||
|
||||
private _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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user