diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 3abdc9acf37..ca9d4bebeb7 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -144,6 +144,7 @@ export class MenuId { static readonly TestCallStack = new MenuId('TestCallStack'); static readonly TestCoverageFilterItem = new MenuId('TestCoverageFilterItem'); static readonly TouchBarContext = new MenuId('TouchBarContext'); + static readonly TitleBar = new MenuId('TitleBar'); static readonly TitleBarContext = new MenuId('TitleBarContext'); static readonly TitleBarTitleContext = new MenuId('TitleBarTitleContext'); static readonly TunnelContext = new MenuId('TunnelContext'); @@ -240,7 +241,7 @@ export class MenuId { static readonly ChatInlineResourceAnchorContext = new MenuId('ChatInlineResourceAnchorContext'); static readonly ChatInlineSymbolAnchorContext = new MenuId('ChatInlineSymbolAnchorContext'); static readonly ChatEditingCodeBlockContext = new MenuId('ChatEditingCodeBlockContext'); - static readonly ChatCommandCenter = new MenuId('ChatCommandCenter'); + static readonly ChatTitleBarMenu = new MenuId('ChatTitleBarMenu'); static readonly ChatAttachmentsContext = new MenuId('ChatAttachmentsContext'); static readonly AccessibleView = new MenuId('AccessibleView'); static readonly MultiDiffEditorFileToolbar = new MenuId('MultiDiffEditorFileToolbar'); diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index e61ae5c2a59..bbe944f87cb 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -267,7 +267,10 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart { private readonly editorActionsChangeDisposable = this._register(new DisposableStore()); private actionToolBarElement!: HTMLElement; + private globalToolbarMenu = this._register(this.menuService.createMenu(MenuId.TitleBar, this.contextKeyService)); private layoutToolbarMenu: IMenu | undefined; + + private readonly globalToolbarMenuDisposables = this._register(new DisposableStore()); private readonly editorToolbarMenuDisposables = this._register(new DisposableStore()); private readonly layoutToolbarMenuDisposables = this._register(new DisposableStore()); private readonly activityToolbarDisposables = this._register(new DisposableStore()); @@ -637,10 +640,17 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart { if (isAccountsActionVisible(this.storageService)) { actions.primary.push(ACCOUNTS_ACTIVITY_TILE_ACTION); } + actions.primary.push(GLOBAL_ACTIVITY_TITLE_ACTION); } - // --- Layout Actions + // --- Global Actions + fillInActionBarActions( + this.globalToolbarMenu.getActions(), + actions + ); + + // --- Layout Actions (always at the end) if (this.layoutToolbarMenu) { fillInActionBarActions( this.layoutToolbarMenu.getActions(), @@ -683,6 +693,9 @@ export class BrowserTitlebarPart extends Part implements ITitlebarPart { } } + this.globalToolbarMenuDisposables.clear(); + this.globalToolbarMenuDisposables.add(this.globalToolbarMenu.onDidChange(() => updateToolBarActions())); + if (update.activityActions) { this.activityToolbarDisposables.clear(); if (this.activityActionsEnabled) { diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts index 6ead9df2c35..fff8f932e20 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatActions.ts @@ -102,7 +102,7 @@ class OpenChatGlobalAction extends Action2 { } }, menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'a_open', order: 1 } @@ -471,7 +471,7 @@ export function registerChatActions() { f1: true, precondition: contextKey, menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'y_manage', order, when: contextKey @@ -516,7 +516,7 @@ export function registerChatActions() { title: localize2('configureCompletions', "Configure Code Completions..."), precondition: ChatContextKeys.enabled, menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'f_completions', order: 10, } @@ -539,7 +539,7 @@ export function stringifyItem(item: IChatRequestViewModel | IChatResponseViewMod } -// --- command center chat +// --- Title Bar Copilot Controls const defaultChat = { documentationUrl: product.defaultChatAgent?.documentationUrl ?? '', @@ -549,15 +549,30 @@ const defaultChat = { providerSetting: product.defaultChatAgent?.providerSetting ?? '', }; +// Add next to the command center if command center is disabled MenuRegistry.appendMenuItem(MenuId.CommandCenter, { - submenu: MenuId.ChatCommandCenter, - title: localize('title4', "Chat"), + submenu: MenuId.ChatTitleBarMenu, + title: localize('title4', "Copilot"), icon: Codicon.copilot, when: ContextKeyExpr.and( ChatContextKeys.supported, ContextKeyExpr.has('config.chat.commandCenter.enabled') ), - order: 10001, + order: 10001 // to the right of command center +}); + +// Add to the global title bar if command center is disabled +MenuRegistry.appendMenuItem(MenuId.TitleBar, { + submenu: MenuId.ChatTitleBarMenu, + title: localize('title4', "Copilot"), + group: 'navigation', + icon: Codicon.copilot, + when: ContextKeyExpr.and( + ChatContextKeys.supported, + ContextKeyExpr.has('config.chat.commandCenter.enabled'), + ContextKeyExpr.has('config.window.commandCenter').negate(), + ), + order: 1 }); registerAction2(class ToggleCopilotControl extends ToggleTitleBarConfigAction { @@ -566,17 +581,14 @@ registerAction2(class ToggleCopilotControl extends ToggleTitleBarConfigAction { 'chat.commandCenter.enabled', localize('toggle.chatControl', 'Copilot Controls'), localize('toggle.chatControlsDescription', "Toggle visibility of the Copilot Controls in title bar"), 5, false, - ContextKeyExpr.and( - ChatContextKeys.supported, - ContextKeyExpr.has('config.window.commandCenter') - ) + ChatContextKeys.supported ); } }); -export class ChatCommandCenterRendering extends Disposable implements IWorkbenchContribution { +export class CopilotTitleBarMenuRendering extends Disposable implements IWorkbenchContribution { - static readonly ID = 'chat.commandCenterRendering'; + static readonly ID = 'copilot.titleBarMenuRendering'; constructor( @IActionViewItemService actionViewItemService: IActionViewItemService, @@ -589,13 +601,13 @@ export class ChatCommandCenterRendering extends Disposable implements IWorkbench const contextKeySet = new Set([ChatContextKeys.Setup.signedOut.key]); - const disposable = actionViewItemService.register(MenuId.CommandCenter, MenuId.ChatCommandCenter, (action, options) => { + const disposable = actionViewItemService.register(MenuId.CommandCenter, MenuId.ChatTitleBarMenu, (action, options) => { if (!(action instanceof SubmenuItemAction)) { return undefined; } const dropdownAction = toAction({ - id: 'chat.commandCenter.more', + id: 'copilot.titleBarMenuRendering.more', label: localize('more', "More..."), run() { } }); diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.ts index 47ac7d2aaf6..71d64cc9a65 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatClearActions.ts @@ -317,7 +317,7 @@ export function registerNewChatActions() { group: 'navigation', order: 1 }, { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'a_open', order: 2 }, { diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts index 0d7d6df305d..8960ffd104a 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts @@ -265,7 +265,7 @@ class AttachFileToChatAction extends AttachFileAction { f1: false, precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.or(ActiveEditorContext.isEqualTo(TEXT_FILE_EDITOR_ID), TextCompareEditorActiveContext)), menu: [{ - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'b_chat_context', order: 15, }, { @@ -301,7 +301,7 @@ class AttachSelectionToChatAction extends Action2 { f1: false, precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.or(ActiveEditorContext.isEqualTo(TEXT_FILE_EDITOR_ID), TextCompareEditorActiveContext)), menu: [{ - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'b_chat_context', order: 10, }, { @@ -366,7 +366,7 @@ class AttachFileToEditingSessionAction extends AttachFileAction { f1: false, precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.or(ActiveEditorContext.isEqualTo(TEXT_FILE_EDITOR_ID), TextCompareEditorActiveContext)), menu: [{ - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'c_edits_context', order: 15, }, { @@ -402,7 +402,7 @@ class AttachSelectionToEditingSessionAction extends Action2 { f1: false, precondition: ContextKeyExpr.and(ChatContextKeys.enabled, ContextKeyExpr.or(ActiveEditorContext.isEqualTo(TEXT_FILE_EDITOR_ID), TextCompareEditorActiveContext)), menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'c_edits_context', order: 10, } diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatQuickInputActions.ts b/src/vs/workbench/contrib/chat/browser/actions/chatQuickInputActions.ts index 2266ef267ee..46c4ab4ed31 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatQuickInputActions.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatQuickInputActions.ts @@ -79,7 +79,7 @@ class QuickChatGlobalAction extends Action2 { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyMod.Alt | KeyCode.KeyL, }, menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'e_quickChat', order: 5 }, diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 352b47bbc3f..223c03d3ba7 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -51,7 +51,7 @@ import { LanguageModelToolsExtensionPointHandler } from '../common/tools/languag import { BuiltinToolsContribution } from '../common/tools/tools.js'; import { IVoiceChatService, VoiceChatService } from '../common/voiceChatService.js'; import { EditsChatAccessibilityHelp, PanelChatAccessibilityHelp, QuickChatAccessibilityHelp } from './actions/chatAccessibilityHelp.js'; -import { ChatCommandCenterRendering, registerChatActions } from './actions/chatActions.js'; +import { CopilotTitleBarMenuRendering, registerChatActions } from './actions/chatActions.js'; import { ACTION_ID_NEW_CHAT, registerNewChatActions } from './actions/chatClearActions.js'; import { CodeBlockActionRendering, registerChatCodeBlockActions, registerChatCodeCompareBlockActions } from './actions/chatCodeblockActions.js'; import { registerChatContextActions } from './actions/chatContextActions.js'; @@ -400,7 +400,7 @@ registerWorkbenchContribution2(ChatSlashStaticSlashCommandsContribution.ID, Chat registerWorkbenchContribution2(ChatExtensionPointHandler.ID, ChatExtensionPointHandler, WorkbenchPhase.BlockStartup); registerWorkbenchContribution2(LanguageModelToolsExtensionPointHandler.ID, LanguageModelToolsExtensionPointHandler, WorkbenchPhase.BlockRestore); registerWorkbenchContribution2(ChatCompatibilityNotifier.ID, ChatCompatibilityNotifier, WorkbenchPhase.Eventually); -registerWorkbenchContribution2(ChatCommandCenterRendering.ID, ChatCommandCenterRendering, WorkbenchPhase.BlockRestore); +registerWorkbenchContribution2(CopilotTitleBarMenuRendering.ID, CopilotTitleBarMenuRendering, WorkbenchPhase.BlockRestore); registerWorkbenchContribution2(CodeBlockActionRendering.ID, CodeBlockActionRendering, WorkbenchPhase.BlockRestore); registerWorkbenchContribution2(ChatImplicitContextContribution.ID, ChatImplicitContextContribution, WorkbenchPhase.Eventually); registerWorkbenchContribution2(ChatRelatedFilesContribution.ID, ChatRelatedFilesContribution, WorkbenchPhase.Eventually); diff --git a/src/vs/workbench/contrib/chat/browser/chatSetup.ts b/src/vs/workbench/contrib/chat/browser/chatSetup.ts index bc95d9dd169..e8b2c184557 100644 --- a/src/vs/workbench/contrib/chat/browser/chatSetup.ts +++ b/src/vs/workbench/contrib/chat/browser/chatSetup.ts @@ -167,7 +167,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr f1: true, precondition: chatSetupTriggerContext, menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'a_last', order: 1, when: chatSetupTriggerContext @@ -203,7 +203,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr category: CHAT_CATEGORY, precondition: ChatContextKeys.Setup.installed.negate(), menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'z_hide', order: 1, when: ChatContextKeys.Setup.installed.negate() @@ -246,7 +246,7 @@ export class ChatSetupContribution extends Disposable implements IWorkbenchContr ChatContextKeys.Setup.limited, ), menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'a_first', order: 1, when: ContextKeyExpr.or( diff --git a/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts b/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts index 4779dee140a..8949a625751 100644 --- a/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts +++ b/src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts @@ -69,7 +69,7 @@ export class StartSessionAction extends Action2 { }, icon: START_INLINE_CHAT, menu: { - id: MenuId.ChatCommandCenter, + id: MenuId.ChatTitleBarMenu, group: 'd_inlineChat', order: 10, }