Skip to content

Commit b3f2337

Browse files
authored
joh/icy manatee (microsoft#183917)
* Use idle value for widget of interactive editor controller microsoft#183820 * also make preview editors idle values microsoft#183820
1 parent 2a8dea3 commit b3f2337

File tree

2 files changed

+59
-58
lines changed

2 files changed

+59
-58
lines changed

src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController.ts

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
7-
import { Barrier, raceCancellationError } from 'vs/base/common/async';
7+
import { Barrier, IdleValue, raceCancellationError } from 'vs/base/common/async';
88
import { CancellationTokenSource } from 'vs/base/common/cancellation';
99
import { toErrorMessage } from 'vs/base/common/errorMessage';
1010
import { Emitter, Event } from 'vs/base/common/event';
@@ -86,7 +86,7 @@ export class InteractiveEditorController implements IEditorContribution {
8686
private _historyOffset: number = -1;
8787

8888
private readonly _store = new DisposableStore();
89-
private readonly _zone: InteractiveEditorZoneWidget;
89+
private readonly _zone: IdleValue<InteractiveEditorZoneWidget>;
9090
private readonly _ctxHasActiveRequest: IContextKey<boolean>;
9191
private readonly _ctxLastResponseType: IContextKey<undefined | InteractiveEditorResponseType>;
9292
private readonly _ctxDidEdit: IContextKey<boolean>;
@@ -118,7 +118,7 @@ export class InteractiveEditorController implements IEditorContribution {
118118
this._ctxDidEdit = CTX_INTERACTIVE_EDITOR_DID_EDIT.bindTo(contextKeyService);
119119
this._ctxLastResponseType = CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.bindTo(contextKeyService);
120120
this._ctxLastFeedbackKind = CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK.bindTo(contextKeyService);
121-
this._zone = this._store.add(_instaService.createInstance(InteractiveEditorZoneWidget, this._editor));
121+
this._zone = new IdleValue(() => this._store.add(_instaService.createInstance(InteractiveEditorZoneWidget, this._editor)));
122122

123123
this._store.add(this._editor.onDidChangeModel(async e => {
124124
if (this._activeSession || !e.newModelUrl) {
@@ -167,7 +167,7 @@ export class InteractiveEditorController implements IEditorContribution {
167167
}
168168

169169
getWidgetPosition(): Position | undefined {
170-
return this._zone.position;
170+
return this._zone.value.position;
171171
}
172172

173173
async run(options: InteractiveEditorRunOptions | undefined): Promise<void> {
@@ -234,14 +234,14 @@ export class InteractiveEditorController implements IEditorContribution {
234234

235235
switch (session.editMode) {
236236
case EditMode.Live:
237-
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.widget);
237+
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget);
238238
break;
239239
case EditMode.Preview:
240-
this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.widget);
240+
this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.value.widget);
241241
break;
242242
case EditMode.LivePreview:
243243
default:
244-
this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.widget);
244+
this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value.widget);
245245
break;
246246
}
247247

@@ -265,11 +265,11 @@ export class InteractiveEditorController implements IEditorContribution {
265265
}]);
266266
this._sessionStore.add(toDisposable(() => wholeRangeDecoration.clear()));
267267

268-
this._zone.widget.updateSlashCommands(this._activeSession.session.slashCommands ?? []);
269-
this._zone.widget.placeholder = this._getPlaceholderText();
270-
this._zone.widget.value = this._activeSession.lastInput ?? '';
271-
this._zone.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect"));
272-
this._zone.show(this._activeSession.wholeRange.getEndPosition());
268+
this._zone.value.widget.updateSlashCommands(this._activeSession.session.slashCommands ?? []);
269+
this._zone.value.widget.placeholder = this._getPlaceholderText();
270+
this._zone.value.widget.value = this._activeSession.lastInput ?? '';
271+
this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect"));
272+
this._zone.value.show(this._activeSession.wholeRange.getEndPosition());
273273

274274
this._sessionStore.add(this._editor.onDidChangeModel((e) => {
275275
const msg = this._activeSession?.lastExchange
@@ -357,12 +357,12 @@ export class InteractiveEditorController implements IEditorContribution {
357357
private async [State.WAIT_FOR_INPUT](options: InteractiveEditorRunOptions | undefined): Promise<State.ACCEPT | State.CANCEL | State.PAUSE | State.WAIT_FOR_INPUT | State.MAKE_REQUEST> {
358358
assertType(this._activeSession);
359359

360-
this._zone.widget.placeholder = this._getPlaceholderText();
361-
this._zone.show(this._activeSession.wholeRange.getEndPosition());
360+
this._zone.value.widget.placeholder = this._getPlaceholderText();
361+
this._zone.value.show(this._activeSession.wholeRange.getEndPosition());
362362

363363
if (options?.message) {
364-
this._zone.widget.value = options?.message;
365-
this._zone.widget.selectAll();
364+
this._zone.value.widget.value = options?.message;
365+
this._zone.value.widget.selectAll();
366366
delete options?.message;
367367
}
368368

@@ -382,7 +382,7 @@ export class InteractiveEditorController implements IEditorContribution {
382382
msgListener.dispose();
383383
}
384384

385-
this._zone.widget.selectAll();
385+
this._zone.value.widget.selectAll();
386386

387387
if (message & (Message.CANCEL_INPUT | Message.CANCEL_SESSION)) {
388388
return State.CANCEL;
@@ -396,11 +396,11 @@ export class InteractiveEditorController implements IEditorContribution {
396396
return State.PAUSE;
397397
}
398398

399-
if (!this._zone.widget.value) {
399+
if (!this._zone.value.widget.value) {
400400
return State.WAIT_FOR_INPUT;
401401
}
402402

403-
const input = this._zone.widget.value;
403+
const input = this._zone.value.widget.value;
404404

405405
if (!InteractiveEditorController._promptHistory.includes(input)) {
406406
InteractiveEditorController._promptHistory.unshift(input);
@@ -437,7 +437,7 @@ export class InteractiveEditorController implements IEditorContribution {
437437
requestCts.cancel();
438438
});
439439

440-
const typeListener = this._zone.widget.onDidChangeInput(() => {
440+
const typeListener = this._zone.value.widget.onDidChangeInput(() => {
441441
requestCts.cancel();
442442
});
443443

@@ -454,8 +454,8 @@ export class InteractiveEditorController implements IEditorContribution {
454454
let response: EditResponse | MarkdownResponse | ErrorResponse | EmptyResponse;
455455
let reply: IInteractiveEditorResponse | null | undefined;
456456
try {
457-
this._zone.widget.updateProgress(true);
458-
this._zone.widget.updateInfo(!this._activeSession.lastExchange ? localize('thinking', "Thinking\u2026") : '');
457+
this._zone.value.widget.updateProgress(true);
458+
this._zone.value.widget.updateInfo(!this._activeSession.lastExchange ? localize('thinking', "Thinking\u2026") : '');
459459
this._ctxHasActiveRequest.set(true);
460460
reply = await raceCancellationError(Promise.resolve(task), requestCts.token);
461461

@@ -472,8 +472,8 @@ export class InteractiveEditorController implements IEditorContribution {
472472

473473
} finally {
474474
this._ctxHasActiveRequest.set(false);
475-
this._zone.widget.updateProgress(false);
476-
this._zone.widget.updateInfo('');
475+
this._zone.value.widget.updateProgress(false);
476+
this._zone.value.widget.updateInfo('');
477477
this._log('request took', sw.elapsed(), this._activeSession.provider.debugName);
478478

479479
}
@@ -500,7 +500,7 @@ export class InteractiveEditorController implements IEditorContribution {
500500
const { response } = this._activeSession.lastExchange!;
501501
if (response instanceof EditResponse) {
502502
// edit response -> complex...
503-
this._zone.widget.updateMarkdownMessage(undefined);
503+
this._zone.value.widget.updateMarkdownMessage(undefined);
504504

505505
const canContinue = this._strategy.checkChanges(response);
506506
if (!canContinue) {
@@ -540,27 +540,27 @@ export class InteractiveEditorController implements IEditorContribution {
540540

541541
if (response instanceof EmptyResponse) {
542542
// show status message
543-
this._zone.widget.updateStatus(localize('empty', "No results, please refine your input and try again"), { classes: ['warn'] });
543+
this._zone.value.widget.updateStatus(localize('empty', "No results, please refine your input and try again"), { classes: ['warn'] });
544544
return State.WAIT_FOR_INPUT;
545545

546546
} else if (response instanceof ErrorResponse) {
547547
// show error
548548
if (!response.isCancellation) {
549-
this._zone.widget.updateStatus(response.message, { classes: ['error'] });
549+
this._zone.value.widget.updateStatus(response.message, { classes: ['error'] });
550550
}
551551

552552
} else if (response instanceof MarkdownResponse) {
553553
// clear status, show MD message
554554
const renderedMarkdown = renderMarkdown(response.raw.message, { inline: true });
555-
this._zone.widget.updateStatus('');
556-
this._zone.widget.updateMarkdownMessage(renderedMarkdown.element);
557-
this._zone.widget.updateToolbar(true);
558-
this._zone.widget.updateMarkdownMessageExpansionState(this._activeSession.lastExpansionState);
555+
this._zone.value.widget.updateStatus('');
556+
this._zone.value.widget.updateMarkdownMessage(renderedMarkdown.element);
557+
this._zone.value.widget.updateToolbar(true);
558+
this._zone.value.widget.updateMarkdownMessageExpansionState(this._activeSession.lastExpansionState);
559559

560560
} else if (response instanceof EditResponse) {
561561
// edit response -> complex...
562-
this._zone.widget.updateMarkdownMessage(undefined);
563-
this._zone.widget.updateToolbar(true);
562+
this._zone.value.widget.updateMarkdownMessage(undefined);
563+
this._zone.value.widget.updateToolbar(true);
564564

565565
const canContinue = this._strategy.checkChanges(response);
566566
if (!canContinue) {
@@ -586,7 +586,7 @@ export class InteractiveEditorController implements IEditorContribution {
586586
this._ctxLastResponseType.reset();
587587
this._ctxLastFeedbackKind.reset();
588588

589-
this._zone.hide();
589+
this._zone.value.hide();
590590

591591
// Return focus to the editor only if the current focus is within the editor widget
592592
if (this._editor.hasWidgetFocus()) {
@@ -627,9 +627,9 @@ export class InteractiveEditorController implements IEditorContribution {
627627
}
628628

629629
arrowOut(up: boolean): void {
630-
if (this._zone.position && this._editor.hasModel()) {
630+
if (this._zone.value.position && this._editor.hasModel()) {
631631
const { column } = this._editor.getPosition();
632-
const { lineNumber } = this._zone.position;
632+
const { lineNumber } = this._zone.value.position;
633633
const newLine = up ? lineNumber : lineNumber + 1;
634634
this._editor.setPosition({ lineNumber: newLine, column });
635635
this._editor.focus();
@@ -641,7 +641,7 @@ export class InteractiveEditorController implements IEditorContribution {
641641
}
642642

643643
focus(): void {
644-
this._zone.widget.focus();
644+
this._zone.value.widget.focus();
645645
}
646646

647647
populateHistory(up: boolean) {
@@ -652,8 +652,8 @@ export class InteractiveEditorController implements IEditorContribution {
652652
const pos = (len + this._historyOffset + (up ? 1 : -1)) % len;
653653
const entry = InteractiveEditorController._promptHistory[pos];
654654

655-
this._zone.widget.value = entry;
656-
this._zone.widget.selectAll();
655+
this._zone.value.widget.value = entry;
656+
this._zone.value.widget.selectAll();
657657
this._historyOffset = pos;
658658
}
659659

@@ -665,7 +665,7 @@ export class InteractiveEditorController implements IEditorContribution {
665665

666666
updateExpansionState(expand: boolean) {
667667
if (this._activeSession) {
668-
this._zone.widget.updateMarkdownMessageExpansionState(expand);
668+
this._zone.value.widget.updateMarkdownMessageExpansionState(expand);
669669
this._activeSession.lastExpansionState = expand;
670670
}
671671
}
@@ -675,7 +675,7 @@ export class InteractiveEditorController implements IEditorContribution {
675675
const kind = helpful ? InteractiveEditorResponseFeedbackKind.Helpful : InteractiveEditorResponseFeedbackKind.Unhelpful;
676676
this._activeSession.provider.handleInteractiveEditorResponseFeedback?.(this._activeSession.session, this._activeSession.lastExchange.response.raw, kind);
677677
this._ctxLastFeedbackKind.set(helpful ? 'helpful' : 'unhelpful');
678-
this._zone.widget.updateStatus('Thank you for your feedback!', { resetAfter: 1250 });
678+
this._zone.value.widget.updateStatus('Thank you for your feedback!', { resetAfter: 1250 });
679679
}
680680
}
681681

src/vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
5050
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
5151
import { assertType } from 'vs/base/common/types';
5252
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
53+
import { IdleValue } from 'vs/base/common/async';
5354

5455
const defaultAriaLabel = localize('aria-label', "Interactive Editor Input");
5556

@@ -160,11 +161,11 @@ export class InteractiveEditorWidget {
160161

161162
private readonly _progressBar: ProgressBar;
162163

163-
private readonly _previewDiffEditor: EmbeddedDiffEditorWidget;
164+
private readonly _previewDiffEditor: IdleValue<EmbeddedDiffEditorWidget>;
164165
private readonly _previewDiffModel = this._store.add(new MutableDisposable());
165166

166167
private readonly _previewCreateTitle: ResourceLabel;
167-
private readonly _previewCreateEditor: ICodeEditor;
168+
private readonly _previewCreateEditor: IdleValue<ICodeEditor>;
168169
private readonly _previewCreateModel = this._store.add(new MutableDisposable());
169170

170171
private readonly _onDidChangeHeight = new MicrotaskEmitter<void>();
@@ -327,10 +328,10 @@ export class InteractiveEditorWidget {
327328
this._store.add(feedbackToolbar);
328329

329330
// preview editors
330-
this._previewDiffEditor = this._store.add(_instantiationService.createInstance(EmbeddedDiffEditorWidget, this._elements.previewDiff, _previewEditorEditorOptions, { modifiedEditor: codeEditorWidgetOptions, originalEditor: codeEditorWidgetOptions }, parentEditor));
331+
this._previewDiffEditor = new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedDiffEditorWidget, this._elements.previewDiff, _previewEditorEditorOptions, { modifiedEditor: codeEditorWidgetOptions, originalEditor: codeEditorWidgetOptions }, parentEditor)));
331332

332333
this._previewCreateTitle = this._store.add(_instantiationService.createInstance(ResourceLabel, this._elements.previewCreateTitle, { supportIcons: true }));
333-
this._previewCreateEditor = this._store.add(_instantiationService.createInstance(EmbeddedCodeEditorWidget, this._elements.previewCreate, _previewEditorEditorOptions, codeEditorWidgetOptions, parentEditor));
334+
this._previewCreateEditor = new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedCodeEditorWidget, this._elements.previewCreate, _previewEditorEditorOptions, codeEditorWidgetOptions, parentEditor)));
334335

335336
this._elements.message.tabIndex = 0;
336337
this._elements.statusLabel.tabIndex = 0;
@@ -372,12 +373,12 @@ export class InteractiveEditorWidget {
372373
this._inputEditor.layout(new Dimension(innerEditorWidth, this._inputEditor.getContentHeight()));
373374
this._elements.placeholder.style.width = `${innerEditorWidth /* input-padding*/}px`;
374375

375-
const previewDiffDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewDiffEditor.getContentHeight())));
376-
this._previewDiffEditor.layout(previewDiffDim);
376+
const previewDiffDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewDiffEditor.value.getContentHeight())));
377+
this._previewDiffEditor.value.layout(previewDiffDim);
377378
this._elements.previewDiff.style.height = `${previewDiffDim.height}px`;
378379

379-
const previewCreateDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewCreateEditor.getContentHeight())));
380-
this._previewCreateEditor.layout(previewCreateDim);
380+
const previewCreateDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewCreateEditor.value.getContentHeight())));
381+
this._previewCreateEditor.value.layout(previewCreateDim);
381382
this._elements.previewCreate.style.height = `${previewCreateDim.height}px`;
382383
}
383384
} finally {
@@ -389,9 +390,9 @@ export class InteractiveEditorWidget {
389390
const base = getTotalHeight(this._elements.progress) + getTotalHeight(this._elements.status);
390391
const editorHeight = this._inputEditor.getContentHeight() + 12 /* padding and border */;
391392
const markdownMessageHeight = getTotalHeight(this._elements.markdownMessage);
392-
const previewDiffHeight = this._previewDiffEditor.getModel().modified ? 12 + Math.min(300, Math.max(0, this._previewDiffEditor.getContentHeight())) : 0;
393+
const previewDiffHeight = this._previewDiffEditor.value.getModel().modified ? 12 + Math.min(300, Math.max(0, this._previewDiffEditor.value.getContentHeight())) : 0;
393394
const previewCreateTitleHeight = getTotalHeight(this._elements.previewCreateTitle);
394-
const previewCreateHeight = this._previewCreateEditor.getModel() ? 18 + Math.min(300, Math.max(0, this._previewCreateEditor.getContentHeight())) : 0;
395+
const previewCreateHeight = this._previewCreateEditor.value.getModel() ? 18 + Math.min(300, Math.max(0, this._previewCreateEditor.value.getContentHeight())) : 0;
395396
return base + editorHeight + markdownMessageHeight + previewDiffHeight + previewCreateTitleHeight + previewCreateHeight + 18 /* padding */ + 8 /*shadow*/;
396397
}
397398

@@ -508,7 +509,7 @@ export class InteractiveEditorWidget {
508509
const languageSelection: ILanguageSelection = { languageId: textModelv0.getLanguageId(), onDidChange: Event.None };
509510
const modified = this._modelService.createModel(createTextBufferFactoryFromSnapshot(textModelv0.createSnapshot()), languageSelection, undefined, true);
510511
modified.applyEdits(edits, false);
511-
this._previewDiffEditor.setModel({ original: textModelv0, modified });
512+
this._previewDiffEditor.value.setModel({ original: textModelv0, modified });
512513

513514
// joined ranges
514515
let originalLineRange = changes[0].originalRange;
@@ -531,16 +532,16 @@ export class InteractiveEditorWidget {
531532

532533
const hiddenOriginal = invertLineRange(originalLineRange, textModelv0);
533534
const hiddenModified = invertLineRange(modifiedLineRange, modified);
534-
this._previewDiffEditor.getOriginalEditor().setHiddenAreas(hiddenOriginal.map(lineRangeAsRange), 'diff-hidden');
535-
this._previewDiffEditor.getModifiedEditor().setHiddenAreas(hiddenModified.map(lineRangeAsRange), 'diff-hidden');
536-
this._previewDiffEditor.revealLine(modifiedLineRange.startLineNumber, ScrollType.Immediate);
535+
this._previewDiffEditor.value.getOriginalEditor().setHiddenAreas(hiddenOriginal.map(lineRangeAsRange), 'diff-hidden');
536+
this._previewDiffEditor.value.getModifiedEditor().setHiddenAreas(hiddenModified.map(lineRangeAsRange), 'diff-hidden');
537+
this._previewDiffEditor.value.revealLine(modifiedLineRange.startLineNumber, ScrollType.Immediate);
537538

538539
this._onDidChangeHeight.fire();
539540
}
540541

541542
hideEditsPreview() {
542543
this._elements.previewDiff.classList.add('hidden');
543-
this._previewDiffEditor.setModel(null);
544+
this._previewDiffEditor.value.setModel(null);
544545
this._previewDiffModel.clear();
545546
this._onDidChangeHeight.fire();
546547
}
@@ -555,14 +556,14 @@ export class InteractiveEditorWidget {
555556
const model = this._modelService.createModel('', langSelection, undefined, true);
556557
model.applyEdits(edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));
557558
this._previewCreateModel.value = model;
558-
this._previewCreateEditor.setModel(model);
559+
this._previewCreateEditor.value.setModel(model);
559560
this._onDidChangeHeight.fire();
560561
}
561562

562563
hideCreatePreview() {
563564
this._elements.previewCreateTitle.classList.add('hidden');
564565
this._elements.previewCreate.classList.add('hidden');
565-
this._previewCreateEditor.setModel(null);
566+
this._previewCreateEditor.value.setModel(null);
566567
this._previewCreateTitle.element.clear();
567568
this._onDidChangeHeight.fire();
568569
}

0 commit comments

Comments
 (0)