Skip to content

Commit 2f6b1d5

Browse files
authored
1 parent 798f191 commit 2f6b1d5

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

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

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as dom from '../../../../../base/browser/dom.js';
67
import { ServicesAccessor } from '../../../../../editor/browser/editorExtensions.js';
78
import { localize2 } from '../../../../../nls.js';
89
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
910
import { IClipboardService } from '../../../../../platform/clipboard/common/clipboardService.js';
1011
import { CHAT_CATEGORY, stringifyItem } from './chatActions.js';
11-
import { IChatWidgetService } from '../chat.js';
12+
import { ChatTreeItem, IChatWidgetService } from '../chat.js';
1213
import { ChatContextKeys } from '../../common/chatContextKeys.js';
13-
import { IChatRequestViewModel, IChatResponseViewModel, isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
14+
import { IChatRequestViewModel, IChatResponseViewModel, isChatTreeItem, isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
1415

1516
export function registerChatCopyActions() {
1617
registerAction2(class CopyAllAction extends Action2 {
@@ -60,15 +61,30 @@ export function registerChatCopyActions() {
6061
});
6162
}
6263

63-
run(accessor: ServicesAccessor, ...args: any[]) {
64-
const item = args[0];
65-
if (!isRequestVM(item) && !isResponseVM(item)) {
64+
async run(accessor: ServicesAccessor, ...args: any[]) {
65+
const chatWidgetService = accessor.get(IChatWidgetService);
66+
const clipboardService = accessor.get(IClipboardService);
67+
68+
const widget = chatWidgetService.lastFocusedWidget;
69+
let item: ChatTreeItem | undefined = args[0];
70+
if (!isChatTreeItem(item)) {
71+
item = widget?.getFocus();
72+
if (!item) {
73+
return;
74+
}
75+
}
76+
77+
// If there is a text selection, and focus is inside the widget, copy the selected text.
78+
// Otherwise, context menu with no selection -> copy the full item
79+
const nativeSelection = dom.getActiveWindow().getSelection();
80+
const selectedText = nativeSelection?.toString();
81+
if (widget && selectedText && selectedText.length > 0 && dom.isAncestor(dom.getActiveElement(), widget.domNode)) {
82+
await clipboardService.writeText(selectedText);
6683
return;
6784
}
6885

69-
const clipboardService = accessor.get(IClipboardService);
7086
const text = stringifyItem(item, false);
71-
clipboardService.writeText(text);
87+
await clipboardService.writeText(text);
7288
}
7389
});
7490
}

src/vs/workbench/contrib/chat/common/chatViewModel.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export function isResponseVM(item: unknown): item is IChatResponseViewModel {
3030
return !!item && typeof (item as IChatResponseViewModel).setVote !== 'undefined';
3131
}
3232

33+
export function isChatTreeItem(item: unknown): item is IChatRequestViewModel | IChatResponseViewModel {
34+
return isRequestVM(item) || isResponseVM(item);
35+
}
36+
3337
export function assertIsResponseVM(item: unknown): asserts item is IChatResponseViewModel {
3438
if (!isResponseVM(item)) {
3539
throw new Error('Expected item to be IChatResponseViewModel');

0 commit comments

Comments
 (0)