Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: render conflict actions #2002

Merged
merged 2 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Disposable, MonacoService } from '@opensumi/ide-core-browser';
import { ICodeEditor } from '../../monaco-api/editor';

import { ComputerDiffModel } from './model/computer-diff';
import { ActionsManager } from './view/actions-manager';
import { CurrentCodeEditor } from './view/editors/currentCodeEditor';
import { IncomingCodeEditor } from './view/editors/incomingCodeEditor';
import { ResultCodeEditor } from './view/editors/resultCodeEditor';
Expand All @@ -23,6 +24,7 @@ export class MergeEditorService extends Disposable {
private incomingView: IncomingCodeEditor;

private computerDiffModel: ComputerDiffModel;
private actionsManager: ActionsManager;

public scrollSynchronizer: ScrollSynchronizer;
public stickinessConnectManager: StickinessConnectManager;
Expand All @@ -32,6 +34,7 @@ export class MergeEditorService extends Disposable {
this.computerDiffModel = new ComputerDiffModel();
this.scrollSynchronizer = new ScrollSynchronizer();
this.stickinessConnectManager = new StickinessConnectManager();
this.actionsManager = new ActionsManager();
}

public instantiationCodeEditor(current: HTMLDivElement, result: HTMLDivElement, incoming: HTMLDivElement): void {
Expand All @@ -45,6 +48,7 @@ export class MergeEditorService extends Disposable {

this.scrollSynchronizer.mount(this.currentView, this.resultView, this.incomingView);
this.stickinessConnectManager.mount(this.currentView, this.resultView, this.incomingView);
this.actionsManager.mount(this.currentView, this.resultView, this.incomingView);
}

public override dispose(): void {
Expand All @@ -54,6 +58,7 @@ export class MergeEditorService extends Disposable {
this.incomingView.dispose();
this.scrollSynchronizer.dispose();
this.stickinessConnectManager.dispose();
this.actionsManager.dispose();
}

public getCurrentEditor(): ICodeEditor {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Injectable, Optional } from '@opensumi/di';
import { Disposable } from '@opensumi/ide-core-common';
import { IEditorDecorationsCollection } from '@opensumi/monaco-editor-core/esm/vs/editor/common/editorCommon';
import { ModelDecorationOptions } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model/textModel';

import { ICodeEditor, IModelDeltaDecoration } from '../../../monaco-api/editor';
import { IActionsDescription } from '../types';
import { BaseCodeEditor } from '../view/editors/baseCodeEditor';

import { LineRange } from './line-range';

@Injectable({ multiple: false })
export class ConflictActions extends Disposable {
private decorationsCollection: IEditorDecorationsCollection;
private actionsCollect: Map<number, LineRange>;

private get editor(): ICodeEditor {
return this.codeEditor.getEditor();
}

constructor(@Optional() private readonly codeEditor: BaseCodeEditor) {
super();

this.decorationsCollection = this.editor.createDecorationsCollection();
this.actionsCollect = new Map();
}

public override dispose(): void {
super.dispose();
this.decorationsCollection.clear();
this.actionsCollect.clear();
}

public setActions(actions: IActionsDescription[]): void {
const newDecorations: IModelDeltaDecoration[] = actions.map((action) => {
const { range } = action;
this.actionsCollect.set(range.startLineNumber, range);

return {
range: {
startLineNumber: range.startLineNumber,
startColumn: 0,
endLineNumber: range.startLineNumber,
endColumn: 0,
},
options: ModelDecorationOptions.register(action.decorationOptions),
};
});

this.decorationsCollection.set(newDecorations);
}

public getActions(line: number): LineRange | undefined {
return this.actionsCollect.get(line);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface IDiffDecoration {
readonly editorDecoration: IModelDeltaDecoration;
}

@Injectable({ multiple: true })
@Injectable({ multiple: false })
export class MergeEditorDecorations extends Disposable {
private deltaDecoration: IDiffDecoration[] = [];
private retainDecoration: IDiffDecoration[] = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { IRange } from '@opensumi/monaco-editor-core';
import { Range } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';
import { LineRange as MonacoLineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/linesDiffComputer';

export class LineRange extends MonacoLineRange {
Expand All @@ -12,4 +14,11 @@ export class LineRange extends MonacoLineRange {
public isTendencyLeft(refer: LineRange): boolean {
return !this.isEmpty && refer.isEmpty;
}

public toIRange(): IRange {
return Range.fromPositions(
{ lineNumber: this.startLineNumber, column: 0 },
{ lineNumber: this.endLineNumberExclusive - 1, column: 0 },
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import clone from 'lodash/clone';

import { IStickyPiece, IStickyPiecePath, IStickyPiecePosition, LineRangeType } from '../types';

export class StickyPieceModel implements IStickyPiece {
Expand Down
40 changes: 40 additions & 0 deletions packages/monaco/src/browser/contrib/merge-editor/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import { getIcon } from '@opensumi/ide-core-browser';
import { IEditorMouseEvent } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorBrowser';

import { IModelDecorationOptions } from '../../monaco-api/editor';

import { LineRange } from './model/line-range';

export interface IBaseCodeEditor {
mount(): void;
}

export type LineRangeType = 'insert' | 'modify' | 'remove';

export type EditorViewType = 'current' | 'result' | 'incoming';
Expand All @@ -20,3 +31,32 @@ export interface IStickyPiece {
position: IStickyPiecePosition;
path: IStickyPiecePath;
}

export interface IActionsDescription {
range: LineRange;
decorationOptions: IModelDecorationOptions;
}

export const ACCEPT_CURRENT = 'accpet_current';
export const ACCEPT_COMBINATION = 'accpet_combination';
export const IGNORE = 'ignore';

export interface IActionsProvider {
onActionsClick?: (
e: IEditorMouseEvent,
currentView: IBaseCodeEditor,
resultView: IBaseCodeEditor,
incomingView: IBaseCodeEditor,
) => void;
mouseDownGuard?: (e: IEditorMouseEvent) => boolean;
/**
* 提供 actions 操作项
*/
provideActionsItems: () => IActionsDescription[];
}

export namespace CONFLICT_ACTIONS_ICON {
export const RIGHT = `conflict-actions ${ACCEPT_CURRENT} ${getIcon('right')}`;
export const LEFT = `conflict-actions ${ACCEPT_CURRENT} ${getIcon('left')}`;
export const CLOSE = `conflict-actions ${IGNORE} ${getIcon('close')}`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Disposable } from '@opensumi/ide-core-common';
import { IEditorMouseEvent, MouseTargetType } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorBrowser';

import { IActionsDescription } from '../types';

import { BaseCodeEditor } from './editors/baseCodeEditor';

export class ActionsManager extends Disposable {
private currentView: BaseCodeEditor | undefined;
private resultView: BaseCodeEditor | undefined;
private incomingView: BaseCodeEditor | undefined;

constructor() {
super();
}

public mount(currentView: BaseCodeEditor, resultView: BaseCodeEditor, incomingView: BaseCodeEditor): void {
this.currentView = currentView;
this.resultView = resultView;
this.incomingView = incomingView;

const handleMouseDown = (e: IEditorMouseEvent, _this: BaseCodeEditor) => {
const provider = _this.actionsProvider;
if (!provider) {
return;
}

let { mouseDownGuard } = provider;
const { onActionsClick, provideActionsItems } = provider;

if (typeof mouseDownGuard === 'undefined') {
const items = provideActionsItems();
mouseDownGuard = (e: IEditorMouseEvent) => {
if (e.event.rightButton) {
return false;
}

if (e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS) {
return false;
}

const { position } = e.target;

if (!items.some((item: IActionsDescription) => item.range.startLineNumber === position.lineNumber)) {
return false;
}

return true;
};
}

if (mouseDownGuard(e) === true && onActionsClick) {
onActionsClick.call(_this, e, currentView, resultView, incomingView);
}
};

this.addDispose(currentView.getEditor().onMouseDown((e: IEditorMouseEvent) => handleMouseDown(e, currentView)));
this.addDispose(incomingView.getEditor().onMouseDown((e: IEditorMouseEvent) => handleMouseDown(e, incomingView)));
this.addDispose(resultView.getEditor().onMouseDown((e: IEditorMouseEvent) => handleMouseDown(e, resultView)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@ import { Injector } from '@opensumi/di';
import { MonacoService } from '@opensumi/ide-core-browser';
import { Disposable, Event } from '@opensumi/ide-core-common';
import { ICodeEditor } from '@opensumi/monaco-editor-core/esm/vs/editor/browser/editorBrowser';
import { EditorLayoutInfo } from '@opensumi/monaco-editor-core/esm/vs/editor/common/config/editorOptions';
import { EditorLayoutInfo, EditorOption } from '@opensumi/monaco-editor-core/esm/vs/editor/common/config/editorOptions';
import { Range } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/range';
import { LineRangeMapping } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/linesDiffComputer';
import { IModelDecorationOptions, ITextModel } from '@opensumi/monaco-editor-core/esm/vs/editor/common/model';
import { IStandaloneEditorConstructionOptions } from '@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneCodeEditor';

import { ConflictActions } from '../../model/conflict-actions';
import {
IDiffDecoration,
IRenderChangesInput,
IRenderInnerChangesInput,
MergeEditorDecorations,
} from '../../model/decorations';
import { LineRange } from '../../model/line-range';
import { EditorViewType } from '../../types';
import { EditorViewType, IActionsProvider, IBaseCodeEditor } from '../../types';
import { flatModified, flatOriginal } from '../../utils';
import { GuidelineWidget } from '../guideline-widget';

export abstract class BaseCodeEditor extends Disposable {
export abstract class BaseCodeEditor extends Disposable implements IBaseCodeEditor {
#actionsProvider: IActionsProvider | undefined;
#conflictActions: ConflictActions;

protected decorations: MergeEditorDecorations;
protected editor: ICodeEditor;

Expand All @@ -36,6 +40,7 @@ export abstract class BaseCodeEditor extends Disposable {
super.dispose();
this.editor.dispose();
this.decorations.dispose();
this.#conflictActions.dispose();
}

public mount(): void {
Expand All @@ -53,6 +58,7 @@ export abstract class BaseCodeEditor extends Disposable {
});

this.decorations = this.injector.get(MergeEditorDecorations, [this, this.getEditorViewType()]);
this.#conflictActions = this.injector.get(ConflictActions, [this]);

this.addDispose(
Event.debounce(
Expand All @@ -63,13 +69,15 @@ export abstract class BaseCodeEditor extends Disposable {
() => {},
0,
)(() => {
const marginWith = this.editor.getLayoutInfo().contentLeft;
const lineDecorationsWidth = this.editor.getOption(EditorOption.lineDecorationsWidth);
const contentLeft = this.editor.getLayoutInfo().contentLeft;
const marginWidth = contentLeft - (typeof lineDecorationsWidth === 'number' ? lineDecorationsWidth : 0);
const widgets = this.decorations.getLineWidgets();
if (widgets.length > 0) {
widgets.forEach((w) => {
if (w) {
w.setContainerStyle({
left: marginWith + 'px',
left: marginWidth + 'px',
});
}
});
Expand Down Expand Up @@ -150,6 +158,21 @@ export abstract class BaseCodeEditor extends Disposable {
.updateDecorations(r, i);
}

protected registerActionsProvider(provider: IActionsProvider): void {
if (this.#actionsProvider) {
return;
}

this.#actionsProvider = provider;

const { provideActionsItems } = provider;
this.#conflictActions.setActions(provideActionsItems());
}

public get actionsProvider(): IActionsProvider | undefined {
return this.#actionsProvider;
}

public clearDecorations(): void {
this.decorations.clearDecorations();
}
Expand Down
Loading