@opensumi/ide-ai-native 3.7.1-next-1739252693.0 → 3.7.1-next-1739424847.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.d.ts +1 -0
  2. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.d.ts.map +1 -1
  3. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js +26 -4
  4. package/lib/browser/contrib/intelligent-completions/intelligent-completions.contribution.js.map +1 -1
  5. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts +3 -1
  6. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.d.ts.map +1 -1
  7. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js +9 -1
  8. package/lib/browser/contrib/intelligent-completions/intelligent-completions.controller.js.map +1 -1
  9. package/lib/browser/contrib/terminal/component/terminal-command-suggest-controller.js +2 -2
  10. package/lib/browser/contrib/terminal/component/terminal-command-suggest-controller.js.map +1 -1
  11. package/lib/browser/layout/ai-layout.d.ts.map +1 -1
  12. package/lib/browser/layout/ai-layout.js +2 -2
  13. package/lib/browser/layout/ai-layout.js.map +1 -1
  14. package/lib/browser/model/enhanceDecorationsCollection.d.ts +14 -10
  15. package/lib/browser/model/enhanceDecorationsCollection.d.ts.map +1 -1
  16. package/lib/browser/model/enhanceDecorationsCollection.js +42 -53
  17. package/lib/browser/model/enhanceDecorationsCollection.js.map +1 -1
  18. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.d.ts.map +1 -1
  19. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js +1 -2
  20. package/lib/browser/widget/inline-chat/inline-chat-editor.controller.js.map +1 -1
  21. package/lib/browser/widget/inline-diff/inline-diff-previewer.d.ts +21 -5
  22. package/lib/browser/widget/inline-diff/inline-diff-previewer.d.ts.map +1 -1
  23. package/lib/browser/widget/inline-diff/inline-diff-previewer.js +40 -29
  24. package/lib/browser/widget/inline-diff/inline-diff-previewer.js.map +1 -1
  25. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts +8 -12
  26. package/lib/browser/widget/inline-diff/inline-diff.controller.d.ts.map +1 -1
  27. package/lib/browser/widget/inline-diff/inline-diff.controller.js +68 -96
  28. package/lib/browser/widget/inline-diff/inline-diff.controller.js.map +1 -1
  29. package/lib/browser/widget/inline-input/inline-input.controller.d.ts.map +1 -1
  30. package/lib/browser/widget/inline-input/inline-input.controller.js +2 -22
  31. package/lib/browser/widget/inline-input/inline-input.controller.js.map +1 -1
  32. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts +8 -19
  33. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.d.ts.map +1 -1
  34. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js +45 -40
  35. package/lib/browser/widget/inline-stream-diff/inline-stream-diff.handler.js.map +1 -1
  36. package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts +17 -4
  37. package/lib/browser/widget/inline-stream-diff/live-preview.component.d.ts.map +1 -1
  38. package/lib/browser/widget/inline-stream-diff/live-preview.component.js +37 -5
  39. package/lib/browser/widget/inline-stream-diff/live-preview.component.js.map +1 -1
  40. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.d.ts +6 -10
  41. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.d.ts.map +1 -1
  42. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.js +31 -76
  43. package/lib/browser/widget/inline-stream-diff/live-preview.decoration.js.map +1 -1
  44. package/package.json +21 -21
  45. package/src/browser/contrib/intelligent-completions/intelligent-completions.contribution.ts +29 -8
  46. package/src/browser/contrib/intelligent-completions/intelligent-completions.controller.ts +13 -1
  47. package/src/browser/contrib/terminal/component/terminal-command-suggest-controller.tsx +1 -1
  48. package/src/browser/layout/ai-layout.tsx +5 -2
  49. package/src/browser/model/enhanceDecorationsCollection.ts +62 -77
  50. package/src/browser/widget/inline-chat/inline-chat-editor.controller.ts +1 -2
  51. package/src/browser/widget/inline-diff/inline-diff-previewer.ts +50 -33
  52. package/src/browser/widget/inline-diff/inline-diff.controller.ts +90 -114
  53. package/src/browser/widget/inline-input/inline-input.controller.ts +3 -27
  54. package/src/browser/widget/inline-stream-diff/inline-stream-diff.handler.tsx +55 -68
  55. package/src/browser/widget/inline-stream-diff/live-preview.component.tsx +45 -6
  56. package/src/browser/widget/inline-stream-diff/live-preview.decoration.tsx +38 -111
  57. package/lib/browser/model/styles.module.less +0 -7
  58. package/src/browser/model/styles.module.less +0 -7
@@ -6,12 +6,18 @@ import {
6
6
  Emitter,
7
7
  Event,
8
8
  IDisposable,
9
- IEventBus,
10
9
  ReplyResponse,
11
10
  } from '@opensumi/ide-core-common';
12
- import { EditorGroupCloseEvent } from '@opensumi/ide-editor/lib/browser';
13
11
  import * as monaco from '@opensumi/ide-monaco';
14
12
  import { ICodeEditor } from '@opensumi/ide-monaco';
13
+ import {
14
+ IObservable,
15
+ ISettableObservable,
16
+ autorun,
17
+ observableFromEvent,
18
+ observableValue,
19
+ transaction,
20
+ } from '@opensumi/ide-monaco/lib/common/observable';
15
21
 
16
22
  import { BaseAIMonacoEditorController } from '../../contrib/base';
17
23
  import { EInlineDiffPreviewMode } from '../../preferences/schema';
@@ -27,6 +33,8 @@ import {
27
33
  } from './inline-diff-previewer';
28
34
  import { InlineDiffWidget } from './inline-diff-widget';
29
35
 
36
+ type IInlineDiffPreviewer = BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler>;
37
+
30
38
  export class InlineDiffController extends BaseAIMonacoEditorController {
31
39
  public static readonly ID = 'editor.contrib.ai.inline.diff';
32
40
 
@@ -38,106 +46,68 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
38
46
  return this.injector.get(PreferenceService);
39
47
  }
40
48
 
41
- private get eventBus(): IEventBus {
42
- return this.injector.get(IEventBus);
43
- }
44
-
45
49
  private readonly _onMaxLineCount = new Emitter<number>();
46
50
  public readonly onMaxLineCount: Event<number> = this._onMaxLineCount.event;
47
51
 
48
- private previewer: BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler> | undefined;
49
- private _previewerNodeStore = new Map<string, InlineStreamDiffHandler | null>();
52
+ private previewerStore: Map<string, IInlineDiffPreviewer>;
53
+ private currentPreviewer: ISettableObservable<IInlineDiffPreviewer | undefined>;
54
+ private modelChangeObs: IObservable<monaco.editor.ITextModel, unknown>;
50
55
 
