mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
joh/icy manatee (#183917)
* Use idle value for widget of interactive editor controller https://github.com/microsoft/vscode/issues/183820 * also make preview editors idle values https://github.com/microsoft/vscode/issues/183820
This commit is contained in:
parent
2a8dea3225
commit
b3f2337542
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
||||
import { Barrier, raceCancellationError } from 'vs/base/common/async';
|
||||
import { Barrier, IdleValue, raceCancellationError } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { toErrorMessage } from 'vs/base/common/errorMessage';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
@ -86,7 +86,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
private _historyOffset: number = -1;
|
||||
|
||||
private readonly _store = new DisposableStore();
|
||||
private readonly _zone: InteractiveEditorZoneWidget;
|
||||
private readonly _zone: IdleValue<InteractiveEditorZoneWidget>;
|
||||
private readonly _ctxHasActiveRequest: IContextKey<boolean>;
|
||||
private readonly _ctxLastResponseType: IContextKey<undefined | InteractiveEditorResponseType>;
|
||||
private readonly _ctxDidEdit: IContextKey<boolean>;
|
||||
|
@ -118,7 +118,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
this._ctxDidEdit = CTX_INTERACTIVE_EDITOR_DID_EDIT.bindTo(contextKeyService);
|
||||
this._ctxLastResponseType = CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.bindTo(contextKeyService);
|
||||
this._ctxLastFeedbackKind = CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK.bindTo(contextKeyService);
|
||||
this._zone = this._store.add(_instaService.createInstance(InteractiveEditorZoneWidget, this._editor));
|
||||
this._zone = new IdleValue(() => this._store.add(_instaService.createInstance(InteractiveEditorZoneWidget, this._editor)));
|
||||
|
||||
this._store.add(this._editor.onDidChangeModel(async e => {
|
||||
if (this._activeSession || !e.newModelUrl) {
|
||||
|
@ -167,7 +167,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
}
|
||||
|
||||
getWidgetPosition(): Position | undefined {
|
||||
return this._zone.position;
|
||||
return this._zone.value.position;
|
||||
}
|
||||
|
||||
async run(options: InteractiveEditorRunOptions | undefined): Promise<void> {
|
||||
|
@ -234,14 +234,14 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
|
||||
switch (session.editMode) {
|
||||
case EditMode.Live:
|
||||
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.widget);
|
||||
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value.widget);
|
||||
break;
|
||||
case EditMode.Preview:
|
||||
this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.widget);
|
||||
this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.value.widget);
|
||||
break;
|
||||
case EditMode.LivePreview:
|
||||
default:
|
||||
this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.widget);
|
||||
this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value.widget);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -265,11 +265,11 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
}]);
|
||||
this._sessionStore.add(toDisposable(() => wholeRangeDecoration.clear()));
|
||||
|
||||
this._zone.widget.updateSlashCommands(this._activeSession.session.slashCommands ?? []);
|
||||
this._zone.widget.placeholder = this._getPlaceholderText();
|
||||
this._zone.widget.value = this._activeSession.lastInput ?? '';
|
||||
this._zone.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect"));
|
||||
this._zone.show(this._activeSession.wholeRange.getEndPosition());
|
||||
this._zone.value.widget.updateSlashCommands(this._activeSession.session.slashCommands ?? []);
|
||||
this._zone.value.widget.placeholder = this._getPlaceholderText();
|
||||
this._zone.value.widget.value = this._activeSession.lastInput ?? '';
|
||||
this._zone.value.widget.updateInfo(this._activeSession.session.message ?? localize('welcome.1', "AI-generated code may be incorrect"));
|
||||
this._zone.value.show(this._activeSession.wholeRange.getEndPosition());
|
||||
|
||||
this._sessionStore.add(this._editor.onDidChangeModel((e) => {
|
||||
const msg = this._activeSession?.lastExchange
|
||||
|
@ -357,12 +357,12 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
private async [State.WAIT_FOR_INPUT](options: InteractiveEditorRunOptions | undefined): Promise<State.ACCEPT | State.CANCEL | State.PAUSE | State.WAIT_FOR_INPUT | State.MAKE_REQUEST> {
|
||||
assertType(this._activeSession);
|
||||
|
||||
this._zone.widget.placeholder = this._getPlaceholderText();
|
||||
this._zone.show(this._activeSession.wholeRange.getEndPosition());
|
||||
this._zone.value.widget.placeholder = this._getPlaceholderText();
|
||||
this._zone.value.show(this._activeSession.wholeRange.getEndPosition());
|
||||
|
||||
if (options?.message) {
|
||||
this._zone.widget.value = options?.message;
|
||||
this._zone.widget.selectAll();
|
||||
this._zone.value.widget.value = options?.message;
|
||||
this._zone.value.widget.selectAll();
|
||||
delete options?.message;
|
||||
}
|
||||
|
||||
|
@ -382,7 +382,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
msgListener.dispose();
|
||||
}
|
||||
|
||||
this._zone.widget.selectAll();
|
||||
this._zone.value.widget.selectAll();
|
||||
|
||||
if (message & (Message.CANCEL_INPUT | Message.CANCEL_SESSION)) {
|
||||
return State.CANCEL;
|
||||
|
@ -396,11 +396,11 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
return State.PAUSE;
|
||||
}
|
||||
|
||||
if (!this._zone.widget.value) {
|
||||
if (!this._zone.value.widget.value) {
|
||||
return State.WAIT_FOR_INPUT;
|
||||
}
|
||||
|
||||
const input = this._zone.widget.value;
|
||||
const input = this._zone.value.widget.value;
|
||||
|
||||
if (!InteractiveEditorController._promptHistory.includes(input)) {
|
||||
InteractiveEditorController._promptHistory.unshift(input);
|
||||
|
@ -437,7 +437,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
requestCts.cancel();
|
||||
});
|
||||
|
||||
const typeListener = this._zone.widget.onDidChangeInput(() => {
|
||||
const typeListener = this._zone.value.widget.onDidChangeInput(() => {
|
||||
requestCts.cancel();
|
||||
});
|
||||
|
||||
|
@ -454,8 +454,8 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
let response: EditResponse | MarkdownResponse | ErrorResponse | EmptyResponse;
|
||||
let reply: IInteractiveEditorResponse | null | undefined;
|
||||
try {
|
||||
this._zone.widget.updateProgress(true);
|
||||
this._zone.widget.updateInfo(!this._activeSession.lastExchange ? localize('thinking', "Thinking\u2026") : '');
|
||||
this._zone.value.widget.updateProgress(true);
|
||||
this._zone.value.widget.updateInfo(!this._activeSession.lastExchange ? localize('thinking', "Thinking\u2026") : '');
|
||||
this._ctxHasActiveRequest.set(true);
|
||||
reply = await raceCancellationError(Promise.resolve(task), requestCts.token);
|
||||
|
||||
|
@ -472,8 +472,8 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
|
||||
} finally {
|
||||
this._ctxHasActiveRequest.set(false);
|
||||
this._zone.widget.updateProgress(false);
|
||||
this._zone.widget.updateInfo('');
|
||||
this._zone.value.widget.updateProgress(false);
|
||||
this._zone.value.widget.updateInfo('');
|
||||
this._log('request took', sw.elapsed(), this._activeSession.provider.debugName);
|
||||
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
const { response } = this._activeSession.lastExchange!;
|
||||
if (response instanceof EditResponse) {
|
||||
// edit response -> complex...
|
||||
this._zone.widget.updateMarkdownMessage(undefined);
|
||||
this._zone.value.widget.updateMarkdownMessage(undefined);
|
||||
|
||||
const canContinue = this._strategy.checkChanges(response);
|
||||
if (!canContinue) {
|
||||
|
@ -540,27 +540,27 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
|
||||
if (response instanceof EmptyResponse) {
|
||||
// show status message
|
||||
this._zone.widget.updateStatus(localize('empty', "No results, please refine your input and try again"), { classes: ['warn'] });
|
||||
this._zone.value.widget.updateStatus(localize('empty', "No results, please refine your input and try again"), { classes: ['warn'] });
|
||||
return State.WAIT_FOR_INPUT;
|
||||
|
||||
} else if (response instanceof ErrorResponse) {
|
||||
// show error
|
||||
if (!response.isCancellation) {
|
||||
this._zone.widget.updateStatus(response.message, { classes: ['error'] });
|
||||
this._zone.value.widget.updateStatus(response.message, { classes: ['error'] });
|
||||
}
|
||||
|
||||
} else if (response instanceof MarkdownResponse) {
|
||||
// clear status, show MD message
|
||||
const renderedMarkdown = renderMarkdown(response.raw.message, { inline: true });
|
||||
this._zone.widget.updateStatus('');
|
||||
this._zone.widget.updateMarkdownMessage(renderedMarkdown.element);
|
||||
this._zone.widget.updateToolbar(true);
|
||||
this._zone.widget.updateMarkdownMessageExpansionState(this._activeSession.lastExpansionState);
|
||||
this._zone.value.widget.updateStatus('');
|
||||
this._zone.value.widget.updateMarkdownMessage(renderedMarkdown.element);
|
||||
this._zone.value.widget.updateToolbar(true);
|
||||
this._zone.value.widget.updateMarkdownMessageExpansionState(this._activeSession.lastExpansionState);
|
||||
|
||||
} else if (response instanceof EditResponse) {
|
||||
// edit response -> complex...
|
||||
this._zone.widget.updateMarkdownMessage(undefined);
|
||||
this._zone.widget.updateToolbar(true);
|
||||
this._zone.value.widget.updateMarkdownMessage(undefined);
|
||||
this._zone.value.widget.updateToolbar(true);
|
||||
|
||||
const canContinue = this._strategy.checkChanges(response);
|
||||
if (!canContinue) {
|
||||
|
@ -586,7 +586,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
this._ctxLastResponseType.reset();
|
||||
this._ctxLastFeedbackKind.reset();
|
||||
|
||||
this._zone.hide();
|
||||
this._zone.value.hide();
|
||||
|
||||
// Return focus to the editor only if the current focus is within the editor widget
|
||||
if (this._editor.hasWidgetFocus()) {
|
||||
|
@ -627,9 +627,9 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
}
|
||||
|
||||
arrowOut(up: boolean): void {
|
||||
if (this._zone.position && this._editor.hasModel()) {
|
||||
if (this._zone.value.position && this._editor.hasModel()) {
|
||||
const { column } = this._editor.getPosition();
|
||||
const { lineNumber } = this._zone.position;
|
||||
const { lineNumber } = this._zone.value.position;
|
||||
const newLine = up ? lineNumber : lineNumber + 1;
|
||||
this._editor.setPosition({ lineNumber: newLine, column });
|
||||
this._editor.focus();
|
||||
|
@ -641,7 +641,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
}
|
||||
|
||||
focus(): void {
|
||||
this._zone.widget.focus();
|
||||
this._zone.value.widget.focus();
|
||||
}
|
||||
|
||||
populateHistory(up: boolean) {
|
||||
|
@ -652,8 +652,8 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
const pos = (len + this._historyOffset + (up ? 1 : -1)) % len;
|
||||
const entry = InteractiveEditorController._promptHistory[pos];
|
||||
|
||||
this._zone.widget.value = entry;
|
||||
this._zone.widget.selectAll();
|
||||
this._zone.value.widget.value = entry;
|
||||
this._zone.value.widget.selectAll();
|
||||
this._historyOffset = pos;
|
||||
}
|
||||
|
||||
|
@ -665,7 +665,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
|
||||
updateExpansionState(expand: boolean) {
|
||||
if (this._activeSession) {
|
||||
this._zone.widget.updateMarkdownMessageExpansionState(expand);
|
||||
this._zone.value.widget.updateMarkdownMessageExpansionState(expand);
|
||||
this._activeSession.lastExpansionState = expand;
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +675,7 @@ export class InteractiveEditorController implements IEditorContribution {
|
|||
const kind = helpful ? InteractiveEditorResponseFeedbackKind.Helpful : InteractiveEditorResponseFeedbackKind.Unhelpful;
|
||||
this._activeSession.provider.handleInteractiveEditorResponseFeedback?.(this._activeSession.session, this._activeSession.lastExchange.response.raw, kind);
|
||||
this._ctxLastFeedbackKind.set(helpful ? 'helpful' : 'unhelpful');
|
||||
this._zone.widget.updateStatus('Thank you for your feedback!', { resetAfter: 1250 });
|
||||
this._zone.value.widget.updateStatus('Thank you for your feedback!', { resetAfter: 1250 });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
|||
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
|
||||
import { assertType } from 'vs/base/common/types';
|
||||
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { IdleValue } from 'vs/base/common/async';
|
||||
|
||||
const defaultAriaLabel = localize('aria-label', "Interactive Editor Input");
|
||||
|
||||
|
@ -160,11 +161,11 @@ export class InteractiveEditorWidget {
|
|||
|
||||
private readonly _progressBar: ProgressBar;
|
||||
|
||||
private readonly _previewDiffEditor: EmbeddedDiffEditorWidget;
|
||||
private readonly _previewDiffEditor: IdleValue<EmbeddedDiffEditorWidget>;
|
||||
private readonly _previewDiffModel = this._store.add(new MutableDisposable());
|
||||
|
||||
private readonly _previewCreateTitle: ResourceLabel;
|
||||
private readonly _previewCreateEditor: ICodeEditor;
|
||||
private readonly _previewCreateEditor: IdleValue<ICodeEditor>;
|
||||
private readonly _previewCreateModel = this._store.add(new MutableDisposable());
|
||||
|
||||
private readonly _onDidChangeHeight = new MicrotaskEmitter<void>();
|
||||
|
@ -327,10 +328,10 @@ export class InteractiveEditorWidget {
|
|||
this._store.add(feedbackToolbar);
|
||||
|
||||
// preview editors
|
||||
this._previewDiffEditor = this._store.add(_instantiationService.createInstance(EmbeddedDiffEditorWidget, this._elements.previewDiff, _previewEditorEditorOptions, { modifiedEditor: codeEditorWidgetOptions, originalEditor: codeEditorWidgetOptions }, parentEditor));
|
||||
this._previewDiffEditor = new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedDiffEditorWidget, this._elements.previewDiff, _previewEditorEditorOptions, { modifiedEditor: codeEditorWidgetOptions, originalEditor: codeEditorWidgetOptions }, parentEditor)));
|
||||
|
||||
this._previewCreateTitle = this._store.add(_instantiationService.createInstance(ResourceLabel, this._elements.previewCreateTitle, { supportIcons: true }));
|
||||
this._previewCreateEditor = this._store.add(_instantiationService.createInstance(EmbeddedCodeEditorWidget, this._elements.previewCreate, _previewEditorEditorOptions, codeEditorWidgetOptions, parentEditor));
|
||||
this._previewCreateEditor = new IdleValue(() => this._store.add(_instantiationService.createInstance(EmbeddedCodeEditorWidget, this._elements.previewCreate, _previewEditorEditorOptions, codeEditorWidgetOptions, parentEditor)));
|
||||
|
||||
this._elements.message.tabIndex = 0;
|
||||
this._elements.statusLabel.tabIndex = 0;
|
||||
|
@ -372,12 +373,12 @@ export class InteractiveEditorWidget {
|
|||
this._inputEditor.layout(new Dimension(innerEditorWidth, this._inputEditor.getContentHeight()));
|
||||
this._elements.placeholder.style.width = `${innerEditorWidth /* input-padding*/}px`;
|
||||
|
||||
const previewDiffDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewDiffEditor.getContentHeight())));
|
||||
this._previewDiffEditor.layout(previewDiffDim);
|
||||
const previewDiffDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewDiffEditor.value.getContentHeight())));
|
||||
this._previewDiffEditor.value.layout(previewDiffDim);
|
||||
this._elements.previewDiff.style.height = `${previewDiffDim.height}px`;
|
||||
|
||||
const previewCreateDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewCreateEditor.getContentHeight())));
|
||||
this._previewCreateEditor.layout(previewCreateDim);
|
||||
const previewCreateDim = new Dimension(dim.width, Math.min(300, Math.max(0, this._previewCreateEditor.value.getContentHeight())));
|
||||
this._previewCreateEditor.value.layout(previewCreateDim);
|
||||
this._elements.previewCreate.style.height = `${previewCreateDim.height}px`;
|
||||
}
|
||||
} finally {
|
||||
|
@ -389,9 +390,9 @@ export class InteractiveEditorWidget {
|
|||
const base = getTotalHeight(this._elements.progress) + getTotalHeight(this._elements.status);
|
||||
const editorHeight = this._inputEditor.getContentHeight() + 12 /* padding and border */;
|
||||
const markdownMessageHeight = getTotalHeight(this._elements.markdownMessage);
|
||||
const previewDiffHeight = this._previewDiffEditor.getModel().modified ? 12 + Math.min(300, Math.max(0, this._previewDiffEditor.getContentHeight())) : 0;
|
||||
const previewDiffHeight = this._previewDiffEditor.value.getModel().modified ? 12 + Math.min(300, Math.max(0, this._previewDiffEditor.value.getContentHeight())) : 0;
|
||||
const previewCreateTitleHeight = getTotalHeight(this._elements.previewCreateTitle);
|
||||
const previewCreateHeight = this._previewCreateEditor.getModel() ? 18 + Math.min(300, Math.max(0, this._previewCreateEditor.getContentHeight())) : 0;
|
||||
const previewCreateHeight = this._previewCreateEditor.value.getModel() ? 18 + Math.min(300, Math.max(0, this._previewCreateEditor.value.getContentHeight())) : 0;
|
||||
return base + editorHeight + markdownMessageHeight + previewDiffHeight + previewCreateTitleHeight + previewCreateHeight + 18 /* padding */ + 8 /*shadow*/;
|
||||
}
|
||||
|
||||
|
@ -508,7 +509,7 @@ export class InteractiveEditorWidget {
|
|||
const languageSelection: ILanguageSelection = { languageId: textModelv0.getLanguageId(), onDidChange: Event.None };
|
||||
const modified = this._modelService.createModel(createTextBufferFactoryFromSnapshot(textModelv0.createSnapshot()), languageSelection, undefined, true);
|
||||
modified.applyEdits(edits, false);
|
||||
this._previewDiffEditor.setModel({ original: textModelv0, modified });
|
||||
this._previewDiffEditor.value.setModel({ original: textModelv0, modified });
|
||||
|
||||
// joined ranges
|
||||
let originalLineRange = changes[0].originalRange;
|
||||
|
@ -531,16 +532,16 @@ export class InteractiveEditorWidget {
|
|||
|
||||
const hiddenOriginal = invertLineRange(originalLineRange, textModelv0);
|
||||
const hiddenModified = invertLineRange(modifiedLineRange, modified);
|
||||
this._previewDiffEditor.getOriginalEditor().setHiddenAreas(hiddenOriginal.map(lineRangeAsRange), 'diff-hidden');
|
||||
this._previewDiffEditor.getModifiedEditor().setHiddenAreas(hiddenModified.map(lineRangeAsRange), 'diff-hidden');
|
||||
this._previewDiffEditor.revealLine(modifiedLineRange.startLineNumber, ScrollType.Immediate);
|
||||
this._previewDiffEditor.value.getOriginalEditor().setHiddenAreas(hiddenOriginal.map(lineRangeAsRange), 'diff-hidden');
|
||||
this._previewDiffEditor.value.getModifiedEditor().setHiddenAreas(hiddenModified.map(lineRangeAsRange), 'diff-hidden');
|
||||
this._previewDiffEditor.value.revealLine(modifiedLineRange.startLineNumber, ScrollType.Immediate);
|
||||
|
||||
this._onDidChangeHeight.fire();
|
||||
}
|
||||
|
||||
hideEditsPreview() {
|
||||
this._elements.previewDiff.classList.add('hidden');
|
||||
this._previewDiffEditor.setModel(null);
|
||||
this._previewDiffEditor.value.setModel(null);
|
||||
this._previewDiffModel.clear();
|
||||
this._onDidChangeHeight.fire();
|
||||
}
|
||||
|
@ -555,14 +556,14 @@ export class InteractiveEditorWidget {
|
|||
const model = this._modelService.createModel('', langSelection, undefined, true);
|
||||
model.applyEdits(edits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));
|
||||
this._previewCreateModel.value = model;
|
||||
this._previewCreateEditor.setModel(model);
|
||||
this._previewCreateEditor.value.setModel(model);
|
||||
this._onDidChangeHeight.fire();
|
||||
}
|
||||
|
||||
hideCreatePreview() {
|
||||
this._elements.previewCreateTitle.classList.add('hidden');
|
||||
this._elements.previewCreate.classList.add('hidden');
|
||||
this._previewCreateEditor.setModel(null);
|
||||
this._previewCreateEditor.value.setModel(null);
|
||||
this._previewCreateTitle.element.clear();
|
||||
this._onDidChangeHeight.fire();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue