mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-10 16:58:55 -05:00
auto accept changes (#238043)
* add setting to auto apply AI changes * fix rounding error * tweak animation
This commit is contained in:
@@ -128,6 +128,12 @@ configurationRegistry.registerConfiguration({
|
||||
markdownDescription: nls.localize('chat.editing.alwaysSaveWithGeneratedChanges', "Whether files that have changes made by chat can be saved without confirmation."),
|
||||
default: false,
|
||||
},
|
||||
'chat.editing.automaticallyAcceptChanges': {
|
||||
type: 'boolean',
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
markdownDescription: nls.localize('chat.editing.automaticallyAcceptChanges', "Whether changes made by chat are automatically accepted without prior review."),
|
||||
default: false,
|
||||
},
|
||||
'chat.editing.confirmEditRequestRemoval': {
|
||||
type: 'boolean',
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { RunOnceScheduler } from '../../../../../base/common/async.js';
|
||||
import { Emitter } from '../../../../../base/common/event.js';
|
||||
import { Disposable, IReference, toDisposable } from '../../../../../base/common/lifecycle.js';
|
||||
import { Schemas } from '../../../../../base/common/network.js';
|
||||
import { autorun, IObservable, ITransaction, observableValue, transaction } from '../../../../../base/common/observable.js';
|
||||
import { autorun, derived, IObservable, ITransaction, observableValue, transaction } from '../../../../../base/common/observable.js';
|
||||
import { themeColorFromId } from '../../../../../base/common/themables.js';
|
||||
import { URI } from '../../../../../base/common/uri.js';
|
||||
import { EditOperation, ISingleEditOperation } from '../../../../../editor/common/core/editOperation.js';
|
||||
@@ -91,6 +91,12 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
|
||||
return this._maxLineNumberObs;
|
||||
}
|
||||
|
||||
private readonly _reviewModeTempObs = observableValue<true | undefined>(this, undefined);
|
||||
readonly reviewMode: IObservable<boolean>;
|
||||
|
||||
private readonly _autoAcceptCountdown = observableValue<number | undefined>(this, undefined);
|
||||
readonly autoAcceptCountdown: IObservable<number | undefined> = this._autoAcceptCountdown;
|
||||
|
||||
private _isFirstEditAfterStartOrSnapshot: boolean = true;
|
||||
private _edit: OffsetEdit = OffsetEdit.empty;
|
||||
private _isEditFromUs: boolean = false;
|
||||
@@ -199,6 +205,14 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
|
||||
this._diffTrimWhitespace.read(r);
|
||||
this._updateDiffInfoSeq();
|
||||
}));
|
||||
|
||||
// review mode depends on setting and temporary override
|
||||
const autoAccept = observableConfigValue('chat.editing.automaticallyAcceptChanges', false, configService);
|
||||
this.reviewMode = derived(r => {
|
||||
const configuredValue = !autoAccept.read(r);
|
||||
const tempValue = this._reviewModeTempObs.read(r);
|
||||
return tempValue || configuredValue;
|
||||
});
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
@@ -212,6 +226,22 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
|
||||
return this;
|
||||
}
|
||||
|
||||
enableReviewModeUntilSettled(): void {
|
||||
|
||||
this._reviewModeTempObs.set(true, undefined);
|
||||
|
||||
const cleanup = autorun(r => {
|
||||
// reset config when settled
|
||||
const resetConfig = this.state.read(r) !== WorkingSetEntryState.Modified;
|
||||
if (resetConfig) {
|
||||
this._store.delete(cleanup);
|
||||
this._reviewModeTempObs.set(undefined, undefined);
|
||||
}
|
||||
});
|
||||
|
||||
this._store.add(cleanup);
|
||||
}
|
||||
|
||||
private _clearCurrentEditLineDecoration() {
|
||||
this._editDecorations = this.doc.deltaDecorations(this._editDecorations, []);
|
||||
}
|
||||
@@ -258,6 +288,31 @@ export class ChatEditingModifiedFileEntry extends Disposable implements IModifie
|
||||
this._isCurrentlyBeingModifiedObs.set(false, tx);
|
||||
this._rewriteRatioObs.set(0, tx);
|
||||
this._clearCurrentEditLineDecoration();
|
||||
|
||||
// AUTO accept mode
|
||||
if (!this.reviewMode.get()) {
|
||||
|
||||
const future = Date.now() + 10000; // 10secs
|
||||
const update = () => {
|
||||
|
||||
const reviewMode = this.reviewMode.get();
|
||||
if (reviewMode) {
|
||||
// switched back to review mode
|
||||
this._autoAcceptCountdown.set(undefined, undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
const remain = Math.round((future - Date.now()) / 1000);
|
||||
if (remain <= 0) {
|
||||
this.accept(undefined);
|
||||
this._autoAcceptCountdown.set(undefined, undefined);
|
||||
} else {
|
||||
this._autoAcceptCountdown.set(remain, undefined);
|
||||
setTimeout(update, 1000);
|
||||
}
|
||||
};
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
private _mirrorEdits(event: IModelContentChangedEvent) {
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { ICodeEditor, isCodeEditor, isDiffEditor } from '../../../../editor/browser/editorBrowser.js';
|
||||
import { localize2 } from '../../../../nls.js';
|
||||
import { localize, localize2 } from '../../../../nls.js';
|
||||
import { EditorAction2, ServicesAccessor } from '../../../../editor/browser/editorExtensions.js';
|
||||
import { Codicon } from '../../../../base/common/codicons.js';
|
||||
import { Action2, MenuId, registerAction2 } from '../../../../platform/actions/common/actions.js';
|
||||
import { Action2, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';
|
||||
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
|
||||
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
|
||||
import { CHAT_CATEGORY } from './actions/chatActions.js';
|
||||
import { ChatEditorController, ctxHasEditorModification, ctxHasRequestInProgress } from './chatEditorController.js';
|
||||
import { ChatEditorController, ctxHasEditorModification, ctxReviewModeEnabled } from './chatEditorController.js';
|
||||
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { EditorContextKeys } from '../../../../editor/common/editorContextKeys.js';
|
||||
import { ACTIVE_GROUP, IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
@@ -45,6 +45,7 @@ abstract class NavigateAction extends Action2 {
|
||||
id: MenuId.ChatEditingEditorContent,
|
||||
group: 'navigate',
|
||||
order: !next ? 2 : 3,
|
||||
when: ctxReviewModeEnabled
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -130,7 +131,7 @@ abstract class AcceptDiscardAction extends Action2 {
|
||||
? localize2('accept2', 'Accept')
|
||||
: localize2('discard2', 'Discard'),
|
||||
category: CHAT_CATEGORY,
|
||||
precondition: ContextKeyExpr.and(ctxHasRequestInProgress.negate(), hasUndecidedChatEditingResourceContextKey),
|
||||
precondition: ContextKeyExpr.and(hasUndecidedChatEditingResourceContextKey),
|
||||
icon: accept
|
||||
? Codicon.check
|
||||
: Codicon.discard,
|
||||
@@ -146,6 +147,7 @@ abstract class AcceptDiscardAction extends Action2 {
|
||||
id: MenuId.ChatEditingEditorContent,
|
||||
group: 'a_resolve',
|
||||
order: accept ? 0 : 1,
|
||||
when: !accept ? ctxReviewModeEnabled : undefined
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -272,6 +274,7 @@ class OpenDiffAction extends EditorAction2 {
|
||||
id: MenuId.ChatEditingEditorContent,
|
||||
group: 'a_resolve',
|
||||
order: 2,
|
||||
when: ctxReviewModeEnabled
|
||||
}]
|
||||
});
|
||||
}
|
||||
@@ -281,12 +284,55 @@ class OpenDiffAction extends EditorAction2 {
|
||||
}
|
||||
}
|
||||
|
||||
export class ReviewChangesAction extends EditorAction2 {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'chatEditor.action.reviewChanges',
|
||||
title: localize2('review', "Review"),
|
||||
menu: [{
|
||||
id: MenuId.ChatEditingEditorContent,
|
||||
group: 'a_resolve',
|
||||
order: 3,
|
||||
when: ctxReviewModeEnabled.negate(),
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
override runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor) {
|
||||
const chatEditingService = accessor.get(IChatEditingService);
|
||||
|
||||
if (!editor.hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const session = chatEditingService.editingSessionsObs.get().find(session => session.getEntry(editor.getModel().uri));
|
||||
const entry = session?.getEntry(editor.getModel().uri);
|
||||
entry?.enableReviewModeUntilSettled();
|
||||
}
|
||||
}
|
||||
|
||||
export function registerChatEditorActions() {
|
||||
registerAction2(class NextAction extends NavigateAction { constructor() { super(true); } });
|
||||
registerAction2(class PrevAction extends NavigateAction { constructor() { super(false); } });
|
||||
registerAction2(ReviewChangesAction);
|
||||
registerAction2(AcceptAction);
|
||||
registerAction2(AcceptHunkAction);
|
||||
registerAction2(RejectAction);
|
||||
registerAction2(RejectHunkAction);
|
||||
registerAction2(OpenDiffAction);
|
||||
|
||||
}
|
||||
|
||||
export const navigationBearingFakeActionId = 'chatEditor.navigation.bearings';
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.ChatEditingEditorContent, {
|
||||
command: {
|
||||
id: navigationBearingFakeActionId,
|
||||
title: localize('label', "Navigation Status"),
|
||||
precondition: ContextKeyExpr.false(),
|
||||
},
|
||||
group: 'navigate',
|
||||
order: -1,
|
||||
when: ctxReviewModeEnabled,
|
||||
});
|
||||
|
||||
@@ -39,6 +39,7 @@ import { ChatEditorOverlayWidget } from './chatEditorOverlay.js';
|
||||
|
||||
export const ctxHasEditorModification = new RawContextKey<boolean>('chat.hasEditorModifications', undefined, localize('chat.hasEditorModifications', "The current editor contains chat modifications"));
|
||||
export const ctxHasRequestInProgress = new RawContextKey<boolean>('chat.ctxHasRequestInProgress', false, localize('chat.ctxHasRequestInProgress', "The current editor shows a file from an edit session which is still in progress"));
|
||||
export const ctxReviewModeEnabled = new RawContextKey<boolean>('chat.ctxReviewModeEnabled', true, localize('chat.ctxReviewModeEnabled', "Review mode for chat changes is enabled"));
|
||||
|
||||
export class ChatEditorController extends Disposable implements IEditorContribution {
|
||||
|
||||
@@ -57,6 +58,7 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
|
||||
private readonly _ctxHasEditorModification: IContextKey<boolean>;
|
||||
private readonly _ctxRequestInProgress: IContextKey<boolean>;
|
||||
private readonly _ctxReviewModelEnabled: IContextKey<boolean>;
|
||||
|
||||
static get(editor: ICodeEditor): ChatEditorController | null {
|
||||
const controller = editor.getContribution<ChatEditorController>(ChatEditorController.ID);
|
||||
@@ -84,13 +86,13 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
this._overlayWidget = _instantiationService.createInstance(ChatEditorOverlayWidget, _editor);
|
||||
this._ctxHasEditorModification = ctxHasEditorModification.bindTo(contextKeyService);
|
||||
this._ctxRequestInProgress = ctxHasRequestInProgress.bindTo(contextKeyService);
|
||||
this._ctxReviewModelEnabled = ctxReviewModeEnabled.bindTo(contextKeyService);
|
||||
|
||||
const editorObs = observableCodeEditor(this._editor);
|
||||
const fontInfoObs = editorObs.getOption(EditorOption.fontInfo);
|
||||
const lineHeightObs = editorObs.getOption(EditorOption.lineHeight);
|
||||
const modelObs = editorObs.model;
|
||||
|
||||
|
||||
this._store.add(autorun(r => {
|
||||
let isStreamingEdits = false;
|
||||
for (const session of _chatEditingService.editingSessionsObs.read(r)) {
|
||||
@@ -139,11 +141,13 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
|
||||
const { session, entries, idx, entry } = currentEditorEntry;
|
||||
|
||||
this._ctxReviewModelEnabled.set(entry.reviewMode.read(r));
|
||||
|
||||
// context
|
||||
this._currentEntryIndex.set(idx, undefined);
|
||||
|
||||
// overlay widget
|
||||
if (entry.state.read(r) === WorkingSetEntryState.Accepted || entry.state.read(r) === WorkingSetEntryState.Rejected) {
|
||||
if (entry.state.read(r) !== WorkingSetEntryState.Modified) {
|
||||
this._overlayWidget.hide();
|
||||
} else {
|
||||
this._overlayWidget.show(session, entry, entries[(idx + 1) % entries.length]);
|
||||
@@ -172,9 +176,11 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
// Add line decorations (just markers, no UI) for diff navigation
|
||||
this._updateDiffLineDecorations(diff);
|
||||
|
||||
const reviewMode = entry.reviewMode.read(r);
|
||||
|
||||
// Add diff decoration to the UI (unless in diff editor)
|
||||
if (!this._editor.getOption(EditorOption.inDiffEditor)) {
|
||||
this._updateDiffRendering(entry, diff);
|
||||
this._updateDiffRendering(entry, diff, reviewMode);
|
||||
} else {
|
||||
this._clearDiffRendering();
|
||||
}
|
||||
@@ -246,6 +252,7 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
this._currentChangeIndex.set(undefined, undefined);
|
||||
this._currentEntryIndex.set(undefined, undefined);
|
||||
this._ctxHasEditorModification.reset();
|
||||
this._ctxReviewModelEnabled.reset();
|
||||
}
|
||||
|
||||
private _clearDiffRendering() {
|
||||
@@ -260,7 +267,7 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
this._scrollLock = false;
|
||||
}
|
||||
|
||||
private _updateDiffRendering(entry: IModifiedFileEntry, diff: IDocumentDiff): void {
|
||||
private _updateDiffRendering(entry: IModifiedFileEntry, diff: IDocumentDiff, reviewMode: boolean): void {
|
||||
|
||||
const originalModel = entry.originalModel;
|
||||
|
||||
@@ -309,18 +316,21 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
mightContainRTL,
|
||||
);
|
||||
const decorations: InlineDecoration[] = [];
|
||||
for (const i of diffEntry.innerChanges || []) {
|
||||
decorations.push(new InlineDecoration(
|
||||
i.originalRange.delta(-(diffEntry.original.startLineNumber - 1)),
|
||||
diffDeleteDecoration.className!,
|
||||
InlineDecorationType.Regular
|
||||
));
|
||||
|
||||
// If the original range is empty, the start line number is 1 and the new range spans the entire file, don't draw an Added decoration
|
||||
if (!(i.originalRange.isEmpty() && i.originalRange.startLineNumber === 1 && i.modifiedRange.endLineNumber === editorLineCount) && !i.modifiedRange.isEmpty()) {
|
||||
modifiedVisualDecorations.push({
|
||||
range: i.modifiedRange, options: chatDiffAddDecoration
|
||||
});
|
||||
if (reviewMode) {
|
||||
for (const i of diffEntry.innerChanges || []) {
|
||||
decorations.push(new InlineDecoration(
|
||||
i.originalRange.delta(-(diffEntry.original.startLineNumber - 1)),
|
||||
diffDeleteDecoration.className!,
|
||||
InlineDecorationType.Regular
|
||||
));
|
||||
|
||||
// If the original range is empty, the start line number is 1 and the new range spans the entire file, don't draw an Added decoration
|
||||
if (!(i.originalRange.isEmpty() && i.originalRange.startLineNumber === 1 && i.modifiedRange.endLineNumber === editorLineCount) && !i.modifiedRange.isEmpty()) {
|
||||
modifiedVisualDecorations.push({
|
||||
range: i.modifiedRange, options: chatDiffAddDecoration
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,33 +364,38 @@ export class ChatEditorController extends Disposable implements IEditorContribut
|
||||
options: modifiedDecoration
|
||||
});
|
||||
}
|
||||
const domNode = document.createElement('div');
|
||||
domNode.className = 'chat-editing-original-zone view-lines line-delete monaco-mouse-cursor-text';
|
||||
const result = renderLines(source, renderOptions, decorations, domNode);
|
||||
|
||||
if (!isCreatedContent) {
|
||||
const viewZoneData: IViewZone = {
|
||||
afterLineNumber: diffEntry.modified.startLineNumber - 1,
|
||||
heightInLines: result.heightInLines,
|
||||
domNode,
|
||||
ordinal: 50000 + 2 // more than https://github.com/microsoft/vscode/blob/bf52a5cfb2c75a7327c9adeaefbddc06d529dcad/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts#L42
|
||||
};
|
||||
if (reviewMode) {
|
||||
const domNode = document.createElement('div');
|
||||
domNode.className = 'chat-editing-original-zone view-lines line-delete monaco-mouse-cursor-text';
|
||||
const result = renderLines(source, renderOptions, decorations, domNode);
|
||||
|
||||
this._viewZones.push(viewZoneChangeAccessor.addZone(viewZoneData));
|
||||
}
|
||||
if (!isCreatedContent) {
|
||||
|
||||
// Add content widget for each diff change
|
||||
const widget = this._instantiationService.createInstance(DiffHunkWidget, entry, diffEntry, this._editor.getModel()!.getVersionId(), this._editor, isCreatedContent ? 0 : result.heightInLines);
|
||||
widget.layout(diffEntry.modified.startLineNumber);
|
||||
const viewZoneData: IViewZone = {
|
||||
afterLineNumber: diffEntry.modified.startLineNumber - 1,
|
||||
heightInLines: result.heightInLines,
|
||||
domNode,
|
||||
ordinal: 50000 + 2 // more than https://github.com/microsoft/vscode/blob/bf52a5cfb2c75a7327c9adeaefbddc06d529dcad/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts#L42
|
||||
};
|
||||
|
||||
this._diffHunkWidgets.push(widget);
|
||||
diffHunkDecorations.push({
|
||||
range: diffEntry.modified.toInclusiveRange() ?? new Range(diffEntry.modified.startLineNumber, 1, diffEntry.modified.startLineNumber, Number.MAX_SAFE_INTEGER),
|
||||
options: {
|
||||
description: 'diff-hunk-widget',
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges
|
||||
this._viewZones.push(viewZoneChangeAccessor.addZone(viewZoneData));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Add content widget for each diff change
|
||||
const widget = this._instantiationService.createInstance(DiffHunkWidget, entry, diffEntry, this._editor.getModel()!.getVersionId(), this._editor, isCreatedContent ? 0 : result.heightInLines);
|
||||
widget.layout(diffEntry.modified.startLineNumber);
|
||||
|
||||
this._diffHunkWidgets.push(widget);
|
||||
diffHunkDecorations.push({
|
||||
range: diffEntry.modified.toInclusiveRange() ?? new Range(diffEntry.modified.startLineNumber, 1, diffEntry.modified.startLineNumber, Number.MAX_SAFE_INTEGER),
|
||||
options: {
|
||||
description: 'diff-hunk-widget',
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this._diffVisualDecorations.set(modifiedVisualDecorations);
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPosit
|
||||
import { HiddenItemStrategy, MenuWorkbenchToolBar, WorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js';
|
||||
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
|
||||
import { IChatEditingSession, IModifiedFileEntry } from '../common/chatEditingService.js';
|
||||
import { MenuId, MenuRegistry } from '../../../../platform/actions/common/actions.js';
|
||||
import { MenuId } from '../../../../platform/actions/common/actions.js';
|
||||
import { ActionViewItem } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
|
||||
import { ACTIVE_GROUP, IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
import { Range } from '../../../../editor/common/core/range.js';
|
||||
@@ -20,8 +20,7 @@ import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||
import { Codicon } from '../../../../base/common/codicons.js';
|
||||
import { assertType } from '../../../../base/common/types.js';
|
||||
import { localize } from '../../../../nls.js';
|
||||
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { AcceptAction, RejectAction } from './chatEditorActions.js';
|
||||
import { AcceptAction, navigationBearingFakeActionId, RejectAction } from './chatEditorActions.js';
|
||||
import { ChatEditorController } from './chatEditorController.js';
|
||||
import './media/chatEditorOverlay.css';
|
||||
import { findDiffEditorContainingCodeEditor } from '../../../../editor/browser/widget/diffEditor/commands.js';
|
||||
@@ -123,6 +122,25 @@ export class ChatEditorOverlayWidget implements IOverlayWidget {
|
||||
constructor() {
|
||||
super(undefined, action, { ...options, icon: false, label: true, keybindingNotRenderedWithLabel: true });
|
||||
}
|
||||
|
||||
override render(container: HTMLElement): void {
|
||||
super.render(container);
|
||||
|
||||
if (action.id === AcceptAction.ID) {
|
||||
assertType(this.label);
|
||||
assertType(this.element);
|
||||
|
||||
this._store.add(autorun(r => {
|
||||
const value = that._entry.read(r)?.entry.autoAcceptCountdown.read(r);
|
||||
this.label!.innerText = value === undefined
|
||||
? this.action.label
|
||||
: localize('pattern', "{0} ({1})", this.action.label, value);
|
||||
|
||||
this.element?.classList.toggle('auto', !!value);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
override set actionRunner(actionRunner: IActionRunner) {
|
||||
super.actionRunner = actionRunner;
|
||||
|
||||
@@ -258,15 +276,3 @@ export class ChatEditorOverlayWidget implements IOverlayWidget {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const navigationBearingFakeActionId = 'chatEditor.navigation.bearings';
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.ChatEditingEditorContent, {
|
||||
command: {
|
||||
id: navigationBearingFakeActionId,
|
||||
title: localize('label', "Navigation Status"),
|
||||
precondition: ContextKeyExpr.false(),
|
||||
},
|
||||
group: 'navigate',
|
||||
order: -1
|
||||
});
|
||||
|
||||
@@ -89,3 +89,22 @@
|
||||
color: var(--vscode-button-foreground);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chat-editor-overlay-widget .action-item.auto > .action-label {
|
||||
animation: textShift 5s linear infinite alternate;
|
||||
background: linear-gradient(90deg,
|
||||
var(--vscode-button-foreground) 0%,
|
||||
var(--vscode-button-foreground) 45%,
|
||||
var(--vscode-editorGutter-addedBackground) 50%,
|
||||
var(--vscode-button-foreground) 55%,
|
||||
var(--vscode-button-foreground) 100%);
|
||||
background-size: 200% 100%;
|
||||
color: transparent;
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
@keyframes textShift {
|
||||
0% { background-position: 100% 50%; }
|
||||
100% { background-position: 0% 50%; }
|
||||
}
|
||||
|
||||
@@ -138,6 +138,10 @@ export interface IModifiedFileEntry {
|
||||
readonly lastModifyingRequestId: string;
|
||||
accept(transaction: ITransaction | undefined): Promise<void>;
|
||||
reject(transaction: ITransaction | undefined): Promise<void>;
|
||||
|
||||
reviewMode: IObservable<boolean>;
|
||||
autoAcceptCountdown: IObservable<number | undefined>;
|
||||
enableReviewModeUntilSettled(): void;
|
||||
}
|
||||
|
||||
export interface IChatEditingSessionStream {
|
||||
|
||||
@@ -18,8 +18,7 @@ import { autorun, autorunWithStore, IObservable, ISettableObservable, observable
|
||||
import { isEqual } from '../../../../../../base/common/resources.js';
|
||||
import { CellDiffInfo } from '../../diff/notebookDiffViewModel.js';
|
||||
import { INotebookDeletedCellDecorator } from './notebookCellDecorators.js';
|
||||
import { AcceptAction, RejectAction } from '../../../../chat/browser/chatEditorActions.js';
|
||||
import { navigationBearingFakeActionId } from '../../../../chat/browser/chatEditorOverlay.js';
|
||||
import { AcceptAction, navigationBearingFakeActionId, RejectAction } from '../../../../chat/browser/chatEditorActions.js';
|
||||
|
||||
export class NotebookChatActionsOverlayController extends Disposable {
|
||||
constructor(
|
||||
|
||||
Reference in New Issue
Block a user