fix: use chat edit state for chat file list decorations (#230284)

* fix: use chat edit state for chat file list decorations

* Add theme defaults
This commit is contained in:
Joyce Er 2024-10-02 00:50:08 -07:00 коммит произвёл GitHub
Родитель 72113138d2
Коммит 370f5619b9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
11 изменённых файлов: 45 добавлений и 20 удалений

Просмотреть файл

@ -53,6 +53,7 @@
"--vscode-chat-requestBorder",
"--vscode-chat-slashCommandBackground",
"--vscode-chat-slashCommandForeground",
"--vscode-chat-editedFileForeground",
"--vscode-checkbox-background",
"--vscode-checkbox-border",
"--vscode-checkbox-foreground",
@ -888,4 +889,4 @@
"--widget-color",
"--text-link-decoration"
]
}
}

Просмотреть файл

@ -21,6 +21,7 @@
"button.secondaryHoverBackground": "#3C3C3C",
"chat.slashCommandBackground": "#34414B",
"chat.slashCommandForeground": "#40A6FF",
"chat.editedFileForeground": "#E2C08D",
"checkbox.background": "#313131",
"checkbox.border": "#3C3C3C",
"debugToolBar.background": "#181818",

Просмотреть файл

@ -21,6 +21,7 @@
"button.secondaryHoverBackground": "#CCCCCC",
"chat.slashCommandBackground": "#D2ECFF",
"chat.slashCommandForeground": "#306CA2",
"chat.editedFileForeground": "#895503",
"checkbox.background": "#F8F8F8",
"checkbox.border": "#CECECE",
"descriptionForeground": "#3B3B3B",

Просмотреть файл

