diff --git a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.html b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.html index 4834d2b2a..dc7e0038e 100644 --- a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.html +++ b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.html @@ -1,5 +1,6 @@ diff --git a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts index 4b5fa1fb1..29526bf6e 100644 --- a/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/editor/editor.component.ts @@ -25,45 +25,32 @@ const notZero = (lineChange: ILineChange) => lineChange.originalEndLineNumber != styleUrls: ['./editor.component.scss'], }) export class EditorComponent implements OnInit { + @Input() showDiffEditor = false; + @Input() diffEditorText: string; + @Input() @OnChange('revert') initialEntries: List; + @Input() canEdit = false; + + /** Used as [modified] input on diff editor, shouldn't be updated when editing in diff editor. */ diffValue: string; editorOptions: IStandaloneEditorConstructionOptions = {}; - @Input() - showDiffEditor = false; - @Input() - @OnChange('revert') - initialEntries: List; - @Input() - canEdit = false; - currentEntries: string[] = []; codeEditor: ICodeEditor; - diffEditor: IDiffEditor; + value: string; + private _diffEditor: IDiffEditor; private _decorations: string[] = []; - _diffEditorText = ''; - get diffEditorText() { - return this._diffEditorText; - } - - @Input() - set diffEditorText(value: string) { - this._diffEditorText = value; - this.diffEditor?.getOriginalEditor().setValue(value); - } - - get value(): string { - return this.currentEntries.join('\n'); - } - - set value(text: string) { - this.currentEntries = text.split('\n'); - this.codeEditorTextChanged(); + get currentEntries(): string[] { + return this.value.split('\n'); } get hasChanges(): boolean { return this.currentEntries.toString() !== this.initialEntries.toString(); } + private get _currentEntriesCount(): number { + return this.currentEntries.length; + } + ngOnInit(): void { - this.currentEntries = [...this.initialEntries]; + this.revert(); this.editorOptions = { theme: 'vs', @@ -75,9 +62,13 @@ export class EditorComponent implements OnInit { } onDiffEditorInit(editor: IDiffEditor): void { - this.diffEditor = editor; + this._diffEditor = editor; + this.codeEditor = editor.getModifiedEditor(); this._addMarginButtons(); - this.diffEditor.getOriginalEditor().onMouseDown(event => this._handleMarginButtonClick(event)); + this._diffEditor.getOriginalEditor().onMouseDown(event => this._handleMarginButtonClick(event)); + this._diffEditor.getModifiedEditor().onDidChangeModelContent(() => { + this.value = this._diffEditor.getModel().modified.getValue(); + }); } onCodeEditorInit(editor: ICodeEditor): void { @@ -96,12 +87,14 @@ export class EditorComponent implements OnInit { @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; } revert() { - this.currentEntries = [...this.initialEntries]; + this.value = this.initialEntries.join('\n'); + this.diffValue = this.value; + this._diffEditor?.getModifiedEditor().setValue(this.diffValue); } private _handleMarginButtonClick(event: IEditorMouseEvent) { @@ -113,23 +106,33 @@ export class EditorComponent implements OnInit { } private _addContentFromOriginalAtLine(lineNumber: number) { - const lineContent = this.diffEditor.getOriginalEditor().getModel().getLineContent(lineNumber); - const entriesBefore = this.currentEntries.slice(0, lineNumber); - const entriesAfter = this.currentEntries.slice(lineNumber); - this.currentEntries = [...entriesBefore, lineContent, ...entriesAfter]; + const lineContent = this._diffEditor.getOriginalEditor().getModel().getLineContent(lineNumber) + '\n'; + const lineChanges = this._diffEditor.getLineChanges(); + let targetLineNumber = lineNumber; + for (const lineChange of lineChanges) { + const { originalStartLineNumber, originalEndLineNumber, modifiedStartLineNumber } = lineChange; + if (originalStartLineNumber <= lineNumber && originalEndLineNumber >= lineNumber) { + targetLineNumber = modifiedStartLineNumber + 1; + break; + } + } + const prefix = + targetLineNumber > this._currentEntriesCount && this.currentEntries[this._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() { let glyphDecorations = []; - this.diffEditor.onDidUpdateDiff(() => { + this._diffEditor.onDidUpdateDiff(() => { /** * Sometimes diff editor thinks that there's a change that starts on a line greater than 0 and ends on line 0. * We must get all change that started on a line and ended on the same or greater line * Otherwise margin buttons will have an odd behaviour */ - const lineChanges = this.diffEditor.getLineChanges().filter(change => isPositive(change) && notZero(change)); + const lineChanges = this._diffEditor.getLineChanges().filter(change => isPositive(change) && notZero(change)); const decorations = lineChanges.map(lineChangeToDecoration); - glyphDecorations = this.diffEditor.getOriginalEditor().deltaDecorations(glyphDecorations, decorations); + glyphDecorations = this._diffEditor.getOriginalEditor().deltaDecorations(glyphDecorations, decorations); }); }