Skip to content

Commit 2881790

Browse files
committed
feat: show title head info & implement the apply actions (#2095)
* feat: implement title head & fix scroll & keep view state * feat: implement apply action * fix: time machine record * docs: apply button i18n * chore: improve code
1 parent 19b1811 commit 2881790

15 files changed

Lines changed: 438 additions & 91 deletions

File tree

packages/core-browser/src/monaco/merge-editor-widget.ts

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ export interface IMergeEditorEditor extends IEditor {
88
getResultEditor(): ICodeEditor;
99
getTheirsEditor(): ICodeEditor;
1010
open(openMergeEditorArgs: IOpenMergeEditorArgs): Promise<void>;
11-
compare(): Promise<void>;
1211
}
1312

14-
export class MergeEditorInputData {
13+
export interface IMergeEditorInputData {
14+
uri: URI;
15+
title?: string;
16+
detail?: string; // 分支名
17+
description?: string; // commit
18+
}
19+
20+
export class MergeEditorInputData implements IMergeEditorInputData {
1521
static from(data: string): MergeEditorInputData {
1622
try {
1723
const obj: MergeEditorInputData = JSON.parse(data);
18-
return new MergeEditorInputData(obj.uri, obj.detail, obj.description);
24+
return new MergeEditorInputData(obj.uri, obj.title, obj.detail, obj.description);
1925
} catch (error) {
2026
throw Error('invalid MergeEditorInputData parse');
2127
}
@@ -26,11 +32,26 @@ export class MergeEditorInputData {
2632
return this._textModel;
2733
}
2834

29-
constructor(readonly uri: URI, readonly detail?: string | undefined, readonly description?: string | undefined) {}
35+
constructor(
36+
readonly uri: URI,
37+
readonly title?: string,
38+
readonly detail?: string | undefined,
39+
readonly description?: string | undefined,
40+
) {}
41+
42+
public getRaw(): IMergeEditorInputData {
43+
return {
44+
uri: this.uri,
45+
title: this.title,
46+
detail: this.detail,
47+
description: this.description,
48+
};
49+
}
3050

3151
public toString(): string {
3252
return JSON.stringify({
3353
uri: this.uri.toString(),
54+
title: this.title,
3455
detail: this.detail,
3556
description: this.description,
3657
});
@@ -71,8 +92,14 @@ export namespace IRelaxedOpenMergeEditorArgs {
7192
const obj = args as IValidateOpenArgs;
7293
const ancestor = toUri(obj.ancestor);
7394
const output = toUri(obj.output);
74-
const input1 = toInputData(obj.input1);
75-
const input2 = toInputData(obj.input2);
95+
const input1 = toInputData({
96+
...obj.input1,
97+
title: obj.input1.title ?? 'Current',
98+
});
99+
const input2 = toInputData({
100+
...obj.input2,
101+
title: obj.input2.title ?? 'Incoming',
102+
});
76103
return { ancestor, input1, input2, output };
77104
};
78105

@@ -89,21 +116,22 @@ export namespace IRelaxedOpenMergeEditorArgs {
89116

90117
const toInputData = (args: unknown): MergeEditorInputData => {
91118
if (typeof args === 'string') {
92-
return new MergeEditorInputData(URI.parse(args), undefined, undefined);
119+
return new MergeEditorInputData(URI.parse(args));
93120
}
94121
if (!args || typeof args !== 'object') {
95122
throw new TypeError('invalid argument');
96123
}
97124

98125
if (isUriComponents(args)) {
99-
return new MergeEditorInputData(URI.from(args), undefined, undefined);
126+
return new MergeEditorInputData(URI.from(args));
100127
}
101128

102129
const obj = args as MergeEditorInputData;
103130
const uri = toUri(obj.uri);
131+
const title = obj.title;
104132
const detail = obj.detail;
105133
const description = obj.description;
106-
return new MergeEditorInputData(uri, detail, description);
134+
return new MergeEditorInputData(uri, title, detail, description);
107135
};
108136

109137
const toUri = (args: unknown): URI => {

packages/i18n/src/common/en-US.lang.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,11 @@ export const localizationBundle = {
10191019

10201020
// #region merge editor
10211021
'mergeEditor.workbench.tab.name': 'Merging: {0}',
1022+
'mergeEditor.conflict.action.apply.confirm.title':
1023+
'The file has unresolved conflicts or changes, whether to apply and save the changes?',
1024+
'mergeEditor.conflict.action.apply.confirm.continue': 'Continue Merge',
1025+
'mergeEditor.conflict.action.apply.confirm.complete': 'Apply Changes',
1026+
'mergeEditor.button.apply': 'Apply',
10221027
// #endregion merge editor
10231028
...browserViews,
10241029
},

packages/i18n/src/common/zh-CN.lang.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,10 @@ export const localizationBundle = {
10611061

10621062
// #region merge editor
10631063
'mergeEditor.workbench.tab.name': '正在合并: {0}',
1064+
'mergeEditor.conflict.action.apply.confirm.title': '当前文件还有未处理的冲突或变更,是否应用并保存更改?',
1065+
'mergeEditor.conflict.action.apply.confirm.continue': '继续合并',
1066+
'mergeEditor.conflict.action.apply.confirm.complete': '确认保存并更改',
1067+
'mergeEditor.button.apply': '应用更改',
10641068
// #endregion merge editor
10651069
...browserViews,
10661070
},

packages/monaco/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@opensumi/ide-dev-tool": "^1.3.1",
2222
"@opensumi/ide-file-service": "2.21.10",
2323
"@opensumi/ide-theme": "2.21.10",
24-
"@opensumi/ide-workspace": "2.21.10"
24+
"@opensumi/ide-workspace": "2.21.10",
25+
"@opensumi/ide-overlay": "2.21.10"
2526
}
2627
}

packages/monaco/src/browser/contrib/merge-editor/mapping-manager.service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ export class MappingManagerService extends Disposable {
100100
this.revokeActionsFactory(EDiffRangeTurn.MODIFIED)(oppositeRange);
101101
}
102102

103+
public clearMapping(): void {
104+
this.documentMappingTurnLeft.clear();
105+
this.documentMappingTurnRight.clear();
106+
}
107+
103108
/**
104109
* 分别找出离目标 lineRange 最近的 documentMappingTurnLeft 和 documentMappingTurnRight 里的 lineRange
105110
* 其中 target 只能是 result view 视图中的 range

packages/monaco/src/browser/contrib/merge-editor/merge-editor-widget.tsx

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ReactDOM from 'react-dom';
44
import { Injectable, Autowired } from '@opensumi/di';
55
import { AppConfig, ConfigProvider } from '@opensumi/ide-core-browser';
66
import { IMergeEditorEditor, IOpenMergeEditorArgs } from '@opensumi/ide-core-browser/lib/monaco/merge-editor-widget';
7-
import { Disposable, IRange, ISelection } from '@opensumi/ide-core-common';
7+
import { Disposable, IRange, ISelection, URI } from '@opensumi/ide-core-common';
88
import { Selection } from '@opensumi/monaco-editor-core';
99
import { IDisposable } from '@opensumi/monaco-editor-core/esm/vs/base/common/lifecycle';
1010
import { IDimension } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/dimension';
@@ -21,6 +21,7 @@ import { ICodeEditor, IDiffEditorOptions, IEditorOptions, IModelDeltaDecoration
2121
import { IPosition, Position } from '../../monaco-api/types';
2222

2323
import { MergeEditorService } from './merge-editor.service';
24+
import { EditorViewType, IMergeEditorViewState } from './types';
2425
import { Grid } from './view/grid';
2526

2627
export interface IMergeEditorModel {
@@ -43,6 +44,8 @@ export class MergeEditorWidget extends Disposable implements IMergeEditorEditor
4344
private readonly mergeEditorService: MergeEditorService;
4445

4546
private readonly _id: number;
47+
private readonly viewStateMap: Map<string, IMergeEditorViewState> = new Map();
48+
private outputUri: URI | undefined;
4649

4750
constructor(
4851
private readonly rootHtmlElement: HTMLElement,
@@ -56,23 +59,35 @@ export class MergeEditorWidget extends Disposable implements IMergeEditorEditor
5659
this.layout();
5760
}
5861

59-
open({ ancestor, input1, input2 }: IOpenMergeEditorArgs): Promise<void> {
62+
async open(args: IOpenMergeEditorArgs): Promise<void> {
63+
const { ancestor, input1, input2, output } = args;
64+
this.mergeEditorService.setNutritionAndLaunch(args);
65+
66+
// 保存上一次状态
67+
this.saveViewState(this.outputUri);
68+
69+
this.outputUri = output.uri;
70+
const uniqueKey = this.outputUri.toString();
71+
6072
this.setModel({
6173
ours: input1.textModel as ITextModel,
6274
result: ancestor.textModel as ITextModel,
6375
theirs: input2.textModel as ITextModel,
6476
});
6577

66-
this.compare();
78+
if (this.viewStateMap.has(uniqueKey)) {
79+
const state = this.viewStateMap.get(uniqueKey)!;
80+
this.restoreViewState(state);
81+
const { turnLeft, turnRight } = state;
82+
await this.mergeEditorService.compare(turnLeft, turnRight);
83+
} else {
84+
await this.mergeEditorService.compare();
85+
}
6786

68-
this.mergeEditorService.updateOptions(this.options);
87+
this.updateOptions(this.options);
6988
return Promise.resolve();
7089
}
7190

72-
compare(): Promise<void> {
73-
return this.mergeEditorService.compare();
74-
}
75-
7691
getOursEditor(): ICodeEditor {
7792
return this.mergeEditorService.getCurrentEditor()!;
7893
}
@@ -101,7 +116,9 @@ export class MergeEditorWidget extends Disposable implements IMergeEditorEditor
101116
return 'MERGE_EDITOR_DIFF';
102117
}
103118

104-
updateOptions(newOptions: IEditorOptions): void {}
119+
updateOptions(newOptions: IEditorOptions): void {
120+
this.mergeEditorService.updateOptions(newOptions);
121+
}
105122

106123
onVisible(): void {}
107124

@@ -126,11 +143,33 @@ export class MergeEditorWidget extends Disposable implements IMergeEditorEditor
126143
return [];
127144
}
128145

129-
saveViewState(): IEditorViewState | null {
146+
saveViewState(uri?: URI): IEditorViewState | null {
147+
if (!uri) {
148+
return null;
149+
}
150+
151+
const key = uri.toString();
152+
this.viewStateMap.set(key, {
153+
[EditorViewType.CURRENT]: this.getOursEditor().saveViewState(),
154+
[EditorViewType.RESULT]: this.getResultEditor().saveViewState(),
155+
[EditorViewType.INCOMING]: this.getTheirsEditor().saveViewState(),
156+
turnLeft: this.mergeEditorService.getTurnLeftRangeMapping(),
157+
turnRight: this.mergeEditorService.getTurnRightRangeMapping(),
158+
});
130159
return null;
131160
}
132161

133-
restoreViewState(state: IEditorViewState | null): void {}
162+
restoreViewState(state: IMergeEditorViewState | IEditorViewState | null): void {
163+
const {
164+
[EditorViewType.CURRENT]: current,
165+
[EditorViewType.RESULT]: result,
166+
[EditorViewType.INCOMING]: incoming,
167+
} = state as IMergeEditorViewState;
168+
169+
this.getOursEditor().restoreViewState(current);
170+
this.getResultEditor().restoreViewState(result);
171+
this.getTheirsEditor().restoreViewState(incoming);
172+
}
134173

135174
getVisibleColumnFromPosition(position: IPosition): number {
136175
return 1;

0 commit comments

Comments
 (0)