@ -188,7 +188,6 @@ export class CollapsibleListPool extends Disposable {
constructor(
private _onDidChangeVisibility: Event<boolean>,
private readonly menuId: MenuId | undefined,
private readonly options: { enableFileDecorations?: boolean } | undefined,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IThemeService private readonly themeService: IThemeService,
@ILabelService private readonly labelService: ILabelService,
@ -208,7 +207,7 @@ export class CollapsibleListPool extends Disposable {
'ChatListRenderer',
container,
new CollapsibleListDelegate(),
[this.instantiationService.createInstance(CollapsibleListRenderer, resourceLabels, this.menuId, this.options)],
[this.instantiationService.createInstance(CollapsibleListRenderer, resourceLabels, this.menuId)],
{
alwaysConsumeMouseWheel: false,
accessibilityProvider: {
@ -299,7 +298,6 @@ class CollapsibleListRenderer implements IListRenderer<IChatCollapsibleListItem,
constructor(
private labels: ResourceLabels,
private menuId: MenuId | undefined,
private options: { enableFileDecorations?: boolean } | undefined,
@IThemeService private readonly themeService: IThemeService,
@IChatVariablesService private readonly chatVariablesService: IChatVariablesService,
@IProductService private readonly productService: IProductService,
@ -384,7 +382,7 @@ class CollapsibleListRenderer implements IListRenderer<IChatCollapsibleListItem,
templateData.label.setFile(uri, {
fileKind: FileKind.FILE,
// Should not have this live-updating data on a historical reference
fileDecorations: this.options?.enableFileDecorations ? { badges: true, colors: true } : { badges: false, colors: false },
fileDecorations: { badges: false, colors: false },
range: 'range' in reference ? reference.range : undefined,
title: data.options?.status?.description ?? data.title
});
@ -406,9 +404,16 @@ class CollapsibleListRenderer implements IListRenderer<IChatCollapsibleListItem,
if (data.state !== undefined) {
chatEditingWidgetFileStateContextKey.bindTo(templateData.contextKeyService).set(data.state);
}
const actionBarContainer = $('.chat-collapsible-list-action-bar');
templateData.toolbar = templateData.templateDisposables.add(templateData.instantiationService.createInstance(MenuWorkbenchToolBar, actionBarContainer, this.menuId, { menuOptions: { shouldForwardArgs: true, arg: arg } }));
const actionBarContainer = templateData.label.element.querySelector('.chat-collapsible-list-action-bar') as HTMLElement ?? $('.chat-collapsible-list-action-bar');
templateData.toolbar = templateData.templateDisposables.add(templateData.instantiationService.createInstance(MenuWorkbenchToolBar, actionBarContainer, this.menuId, { menuOptions: { shouldForwardArgs: true, arg } }));
templateData.label.element.appendChild(actionBarContainer);
if (data.state === WorkingSetEntryState.Modified && !actionBarContainer.classList.contains('modified')) {
actionBarContainer.classList.add('modified');
} else if (data.state !== WorkingSetEntryState.Modified) {
actionBarContainer.classList.remove('modified');
}
}
}

Просмотреть файл

@ -84,7 +84,7 @@ registerAction2(class OpenFileAction extends WorkingSetAction {
icon: Codicon.goToFile,
menu: [{
id: MenuId.ChatEditingSessionWidgetToolbar,
when: ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Edited),
when: ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Modified),
order: 0,
group: 'navigation'
}],
@ -110,7 +110,7 @@ registerAction2(class AcceptAction extends WorkingSetAction {
group: 'navigation',
}, {
id: MenuId.ChatEditingSessionWidgetToolbar,
when: ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Edited),
when: ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Modified),
order: 2,
group: 'navigation'
}],
@ -135,7 +135,7 @@ registerAction2(class DiscardAction extends WorkingSetAction {
group: 'navigation',
}, {
id: MenuId.ChatEditingSessionWidgetToolbar,
when: ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Edited),
when: ContextKeyExpr.equals(chatEditingWidgetFileStateContextKey.key, WorkingSetEntryState.Modified),
order: 1,
group: 'navigation'
}],

Просмотреть файл

@ -71,7 +71,7 @@ export class ChatEditingService extends Disposable implements IChatEditingServic
return;
}
const entries = currentSession.entries.read(reader);
const decidedEntries = entries.filter(entry => entry.state.read(reader) !== WorkingSetEntryState.Edited);
const decidedEntries = entries.filter(entry => entry.state.read(reader) !== WorkingSetEntryState.Modified);
return decidedEntries.map(entry => entry.entryId);
}));
this._register(this._chatService.onDidDisposeSession((e) => {
@ -609,7 +609,7 @@ class ModifiedFileEntry extends Disposable implements IModifiedFileEntry {
return this.doc.uri;
}
private readonly _stateObs = observableValue<WorkingSetEntryState>(this, WorkingSetEntryState.Edited);
private readonly _stateObs = observableValue<WorkingSetEntryState>(this, WorkingSetEntryState.Modified);
public get state(): IObservable<WorkingSetEntryState> {
return this._stateObs;
}
@ -637,11 +637,11 @@ class ModifiedFileEntry extends Disposable implements IModifiedFileEntry {
applyEdits(textEdits: TextEdit[]): void {
this.doc.applyEdits(textEdits);
this._stateObs.set(WorkingSetEntryState.Edited, undefined);
this._stateObs.set(WorkingSetEntryState.Modified, undefined);
}
async accept(transaction: ITransaction | undefined): Promise<void> {
if (this._stateObs.get() !== WorkingSetEntryState.Edited) {
if (this._stateObs.get() !== WorkingSetEntryState.Modified) {
// already accepted or rejected
return;
}
@ -651,7 +651,7 @@ class ModifiedFileEntry extends Disposable implements IModifiedFileEntry {
}
async reject(transaction: ITransaction | undefined): Promise<void> {
if (this._stateObs.get() !== WorkingSetEntryState.Edited) {
if (this._stateObs.get() !== WorkingSetEntryState.Modified) {
// already accepted or rejected
return;
}

Просмотреть файл

@ -255,7 +255,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
}
}));
this._chatEditsListPool = this._register(this.instantiationService.createInstance(CollapsibleListPool, this._onDidChangeVisibility.event, MenuId.ChatEditingSessionWidgetToolbar, { enableFileDecorations: true }));
this._chatEditsListPool = this._register(this.instantiationService.createInstance(CollapsibleListPool, this._onDidChangeVisibility.event, MenuId.ChatEditingSessionWidgetToolbar));
}
private setCurrentLanguageModelToDefault() {
@ -950,7 +950,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
if (e.element?.kind === 'reference' && URI.isUri(e.element.reference)) {
const modifiedFileUri = e.element.reference;
const editedFile = chatEditingSession.entries.get().find((e) => e.modifiedURI.toString() === modifiedFileUri.toString());
if (editedFile?.state.get() === WorkingSetEntryState.Edited) {
if (editedFile?.state.get() === WorkingSetEntryState.Modified) {
void this.editorService.openEditor({
original: { resource: URI.from(editedFile.originalURI, true) },
modified: { resource: URI.from(editedFile.modifiedURI, true) },
@ -977,7 +977,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
dom.clearNode(actionsContainer);
const actionsContainerRight = actionsContainer.querySelector('.chat-editing-session-actions-group') as HTMLElement ?? $('.chat-editing-session-actions-group');
if (chatEditingSession.entries.get().find((e) => e.state.get() === WorkingSetEntryState.Edited)) {
if (chatEditingSession.entries.get().find((e) => e.state.get() === WorkingSetEntryState.Modified)) {
// Don't show Accept All / Discard All actions if user already selected Accept All / Discard All
const actions = [];
actions.push(

Просмотреть файл

@ -156,7 +156,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
this._editorPool = this._register(this.instantiationService.createInstance(EditorPool, editorOptions, delegate, overflowWidgetsDomNode));
this._diffEditorPool = this._register(this.instantiationService.createInstance(DiffEditorPool, editorOptions, delegate, overflowWidgetsDomNode));
this._treePool = this._register(this.instantiationService.createInstance(TreePool, this._onDidChangeVisibility.event));
this._contentReferencesListPool = this._register(this.instantiationService.createInstance(CollapsibleListPool, this._onDidChangeVisibility.event, undefined, undefined));
this._contentReferencesListPool = this._register(this.instantiationService.createInstance(CollapsibleListPool, this._onDidChangeVisibility.event, undefined));
this._register(this.instantiationService.createInstance(ChatCodeBlockContentProvider));
}

Просмотреть файл

@ -508,6 +508,12 @@ have to be updated for changes to the rules above, or to support more deeply nes
display: inherit;
}
.interactive-session .chat-editing-session .monaco-list-row .chat-collapsible-list-action-bar.modified::after {
content: "M";
padding-right: 4px;
color: var(--vscode-chat-editedFileForeground);
}
.interactive-session .chat-editing-session .chat-editing-session-container.show-file-icons .monaco-scrollable-element .monaco-list-rows .monaco-list-row {
border-radius: 2px;
}

Просмотреть файл

@ -42,3 +42,14 @@ export const chatAvatarForeground = registerColor(
foreground,
localize('chat.avatarForeground', 'The foreground color of a chat avatar.')
);
export const chatEditedFileForeground = registerColor(
'chat.editedFileForeground',
{
light: '#895503',
dark: '#E2C08D',
hcDark: '#E2C08D',
hcLight: '#895503'
},
localize('chat.editedFileForeground', 'The foreground color of a chat edited file in the edited file list.')
);

Просмотреть файл

@ -46,7 +46,7 @@ export interface IChatEditingSession {
export const enum WorkingSetEntryState {
Attached,
Edited,
Modified,
Accepted,
Rejected
}