Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/browser/parts/chatBarPart.ts
13395 views
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 './media/chatBarPart.css';
7
import { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';
8
import { IContextMenuService } from '../../../platform/contextview/browser/contextView.js';
9
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
10
import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';
11
import { INotificationService } from '../../../platform/notification/common/notification.js';
12
import { IStorageService } from '../../../platform/storage/common/storage.js';
13
import { IThemeService } from '../../../platform/theme/common/themeService.js';
14
import { PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_DRAG_AND_DROP_BORDER, PANEL_INACTIVE_TITLE_FOREGROUND, SIDE_BAR_TITLE_BORDER } from '../../../workbench/common/theme.js';
15
import { agentsPanelBackground, agentsPanelBorder, agentsPanelForeground, agentsBadgeBackground, agentsBadgeForeground } from '../../common/theme.js';
16
import { IViewDescriptorService, ViewContainerLocation } from '../../../workbench/common/views.js';
17
import { IExtensionService } from '../../../workbench/services/extensions/common/extensions.js';
18
import { IWorkbenchLayoutService, Parts } from '../../../workbench/services/layout/browser/layoutService.js';
19
import { HoverPosition } from '../../../base/browser/ui/hover/hoverWidget.js';
20
import { assertReturnsDefined } from '../../../base/common/types.js';
21
import { LayoutPriority } from '../../../base/browser/ui/splitview/splitview.js';
22
import { AbstractPaneCompositePart, CompositeBarPosition } from '../../../workbench/browser/parts/paneCompositePart.js';
23
import { Part } from '../../../workbench/browser/part.js';
24
import { ActionsOrientation } from '../../../base/browser/ui/actionbar/actionbar.js';
25
import { IPaneCompositeBarOptions } from '../../../workbench/browser/parts/paneCompositeBar.js';
26
import { IMenuService } from '../../../platform/actions/common/actions.js';
27
import { IHoverService } from '../../../platform/hover/browser/hover.js';
28
import { Extensions } from '../../../workbench/browser/panecomposite.js';
29
import { Menus } from '../menus.js';
30
import { ActiveChatBarContext, ChatBarFocusContext } from '../../common/contextkeys.js';
31
import { ChatCompositeBar } from './chatCompositeBar.js';
32
import { prepend } from '../../../base/browser/dom.js';
33
34
export class ChatBarPart extends AbstractPaneCompositePart { // TODO: should not be a AbstractPaneCompositePart but instead a custom Part with a CompositeBar
35
36
static readonly activeViewSettingsKey = 'workbench.chatbar.activepanelid';
37
static readonly pinnedViewsKey = 'workbench.chatbar.pinnedPanels';
38
static readonly placeholderViewContainersKey = 'workbench.chatbar.placeholderPanels';
39
static readonly viewContainersWorkspaceStateKey = 'workbench.chatbar.viewContainersWorkspaceState';
40
41
override readonly minimumWidth: number = 300;
42
override readonly maximumWidth: number = Number.POSITIVE_INFINITY;
43
override readonly minimumHeight: number = 0;
44
override readonly maximumHeight: number = Number.POSITIVE_INFINITY;
45
override get snap(): boolean { return false; }
46
47
/** Visual margin values for the card-like appearance */
48
static readonly MARGIN_TOP = 10;
49
static readonly MARGIN_LEFT = 10;
50
static readonly MARGIN_RIGHT = 10;
51
static readonly MARGIN_BOTTOM = 0;
52
53
/** Border width on the card (1px each side) */
54
static readonly BORDER_WIDTH = 1;
55
56
/** Height of the session composite bar when visible */
57
private static readonly SESSION_BAR_HEIGHT = 35;
58
59
private _sessionCompositeBar: ChatCompositeBar | undefined;
60
61
protected _lastLayout: { readonly width: number; readonly height: number; readonly top: number; readonly left: number } | undefined;
62
63
get preferredHeight(): number | undefined {
64
return this.layoutService.mainContainerDimension.height * 0.4;
65
}
66
67
readonly priority = LayoutPriority.High;
68
69
constructor(
70
@INotificationService notificationService: INotificationService,
71
@IStorageService storageService: IStorageService,
72
@IContextMenuService contextMenuService: IContextMenuService,
73
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
74
@IKeybindingService keybindingService: IKeybindingService,
75
@IHoverService hoverService: IHoverService,
76
@IInstantiationService instantiationService: IInstantiationService,
77
@IThemeService themeService: IThemeService,
78
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
79
@IContextKeyService contextKeyService: IContextKeyService,
80
@IExtensionService extensionService: IExtensionService,
81
@IMenuService menuService: IMenuService
82
) {
83
super(
84
Parts.CHATBAR_PART,
85
{
86
hasTitle: false,
87
trailingSeparator: true,
88
borderWidth: () => 0,
89
},
90
ChatBarPart.activeViewSettingsKey,
91
ActiveChatBarContext.bindTo(contextKeyService),
92
ChatBarFocusContext.bindTo(contextKeyService),
93
'chatbar',
94
'chatbar',
95
undefined,
96
SIDE_BAR_TITLE_BORDER,
97
ViewContainerLocation.ChatBar,
98
Extensions.ChatBar,
99
Menus.ChatBarTitle,
100
notificationService,
101
storageService,
102
contextMenuService,
103
layoutService,
104
keybindingService,
105
hoverService,
106
instantiationService,
107
themeService,
108
viewDescriptorService,
109
contextKeyService,
110
extensionService,
111
menuService,
112
);
113
}
114
115
override create(parent: HTMLElement): void {
116
super.create(parent);
117
118
// Create the session composite bar and prepend it before the content area
119
this._sessionCompositeBar = this._register(this.instantiationService.createInstance(ChatCompositeBar));
120
prepend(parent, this._sessionCompositeBar.element);
121
122
// Relayout when session bar visibility changes
123
this._register(this._sessionCompositeBar.onDidChangeVisibility(() => {
124
if (this._lastLayout) {
125
this.layout(this._lastLayout.width, this._lastLayout.height, this._lastLayout.top, this._lastLayout.left);
126
}
127
}));
128
}
129
130
override updateStyles(): void {
131
super.updateStyles();
132
133
const container = assertReturnsDefined(this.getContainer());
134
135
// Store background and border as CSS variables for the card styling on .part
136
container.style.setProperty('--part-background', this.getColor(agentsPanelBackground) || '');
137
container.style.setProperty('--part-border-color', this.getColor(agentsPanelBorder) || 'transparent');
138
container.style.setProperty('--part-foreground', this.getColor(agentsPanelForeground) || '');
139
container.style.backgroundColor = this.getColor(agentsPanelBackground) || '';
140
}
141
142
override layout(width: number, height: number, top: number, left: number): void {
143
if (!this.layoutService.isVisible(Parts.CHATBAR_PART)) {
144
return;
145
}
146
147
this._lastLayout = { width, height, top, left };
148
149
// Account for the session composite bar height when visible
150
const sessionBarHeight = this._sessionCompositeBar?.visible ? ChatBarPart.SESSION_BAR_HEIGHT : 0;
151
152
// Layout content with reduced dimensions to account for visual margins and border
153
const borderTotal = ChatBarPart.BORDER_WIDTH * 2;
154
const marginLeft = this.layoutService.isVisible(Parts.SIDEBAR_PART) ? 0 : ChatBarPart.MARGIN_LEFT;
155
super.layout(
156
width - marginLeft - ChatBarPart.MARGIN_RIGHT - borderTotal,
157
height - ChatBarPart.MARGIN_TOP - ChatBarPart.MARGIN_BOTTOM - borderTotal - sessionBarHeight,
158
top, left
159
);
160
161
// Restore the full grid-allocated dimensions so that Part.relayout() works correctly.
162
Part.prototype.layout.call(this, width, height, top, left);
163
}
164
165
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
166
return {
167
partContainerClass: 'chatbar',
168
pinnedViewContainersKey: ChatBarPart.pinnedViewsKey,
169
placeholderViewContainersKey: ChatBarPart.placeholderViewContainersKey,
170
viewContainersWorkspaceStateKey: ChatBarPart.viewContainersWorkspaceStateKey,
171
icon: false,
172
orientation: ActionsOrientation.HORIZONTAL,
173
recomputeSizes: true,
174
activityHoverOptions: {
175
position: () => HoverPosition.BELOW,
176
},
177
fillExtraContextMenuActions: () => { },
178
compositeSize: 0,
179
iconSize: 16,
180
overflowActionSize: 30,
181
colors: theme => ({
182
activeBackgroundColor: theme.getColor(agentsPanelBackground),
183
inactiveBackgroundColor: theme.getColor(agentsPanelBackground),
184
activeBorderBottomColor: theme.getColor(PANEL_ACTIVE_TITLE_BORDER),
185
activeForegroundColor: theme.getColor(PANEL_ACTIVE_TITLE_FOREGROUND),
186
inactiveForegroundColor: theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND),
187
badgeBackground: theme.getColor(agentsBadgeBackground),
188
badgeForeground: theme.getColor(agentsBadgeForeground),
189
dragAndDropBorder: theme.getColor(PANEL_DRAG_AND_DROP_BORDER)
190
}),
191
compact: true
192
};
193
}
194
195
protected shouldShowCompositeBar(): boolean {
196
return false;
197
}
198
199
protected getCompositeBarPosition(): CompositeBarPosition {
200
return CompositeBarPosition.TITLE;
201
}
202
203
override toJSON(): object {
204
return {
205
type: Parts.CHATBAR_PART
206
};
207
}
208
}
209
210