Path: blob/main/src/vs/workbench/contrib/chat/browser/actions/chatMoveActions.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Codicon } from '../../../../../base/common/codicons.js';6import { ThemeIcon } from '../../../../../base/common/themables.js';7import { localize, localize2 } from '../../../../../nls.js';8import { Action2, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';9import { ContextKeyExpr, ContextKeyExpression } from '../../../../../platform/contextkey/common/contextkey.js';10import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';11import { ActiveEditorContext } from '../../../../common/contextkeys.js';12import { ViewContainerLocation } from '../../../../common/views.js';13import { IEditorGroupsService } from '../../../../services/editor/common/editorGroupsService.js';14import { ACTIVE_GROUP, AUX_WINDOW_GROUP, IEditorService } from '../../../../services/editor/common/editorService.js';15import { IViewsService } from '../../../../services/views/common/viewsService.js';16import { isChatViewTitleActionContext } from '../../common/chatActions.js';17import { ChatContextKeys } from '../../common/chatContextKeys.js';18import { ChatAgentLocation } from '../../common/constants.js';19import { ChatViewId, IChatWidgetService } from '../chat.js';20import { ChatEditor, IChatEditorOptions } from '../chatEditor.js';21import { ChatEditorInput } from '../chatEditorInput.js';22import { ChatViewPane } from '../chatViewPane.js';23import { CHAT_CATEGORY } from './chatActions.js';2425enum MoveToNewLocation {26Editor = 'Editor',27Window = 'Window'28}2930export function registerMoveActions() {31registerAction2(class GlobalMoveToEditorAction extends Action2 {32constructor() {33super({34id: 'workbench.action.chat.openInEditor',35title: localize2('chat.openInEditor.label', "Open Chat in Editor"),36category: CHAT_CATEGORY,37precondition: ChatContextKeys.enabled,38f1: true,39menu: {40id: MenuId.ViewTitle,41when: ContextKeyExpr.equals('view', ChatViewId),42order: 0,43group: '1_open'44},45});46}4748async run(accessor: ServicesAccessor, ...args: any[]) {49const context = args[0];50executeMoveToAction(accessor, MoveToNewLocation.Editor, isChatViewTitleActionContext(context) ? context.sessionId : undefined);51}52});5354registerAction2(class GlobalMoveToNewWindowAction extends Action2 {55constructor() {56super({57id: 'workbench.action.chat.openInNewWindow',58title: localize2('chat.openInNewWindow.label', "Open Chat in New Window"),59category: CHAT_CATEGORY,60precondition: ChatContextKeys.enabled,61f1: true,62menu: {63id: MenuId.ViewTitle,64when: ContextKeyExpr.equals('view', ChatViewId),65order: 0,66group: '1_open'67},68});69}7071async run(accessor: ServicesAccessor, ...args: any[]) {72const context = args[0];73executeMoveToAction(accessor, MoveToNewLocation.Window, isChatViewTitleActionContext(context) ? context.sessionId : undefined);74}75});7677registerAction2(class GlobalMoveToSidebarAction extends Action2 {78constructor() {79super({80id: 'workbench.action.chat.openInSidebar',81title: localize2('interactiveSession.openInSidebar.label', "Open Chat in Side Bar"),82category: CHAT_CATEGORY,83precondition: ChatContextKeys.enabled,84f1: true85});86}8788async run(accessor: ServicesAccessor, ...args: any[]) {89return moveToSidebar(accessor);90}91});9293function appendOpenChatInViewMenuItem(menuId: MenuId, title: string, icon: ThemeIcon, locationContextKey: ContextKeyExpression) {94MenuRegistry.appendMenuItem(menuId, {95command: { id: 'workbench.action.chat.openInSidebar', title, icon },96when: ContextKeyExpr.and(97ActiveEditorContext.isEqualTo(ChatEditorInput.EditorID),98locationContextKey99),100group: menuId === MenuId.CompactWindowEditorTitle ? 'navigation' : undefined,101order: 0102});103}104105[MenuId.EditorTitle, MenuId.CompactWindowEditorTitle].forEach(id => {106appendOpenChatInViewMenuItem(id, localize('interactiveSession.openInSecondarySidebar.label', "Open Chat in Secondary Side Bar"), Codicon.layoutSidebarRightDock, ChatContextKeys.panelLocation.isEqualTo(ViewContainerLocation.AuxiliaryBar));107appendOpenChatInViewMenuItem(id, localize('interactiveSession.openInPrimarySidebar.label', "Open Chat in Primary Side Bar"), Codicon.layoutSidebarLeftDock, ChatContextKeys.panelLocation.isEqualTo(ViewContainerLocation.Sidebar));108appendOpenChatInViewMenuItem(id, localize('interactiveSession.openInPanel.label', "Open Chat in Panel"), Codicon.layoutPanelDock, ChatContextKeys.panelLocation.isEqualTo(ViewContainerLocation.Panel));109});110}111112async function executeMoveToAction(accessor: ServicesAccessor, moveTo: MoveToNewLocation, _sessionId?: string) {113const widgetService = accessor.get(IChatWidgetService);114const editorService = accessor.get(IEditorService);115116const widget = (_sessionId ? widgetService.getWidgetBySessionId(_sessionId) : undefined)117?? widgetService.lastFocusedWidget;118if (!widget || !widget.viewModel || widget.location !== ChatAgentLocation.Panel) {119await editorService.openEditor({ resource: ChatEditorInput.getNewEditorUri(), options: { pinned: true, auxiliary: { compact: true, bounds: { width: 640, height: 640 } } } }, moveTo === MoveToNewLocation.Window ? AUX_WINDOW_GROUP : ACTIVE_GROUP);120return;121}122123const sessionId = widget.viewModel.sessionId;124const viewState = widget.getViewState();125126widget.clear();127await widget.waitForReady();128129const options: IChatEditorOptions = { target: { sessionId }, pinned: true, viewState, auxiliary: { compact: true, bounds: { width: 640, height: 640 } } };130await editorService.openEditor({ resource: ChatEditorInput.getNewEditorUri(), options }, moveTo === MoveToNewLocation.Window ? AUX_WINDOW_GROUP : ACTIVE_GROUP);131}132133async function moveToSidebar(accessor: ServicesAccessor): Promise<void> {134const viewsService = accessor.get(IViewsService);135const editorService = accessor.get(IEditorService);136const editorGroupService = accessor.get(IEditorGroupsService);137138const chatEditor = editorService.activeEditorPane;139const chatEditorInput = chatEditor?.input;140let view: ChatViewPane;141if (chatEditor instanceof ChatEditor && chatEditorInput instanceof ChatEditorInput && chatEditorInput.sessionId) {142await editorService.closeEditor({ editor: chatEditor.input, groupId: editorGroupService.activeGroup.id });143view = await viewsService.openView(ChatViewId) as ChatViewPane;144await view.loadSession(chatEditorInput.sessionId, chatEditor.getViewState());145} else {146view = await viewsService.openView(ChatViewId) as ChatViewPane;147}148149view.focus();150}151152153