51
56
  mount(): IDisposable {
57
+ this.previewerStore = new Map();
58
+ this.currentPreviewer = observableValue(this, undefined);
59
+ this.modelChangeObs = observableFromEvent<monaco.editor.ITextModel>(
60
+ this,
61
+ this.monacoEditor.onDidChangeModel,
62
+ () => this.monacoEditor.getModel()!,
63
+ );
64
+
52
65
  this.featureDisposable.addDispose(
53
- this.eventBus.on(EditorGroupCloseEvent, (e: EditorGroupCloseEvent) => {
54
- const uriString = e.payload.resource.uri.toString();
55
- const node = this.getStoredState(uriString);
66
+ autorun((reader) => {
67
+ const model = this.modelChangeObs.read(reader);
68
+ if (!model) {
69
+ return;
70
+ }
56
71
 
57
- if (node && node.previewerOptions.disposeWhenEditorClosed) {
58
- this.destroyPreviewer(uriString);
72
+ /**
73
+ * 切换到其他 model 且 previewer 未卸载时
74
+ * 保留 previewer 的实例,仅卸载 previewer 的渲染层
75
+ */
76
+ const id = model.id;
77
+ const previewer = this.currentPreviewer.read(reader);
78
+ if (previewer && previewer.modelId !== id && !previewer.disposed) {
79
+ previewer.hide();
59
80
  }
81
+
82
+ const storedPreview = this.previewerStore.get(model.id);
83
+ transaction((tx) => {
84
+ if (storedPreview && storedPreview.modelId === id) {
85
+ this.currentPreviewer.set(storedPreview, tx);
86
+ storedPreview.resume();
87
+ } else {
88
+ this.currentPreviewer.set(undefined, tx);
89
+ }
90
+ });
60
91
  }),
61
92
  );
62
93
 
63
- this.registerInlineDiffFeature(this.monacoEditor);
64
-
65
94
  return this.featureDisposable;
66
95
  }
67
96
 
68
- storeState(key: string) {
69
- if (!this.previewer) {
70
- return;
71
- }
72
-
73
- // 存储的是快照
74
- const node = this.previewer.createNodeSnapshot();
75
- if (node) {
76
- this._previewerNodeStore.set(key, node as InlineStreamDiffHandler);
77
- }
97
+ getPreviewer(): IInlineDiffPreviewer | undefined {
98
+ return this.currentPreviewer.get();
78
99
  }
79
100
 
80
- tryRestoreState(monacoEditor: monaco.ICodeEditor, key: string) {
81
- const node = this.getStoredState(key);
82
- if (!node) {
83
- return;
84
- }
85
-
86
- if (node.disposed) {
87
- this.destroyPreviewer(key);
101
+ private renderDiff(previewer: IInlineDiffPreviewer, data: ReplyResponse) {
102
+ if (!previewer) {
88
103
  return;
89
104
  }
90
105
 
91
- return this.restoreState(monacoEditor, node);
92
- }
93
-
94
- restoreState(monacoEditor: monaco.ICodeEditor, node: InlineStreamDiffHandler) {
95
- const uri = monacoEditor.getModel()?.uri;
96
-
97
- if (uri) {
98
- this.previewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor]);
99
- this.previewer.attachNode(node);
100
- this.listenPreviewer(this.previewer);
101
-
102
- const dispose = this.previewer.onDispose(() => {
103
- this.destroyPreviewer();
104
- dispose.dispose();
105
- });
106
- }
107
- }
108
-
109
- registerInlineDiffFeature(monacoEditor: monaco.ICodeEditor): void {
110
- const model = monacoEditor.getModel();
111
-
112
- this.featureDisposable.addDispose(
113
- monacoEditor.onWillChangeModel((e) => {
114
- if (!e.oldModelUrl) {
115
- return;
116
- }
117
-
118
- const urlString = e.oldModelUrl.toString();
119
- this.storeState(urlString);
120
-
121
- this.destroyPreviewer();
122
- }),
123
- );
124
-
125
- this.featureDisposable.addDispose(
126
- monacoEditor.onDidChangeModel((e) => {
127
- if (!e.newModelUrl) {
128
- return;
129
- }
130
- this.tryRestoreState(monacoEditor, e.newModelUrl.toString());
131
- }),
132
- );
106
+ previewer.onData(data);
133
107
 
134
- if (model) {
135
- this.featureDisposable.addDispose(
136
- model.onWillDispose(() => {
137
- const uriString = model.uri.toString();
138
- this.destroyPreviewer(uriString);
139
- }),
140
- );
108
+ // 仅在当前 model 中进行流式渲染
109
+ if (this.modelChangeObs.get()?.id === previewer.modelId) {
110
+ previewer.render();
141
111
  }
142
112
  }
143
113
 
@@ -154,6 +124,10 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
154
124
  const disposable = new Disposable();
155
125
 
156
126
  const previewer = this.createDiffPreviewer(monacoEditor, crossSelection, options.previewerOptions);
127
+ transaction((tx) => {
128
+ this.currentPreviewer.set(previewer, tx);
129
+ this.previewerStore.set(previewer.modelId, previewer);
130
+ });
157
131
 
158
132
  const onFinish = () => {
159
133
  previewer.layout();
@@ -168,7 +142,7 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
168
142
  disposable.addDispose([
169
143
  controller.onData((data) => {
170
144
  if (ReplyResponse.is(data)) {
171
- previewer.onData(data);
145
+ this.renderDiff(previewer, data);
172
146
  }
173
147
  }),
174
148
  controller.onError((error) => {
@@ -203,59 +177,61 @@ export class InlineDiffController extends BaseAIMonacoEditorController {
203
177
  EInlineDiffPreviewMode.inlineLive,
204
178
  );
205
179
 
206
- this.destroyPreviewer();
180
+ let previewer: IInlineDiffPreviewer;
207
181
 
208
182
  if (inlineDiffMode === EInlineDiffPreviewMode.sideBySide) {
209
- this.previewer = this.injector.get(SideBySideInlineDiffWidget, [monacoEditor]);
183
+ previewer = this.injector.get(SideBySideInlineDiffWidget, [monacoEditor]);
210
184
  } else {
211
- this.previewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor]);
185
+ previewer = this.injector.get(LiveInlineDiffPreviewer, [monacoEditor]);
212
186
  }
213
187
 
214
- this.previewer.create(selection, options);
215
- this.previewer.show(selection.startLineNumber - 1, selection.endLineNumber - selection.startLineNumber + 2);
188
+ previewer.create(selection, options);
189
+ previewer.show(selection.startLineNumber - 1, selection.endLineNumber - selection.startLineNumber + 2);
216
190
 
217
- this.listenPreviewer(this.previewer);
191
+ previewer.addDispose(previewer.onLineCount((lineCount) => this._onMaxLineCount.fire(lineCount)));
218
192
 
219
- return this.previewer;
193
+ previewer.addDispose(
194
+ Disposable.create(() => {
195
+ this.previewerStore.delete(previewer.modelId);
196
+ }),
197
+ );
198
+
199
+ return previewer;
220
200
  }
221
201
 
222
- private listenPreviewer(previewer: BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler> | undefined) {
202
+ handleAction(action: EResultKind): void {
203
+ const previewer = this.getPreviewer();
223
204
  if (!previewer) {
224
205
  return;
225
206
  }
226
207
 
227
- previewer.addDispose(previewer.onLineCount((lineCount) => this._onMaxLineCount.fire(lineCount)));
228
- }
229
-
230
- getPreviewer(): BaseInlineDiffPreviewer<InlineDiffWidget | InlineStreamDiffHandler> | undefined {
231
- return this.previewer;
232
- }
233
-
234
- getStoredState(uri: string) {
235
- return this._previewerNodeStore.get(uri);
236
- }
237
-
238
- handleAction(action: EResultKind): void {
239
- this.previewer?.handleAction(action);
208
+ previewer.handleAction(action);
240
209
  }
241
210
 
242
211
  getModifyContent() {
243
- return this.previewer?.getValue();
244
- }
212
+ const previewer = this.getPreviewer();
213
+ if (!previewer) {
214
+ return;
215
+ }
245
216
 
246
- getOriginContent() {
247
- return this.previewer?.getOriginValue();
217
+ return previewer.getValue();
248
218
  }
249
219
 
250
- destroyPreviewer(uriString?: string) {
251
- this.previewer?.dispose();
252
- this.previewer = undefined;
253
- if (uriString) {
254
- this._previewerNodeStore.delete(uriString);
220
+ getOriginContent() {
221
+ const previewer = this.getPreviewer();
222
+ if (!previewer) {
223
+ return;
255
224
  }
225
+
226
+ return previewer.getOriginValue();
256
227
  }
257
228
 
258
229
  revealFirstDiff() {
259
- this.previewer?.revealFirstDiff();
230
+ const previewer = this.getPreviewer();
231
+ if (!previewer) {
232
+ return;
233
+ }
234
+
235
+ previewer.revealFirstDiff();
260
236
  }
261
237
  }
@@ -18,7 +18,6 @@ import { ICodeEditor } from '@opensumi/ide-monaco';
18
18
  import {
19
19
  IObservable,
20
20
  ISettableObservable,
21
- autorun,
22
21
  observableFromEvent,
23
22
  observableValue,
24
23
  } from '@opensumi/ide-monaco/lib/common/observable';
@@ -101,7 +100,6 @@ export class InlineInputController extends BaseAIMonacoEditorController {
101
100
  const currentUri = this.monacoEditor.getModel()?.uri.toString();
102
101
 
103
102
  if (currentUri === resource) {
104
- this.inlineDiffController.destroyPreviewer(currentUri);
105
103
  this.hideInput();
106
104
 
107
105
  const message = localize('aiNative.inline.chat.generating.canceled');
@@ -138,27 +136,6 @@ export class InlineInputController extends BaseAIMonacoEditorController {
138
136
  }),
139
137
  );
140
138
 
141
- this.featureDisposable.addDispose(
142
- autorun((reader) => {
143
- const model = this.modelChangeObs.read(reader);
144
- if (!model) {
145
- return;
146
- }
147
-
148
- const storeData = this.inlineInputWidgetStore.get(model.id);
149
- if (!storeData) {
150
- this.hideInput();
151
- return;
152
- }
153
-
154
- if (storeData instanceof InlineInputWidgetStoreInEmptyLine) {
155
- this.showInputInEmptyLine(storeData.getPosition(), this.monacoEditor, storeData.getValue());
156
- } else if (storeData instanceof InlineInputWidgetStoreInSelection) {
157
- this.showInputInSelection(storeData.getSelection(), this.monacoEditor, storeData.getValue());
158
- }
159
- }),
160
- );
161
-
162
139
  this.featureDisposable.addDispose(this.inputDisposable);
163
140
 
164
141
  return this.featureDisposable;
@@ -430,7 +407,6 @@ export class InlineInputController extends BaseAIMonacoEditorController {
430
407
  inlineInputWidget.show({ selection: decorationSelection });
431
408
 
432
409
  this.aiNativeContextKey.inlineInputWidgetIsVisible.set(true);
433
- this.inlineDiffController.destroyPreviewer(monacoEditor.getModel()?.uri.toString());
434
410
 
435
411
  this.inputDisposable.addDispose(
436
412
  inlineInputWidget.onDispose(() => {
@@ -517,14 +493,14 @@ export class InlineInputController extends BaseAIMonacoEditorController {
517
493
  }),
518
494
  ]);
519
495
 
520
- chatResponse.listen();
521
-
522
496
  const diffPreviewer = this.inlineDiffController.showPreviewerByStream(monacoEditor, {
523
497
  crossSelection: decorationSelection,
524
498
  chatResponse,
525
499
  });
526
500
 
527
- diffPreviewer.mount(inlineInputWidget);
501
+ diffPreviewer.mountWidget(inlineInputWidget);
502
+
503
+ chatResponse.listen();
528
504
  }
529
505
  } else {
530
506
  decorationsCollection.clear();
@@ -3,6 +3,7 @@ import { Disposable, Emitter, Event, FRAME_THREE, Schemes, Uri, randomString, sl
3
3
  import { ISingleEditOperation } from '@opensumi/ide-editor';
4
4
  import { ICodeEditor, ITextModel, Range, Selection } from '@opensumi/ide-monaco';
5
5
  import { StandaloneServices } from '@opensumi/ide-monaco/lib/browser/monaco-api/services';
6
+ import { ISettableObservable, observableValue, transaction } from '@opensumi/ide-monaco/lib/common/observable';
6
7
  import { LineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/lineRange';
7
8
  import { linesDiffComputers } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/linesDiffComputers';
8
9
  import { DetailedLineRangeMapping } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/rangeMapping';
@@ -15,7 +16,7 @@ import { IDiffPreviewerOptions, IInlineDiffPreviewerNode } from '../inline-diff/
15
16
 
16
17
  import { InlineStreamDiffComputer } from './inline-stream-diff-computer';
17
18
  import { IRemovedWidgetState } from './live-preview.component';
18
- import { ILivePreviewDiffDecorationSnapshotData, LivePreviewDiffDecorationModel } from './live-preview.decoration';
19
+ import { LivePreviewDiffDecorationModel } from './live-preview.decoration';
19
20
 
20
21
  interface IRangeChangeData {
21
22
  removedTextLines: string[];
@@ -29,7 +30,7 @@ interface IRangeChangeData {
29
30
  | undefined;
30
31
  }
31
32
 
32
- interface IComputeDiffData {
33
+ export interface IComputeDiffData {
33
34
  newFullRangeTextLines: string[];
34
35
  changes: IRangeChangeData[];
35
36
  activeLine: number;
@@ -41,14 +42,6 @@ export enum EComputerMode {
41
42
  default = 'default',
42
43
  }
43
44
 
44
- export interface IInlineStreamDiffSnapshotData {
45
- rawOriginalTextLines: string[];
46
- rawOriginalTextLinesTokens: LineTokens[];
47
- undoRedoGroup: UndoRedoGroup;
48
- decorationSnapshotData: ILivePreviewDiffDecorationSnapshotData;
49
- previewerOptions: IDiffPreviewerOptions;
50
- }
51
-
52
45
  const inlineStreamDiffComputer = new InlineStreamDiffComputer();
53
46
 
54
47
  @Injectable({ multiple: true })
@@ -64,18 +57,21 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
64
57
  private originalModel: ITextModel;
65
58
  private virtualModel: ITextModel;
66
59
 
67
- // Parts that require snapshots
68
60
  private rawOriginalTextLines: string[];
69
61
  private rawOriginalTextLinesTokens: LineTokens[] = [];
70
- private undoRedoGroup: UndoRedoGroup;
62
+ private undoRedoGroup: UndoRedoGroup = new UndoRedoGroup();
63
+
64
+ private readonly diffModel: ISettableObservable<IComputeDiffData | undefined> = observableValue(this, undefined);
65
+ private readonly finallyDiffModel: ISettableObservable<IComputeDiffData | undefined> = observableValue(
66
+ this,
67
+ undefined,
68
+ );
71
69
 
72
70
  public livePreviewDiffDecorationModel: LivePreviewDiffDecorationModel;
73
71
 
74
72
  constructor(private readonly monacoEditor: ICodeEditor) {
75
73
  super();
76
74
 
77
- this.undoRedoGroup = new UndoRedoGroup();
78
-
79
75
  const modelService = StandaloneServices.get(IModelService);
80
76
  this.virtualModel = modelService.createModel(
81
77
  '',
@@ -136,44 +132,6 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
136
132
  this.livePreviewDiffDecorationModel.initialize(zone);
137
133
  }
138
134
 
139
- private _snapshotStore: IInlineStreamDiffSnapshotData | undefined;
140
- restoreSnapshot(snapshot: IInlineStreamDiffSnapshotData): void {
141
- this._snapshotStore = snapshot;
142
- const {
143
- rawOriginalTextLines,
144
- rawOriginalTextLinesTokens,
145
- undoRedoGroup,
146
- decorationSnapshotData,
147
- previewerOptions,
148
- } = snapshot;
149
-
150
- this.setPreviewerOptions(previewerOptions);
151
-
152
- this.rawOriginalTextLines = rawOriginalTextLines;
153
- this.rawOriginalTextLinesTokens = rawOriginalTextLinesTokens;
154
- this.undoRedoGroup = undoRedoGroup;
155
-
156
- this.livePreviewDiffDecorationModel.initialize(decorationSnapshotData.zone);
157
- }
158
-
159
- get currentSnapshotStore(): IInlineStreamDiffSnapshotData | undefined {
160
- return this._snapshotStore;
161
- }
162
-
163
- restoreDecorationSnapshot(decorationSnapshotData: ILivePreviewDiffDecorationSnapshotData): void {
164
- this.livePreviewDiffDecorationModel.restoreSnapshot(decorationSnapshotData);
165
- }
166
-
167
- createSnapshot(): IInlineStreamDiffSnapshotData {
168
- return {
169
- rawOriginalTextLines: this.rawOriginalTextLines,
170
- rawOriginalTextLinesTokens: this.rawOriginalTextLinesTokens,
171
- undoRedoGroup: this.undoRedoGroup,
172
- decorationSnapshotData: this.livePreviewDiffDecorationModel.createSnapshot(),
173
- previewerOptions: this.previewerOptions,
174
- };
175
- }
176
-
177
135
  getVirtualModelValue() {
178
136
  return this.virtualModel.getValue();
179
137
  }
@@ -345,7 +303,7 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
345
303
  });
346
304
  }
347
305
 
348
- private handleEdits(diffModel: IComputeDiffData): void {
306
+ private renderDiffEdits(diffModel: IComputeDiffData): void {
349
307
  const { activeLine, newFullRangeTextLines, pendingRange } = diffModel;
350
308
  const eol = this.originalModel.getEOL();
351
309
  const zone = this.getZone();
@@ -466,9 +424,8 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
466
424
  }
467
425
 
468
426
  private currentEditLine = 0;
469
- private finallyDiffModel: IComputeDiffData | null = null;
470
427
  private isEditing = false;
471
- private async rateEditController(): Promise<void> {
428
+ public async rateRenderEditController(): Promise<void> {
472
429
  if (this.isEditing === false) {
473
430
  this.isEditing = true;
474
431
 
@@ -480,15 +437,22 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
480
437
  const virtualTextLines = this.virtualModel.getLinesContent();
481
438
  const currentText = virtualTextLines.slice(0, this.currentEditLine);
482
439
  const currentDiffModel = this.computeDiff(this.rawOriginalTextLines, currentText);
483
- this.handleEdits(currentDiffModel);
440
+ transaction((tx) => {
441
+ this.diffModel.set(currentDiffModel, tx);
442
+ });
443
+
444
+ if (this.originalModel.id === this.monacoEditor.getModel()?.id) {
445
+ this.renderDiffEdits(currentDiffModel);
446
+ }
484
447
 
485
448
  this.currentEditLine += 1;
486
449
 
487
450
  await sleep(FRAME_THREE);
488
451
  }
489
452
 
490
- if (this.finallyDiffModel) {
491
- this.finallyRender(this.finallyDiffModel);
453
+ const finallyDiffModel = this.finallyDiffModel.get();
454
+ if (finallyDiffModel) {
455
+ this.finallyRender(finallyDiffModel);
492
456
  }
493
457
 
494
458
  this.isEditing = false;
@@ -496,27 +460,50 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
496
460
  }
497
461
 
498
462
  public addLinesToDiff(newText: string, computerMode: EComputerMode = EComputerMode.default): void {
499
- this.recompute(computerMode, newText);
500
- this.rateEditController();
463
+ const diffModel = this.recompute(computerMode, newText);
464
+ transaction((tx) => {
465
+ this.diffModel.set(diffModel, tx);
466
+ });
501
467
  }
502
468
 
503
469
  public pushRateFinallyDiffStack(diffModel: IComputeDiffData): void {
504
- this.finallyDiffModel = diffModel;
505
-
506
- // 可能存在 rate editr controller 处理完之后接口层流式才结束
507
- if (this.isEditing === false) {
508
- this.finallyRender(this.finallyDiffModel);
509
- }
470
+ transaction((tx) => {
471
+ this.finallyDiffModel.set(diffModel, tx);
472
+ // 可能存在 rate editor controller 处理完之后接口层流式才结束
473
+ if (this.isEditing === false) {
474
+ this.finallyRender(diffModel);
475
+ }
476
+ });
510
477
  }
511
478
 
512
479
  public finallyRender(diffModel: IComputeDiffData): void {
513
- // 流式结束后才会确定所有的 added range,再渲染 partial edit widgets
480
+ transaction((tx) => {
481
+ this.diffModel.set(diffModel, tx);
482
+ });
483
+
484
+ if (this.originalModel.id !== this.monacoEditor.getModel()?.id) {
485
+ return;
486
+ }
487
+
514
488
  this.renderPartialEditWidgets(diffModel);
515
- this.handleEdits(diffModel);
489
+ this.renderDiffEdits(diffModel);
516
490
  this.pushStackElement();
517
491
  this.monacoEditor.focus();
518
492
  }
519
493
 
494
+ public hide(): void {
495
+ this.livePreviewDiffDecorationModel.hide();
496
+ }
497
+
498
+ public resume(): void {
499
+ const finallyDiffModel = this.finallyDiffModel.get();
500
+ if (!finallyDiffModel) {
501
+ this.rateRenderEditController();
502
+ }
503
+
504
+ this.livePreviewDiffDecorationModel.resume();
505
+ }
506
+
520
507
  acceptAll(): void {
521
508
  this.livePreviewDiffDecorationModel.acceptUnProcessed();
522
509
  this.dispose();
@@ -21,6 +21,11 @@ import { LineTokens } from '@opensumi/monaco-editor-core/esm/vs/editor/common/to
21
21
  import { IOptions, ZoneWidget } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/zoneWidget/browser/zoneWidget';
22
22
  import { UndoRedoGroup } from '@opensumi/monaco-editor-core/esm/vs/platform/undoRedo/common/undoRedo';
23
23
 
24
+ import {
25
+ DeltaDecorations,
26
+ EnhanceDecorationsCollection,
27
+ IDeltaDecorationsOptions,
28
+ } from '../../model/enhanceDecorationsCollection';
24
29
  import { renderLines } from '../ghost-text-widget/index';
25
30
 
26
31
  import styles from './inline-stream-diff.module.less';
@@ -34,7 +39,7 @@ interface IPartialEditWidgetComponent {
34
39
  discardSequence: string;
35
40
  }
36
41
 
37
- export type IWidgetStatus = 'accept' | 'discard' | 'pending';
42
+ type IWidgetStatus = 'accept' | 'discard' | 'pending';
38
43
 
39
44
  export interface IRemovedWidgetState {
40
45
  textLines: ITextLinesTokens[];
@@ -141,7 +146,7 @@ export class AcceptPartialEditWidget extends ReactInlineContentWidget {
141
146
  private readonly keybindingRegistry: KeybindingRegistry;
142
147
 
143
148
  private _id: string;
144
- private _decorationId: string;
149
+ private _addedRangeId: string;
145
150
 
146
151
  private readonly _onAccept = this.registerDispose(new Emitter<void>());
147
152
  public readonly onAccept: Event<void> = this._onAccept.event;
@@ -209,12 +214,12 @@ export class AcceptPartialEditWidget extends ReactInlineContentWidget {
209
214
  return styles.accept_partial_edit_widget_id;
210
215
  }
211
216
 
212
- public recordDecorationId(id: string): void {
213
- this._decorationId = id;
217
+ public recordAddedRangeId(id: string): void {
218
+ this._addedRangeId = id;
214
219
  }
215
220
 
216
- public getDecorationId(): string {
217
- return this._decorationId;
221
+ public getAddedRangeId(): string {
222
+ return this._addedRangeId;
218
223
  }
219
224
 
220
225
  public resume(): void {
@@ -314,6 +319,8 @@ export class RemovedZoneWidget extends ZoneWidget {
314
319
  return this._group;
315
320
  }
316
321
 
322
+ public status: IWidgetStatus = 'pending';
323
+
317
324
  constructor(editor: ICodeEditor, public readonly textLines: ITextLinesTokens[], options: IRemovedZoneWidgetOptions) {
318
325
  super(editor, options);
319
326
 
@@ -362,12 +369,23 @@ export class RemovedZoneWidget extends ZoneWidget {
362
369
  return this.position || this._recordPosition;
363
370
  }
364
371
 
372
+ accept(): void {
373
+ this.status = 'accept';
374
+ this.hide();
375
+ }
376
+
377
+ discard(): void {
378
+ this.status = 'discard';
379
+ super.hide();
380
+ }
381
+
365
382
  hide(): void {
366
383
  this._hidden = true;
367
384
  super.hide();
368
385
  }
369
386
 
370
387
  resume(): void {
388
+ this.status = 'pending';
371
389
  const position = this.getLastPosition();
372
390
  if (position) {
373
391
  this.show(position, this.height);
@@ -376,6 +394,7 @@ export class RemovedZoneWidget extends ZoneWidget {
376
394
 
377
395
  override show(pos: IPosition, heightInLines: number): void {
378
396
  this._hidden = false;
397
+ this.status = 'pending';
379
398
  super.show(pos, heightInLines);
380
399
  }
381
400
 
@@ -407,3 +426,23 @@ export class RemovedZoneWidget extends ZoneWidget {
407
426
  super.dispose();
408
427
  }
409
428
  }
429
+
430
+ class AddedRangeDeltaDecorations extends DeltaDecorations {
431
+ public status: IWidgetStatus = 'pending';
432
+
433
+ accept(): void {
434
+ this.status = 'accept';
435
+ super.hide();
436
+ }
437
+
438
+ discard(): void {
439
+ this.status = 'discard';
440
+ super.hide();
441
+ }
442
+ }
443
+
444
+ export class AddedRangeDecorationsCollection extends EnhanceDecorationsCollection<AddedRangeDeltaDecorations> {
445
+ protected override createDecorations(metaData: IDeltaDecorationsOptions) {
446
+ return new AddedRangeDeltaDecorations(metaData);
447
+ }
448
+ }