Skip to content

Commit 2eb365c

Browse files
authored
Add commands to move chat sessions between the editor and sidebar (microsoft#183270)
1 parent 7d57296 commit 2eb365c

File tree

8 files changed

+307
-112
lines changed

8 files changed

+307
-112
lines changed

src/vs/workbench/contrib/chat/browser/actions/chatActions.ts

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
1414
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
1515
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
1616
import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane';
17-
import { ActiveEditorContext } from 'vs/workbench/common/contextkeys';
1817
import { runAccessibilityHelpAction } from 'vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp';
19-
import { clearChatEditor, clearChatSession } from 'vs/workbench/contrib/chat/browser/actions/chatClear';
2018
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
2119
import { IChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatEditor';
2220
import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInput';
@@ -53,36 +51,6 @@ export function registerChatActions() {
5351
}
5452
});
5553

56-
registerAction2(class ClearEditorAction extends Action2 {
57-
constructor() {
58-
super({
59-
id: 'workbench.action.chatEditor.clear',
60-
title: {
61-
value: localize('interactiveSession.clear.label', "Clear"),
62-
original: 'Clear'
63-
},
64-
icon: Codicon.clearAll,
65-
f1: false,
66-
menu: [{
67-
id: MenuId.EditorTitle,
68-
group: 'navigation',
69-
order: 0,
70-
when: ActiveEditorContext.isEqualTo(ChatEditorInput.EditorID),
71-
}]
72-
});
73-
}
74-
async run(accessor: ServicesAccessor, ...args: any[]) {
75-
const widgetService = accessor.get(IChatWidgetService);
76-
77-
const widget = widgetService.lastFocusedWidget;
78-
if (!widget) {
79-
return;
80-
}
81-
82-
await clearChatEditor(accessor, widget);
83-
}
84-
});
85-
8654
registerAction2(class ClearChatHistoryAction extends Action2 {
8755
constructor() {
8856
super({
@@ -165,38 +133,6 @@ export function registerChatActions() {
165133
widgetService.lastFocusedWidget?.focusInput();
166134
}
167135
});
168-
169-
registerAction2(class GlobalClearChatAction extends Action2 {
170-
constructor() {
171-
super({
172-
id: `workbench.action.chat.clear`,
173-
title: {
174-
value: localize('interactiveSession.clear.label', "Clear"),
175-
original: 'Clear'
176-
},
177-
category: CHAT_CATEGORY,
178-
icon: Codicon.clearAll,
179-
precondition: CONTEXT_PROVIDER_EXISTS,
180-
f1: true,
181-
keybinding: {
182-
weight: KeybindingWeight.WorkbenchContrib,
183-
primary: KeyMod.WinCtrl | KeyCode.KeyL,
184-
when: CONTEXT_IN_CHAT_SESSION
185-
}
186-
});
187-
}
188-
189-
async run(accessor: ServicesAccessor, ...args: any[]) {
190-
const widgetService = accessor.get(IChatWidgetService);
191-
192-
const widget = widgetService.lastFocusedWidget;
193-
if (!widget) {
194-
return;
195-
}
196-
197-
await clearChatSession(accessor, widget);
198-
}
199-
});
200136
}
201137

202138
export function getOpenChatEditorAction(id: string, label: string, when?: string) {
@@ -218,36 +154,6 @@ export function getOpenChatEditorAction(id: string, label: string, when?: string
218154
};
219155
}
220156

221-
const getClearChatActionDescriptorForViewTitle = (viewId: string, providerId: string): Readonly<IAction2Options> & { viewId: string } => ({
222-
viewId,
223-
id: `workbench.action.chat.${providerId}.clear`,
224-
title: {
225-
value: localize('interactiveSession.clear.label', "Clear"),
226-
original: 'Clear'
227-
},
228-
menu: {
229-
id: MenuId.ViewTitle,
230-
when: ContextKeyExpr.equals('view', viewId),
231-
group: 'navigation',
232-
order: 0
233-
},
234-
category: CHAT_CATEGORY,
235-
icon: Codicon.clearAll,
236-
f1: false
237-
});
238-
239-
export function getClearAction(viewId: string, providerId: string) {
240-
return class ClearAction extends ViewAction<ChatViewPane> {
241-
constructor() {
242-
super(getClearChatActionDescriptorForViewTitle(viewId, providerId));
243-
}
244-
245-
async runInView(accessor: ServicesAccessor, view: ChatViewPane) {
246-
await view.clear();
247-
}
248-
};
249-
}
250-
251157
const getHistoryChatActionDescriptorForViewTitle = (viewId: string, providerId: string): Readonly<IAction2Options> & { viewId: string } => ({
252158
viewId,
253159
id: `workbench.action.chat.${providerId}.history`,

src/vs/workbench/contrib/chat/browser/actions/chatClear.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55

66
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
77
import { IViewsService } from 'vs/workbench/common/views';
8-
import { IChatWidgetService, type IChatViewPane, type IChatWidget } from 'vs/workbench/contrib/chat/browser/chat';
8+
import { type IChatViewPane, type IChatWidget } from 'vs/workbench/contrib/chat/browser/chat';
99
import { IChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatEditor';
1010
import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInput';
1111
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
1212
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
1313

1414
export async function clearChatSession(accessor: ServicesAccessor, widget: IChatWidget): Promise<void> {
15-
const viewsService = accessor.get(IViewsService);
16-
1715
if ('viewId' in widget.viewContext) {
16+
const viewsService = accessor.get(IViewsService);
1817
// This cast is to break a circular dependency- ideally this would not be called directly for `/clear`
1918
// from the widget class, but from some contribution.
2019
const view = viewsService.getViewWithId(widget.viewContext.viewId);
@@ -24,17 +23,19 @@ export async function clearChatSession(accessor: ServicesAccessor, widget: IChat
2423

2524
(view as any as IChatViewPane).clear();
2625
} else {
27-
await clearChatEditor(accessor, widget);
26+
await clearChatEditor(accessor);
2827
}
2928
}
3029

31-
export async function clearChatEditor(accessor: ServicesAccessor, widget: IChatWidget): Promise<void> {
30+
export async function clearChatEditor(accessor: ServicesAccessor): Promise<void> {
3231
const editorService = accessor.get(IEditorService);
3332
const editorGroupsService = accessor.get(IEditorGroupsService);
34-
const widgetService = accessor.get(IChatWidgetService);
3533

36-
await editorService.replaceEditors([{
37-
editor: editorService.activeEditor!,
38-
replacement: { resource: ChatEditorInput.getNewEditorUri(), options: <IChatEditorOptions>{ target: { providerId: widgetService.lastFocusedWidget!.providerId, pinned: true } } }
39-
}], editorGroupsService.activeGroup);
34+
const chatEditorInput = editorService.activeEditor;
35+
if (chatEditorInput instanceof ChatEditorInput && chatEditorInput.providerId) {
36+
await editorService.replaceEditors([{
37+
editor: chatEditorInput,
38+
replacement: { resource: ChatEditorInput.getNewEditorUri(), options: <IChatEditorOptions>{ target: { providerId: chatEditorInput.providerId, pinned: true } } }
39+
}], editorGroupsService.activeGroup);
40+
}
4041
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { Codicon } from 'vs/base/common/codicons';
7+
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
8+
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
9+
import { localize } from 'vs/nls';
10+
import { Action2, IAction2Options, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
11+
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
12+
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
13+
import { ViewAction } from 'vs/workbench/browser/parts/views/viewPane';
14+
import { ActiveEditorContext } from 'vs/workbench/common/contextkeys';
15+
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
16+
import { clearChatEditor, clearChatSession } from 'vs/workbench/contrib/chat/browser/actions/chatClear';
17+
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
18+
import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInput';
19+
import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
20+
import { CONTEXT_IN_CHAT_SESSION, CONTEXT_PROVIDER_EXISTS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
21+
22+
export function registerClearActions() {
23+
24+
registerAction2(class ClearEditorAction extends Action2 {
25+
constructor() {
26+
super({
27+
id: 'workbench.action.chatEditor.clear',
28+
title: {
29+
value: localize('interactiveSession.clear.label', "Clear"),
30+
original: 'Clear'
31+
},
32+
icon: Codicon.clearAll,
33+
f1: false,
34+
menu: [{
35+
id: MenuId.EditorTitle,
36+
group: 'navigation',
37+
order: 0,
38+
when: ActiveEditorContext.isEqualTo(ChatEditorInput.EditorID),
39+
}]
40+
});
41+
}
42+
async run(accessor: ServicesAccessor, ...args: any[]) {
43+
await clearChatEditor(accessor);
44+
}
45+
});
46+
47+
48+
registerAction2(class GlobalClearChatAction extends Action2 {
49+
constructor() {
50+
super({
51+
id: `workbench.action.chat.clear`,
52+
title: {
53+
value: localize('interactiveSession.clear.label', "Clear"),
54+
original: 'Clear'
55+
},
56+
category: CHAT_CATEGORY,
57+
icon: Codicon.clearAll,
58+
precondition: CONTEXT_PROVIDER_EXISTS,
59+
f1: true,
60+
keybinding: {
61+
weight: KeybindingWeight.WorkbenchContrib,
62+
primary: KeyMod.WinCtrl | KeyCode.KeyL,
63+
when: CONTEXT_IN_CHAT_SESSION
64+
}
65+
});
66+
}
67+
68+
async run(accessor: ServicesAccessor, ...args: any[]) {
69+
const widgetService = accessor.get(IChatWidgetService);
70+
71+
const widget = widgetService.lastFocusedWidget;
72+
if (!widget) {
73+
return;
74+
}
75+
76+
await clearChatSession(accessor, widget);
77+
}
78+
});
79+
}
80+
81+
const getClearChatActionDescriptorForViewTitle = (viewId: string, providerId: string): Readonly<IAction2Options> & { viewId: string } => ({
82+
viewId,
83+
id: `workbench.action.chat.${providerId}.clear`,
84+
title: {
85+
value: localize('interactiveSession.clear.label', "Clear"),
86+
original: 'Clear'
87+
},
88+
menu: {
89+
id: MenuId.ViewTitle,
90+
when: ContextKeyExpr.equals('view', viewId),
91+
group: 'navigation',
92+
order: 0
93+
},
94+
category: CHAT_CATEGORY,
95+
icon: Codicon.clearAll,
96+
f1: false
97+
});
98+
99+
export function getClearAction(viewId: string, providerId: string) {
100+
return class ClearAction extends ViewAction<ChatViewPane> {
101+
constructor() {
102+
super(getClearChatActionDescriptorForViewTitle(viewId, providerId));
103+
}
104+
105+
async runInView(accessor: ServicesAccessor, view: ChatViewPane) {
106+
await view.clear();
107+
}
108+
};
109+
}

0 commit comments

Comments
 (0)