Skip to content

Commit 0275abc

Browse files
committed
Add back basic rendering of contributed chat status items
Fixes #311610
1 parent c4e8073 commit 0275abc

2 files changed

Lines changed: 97 additions & 1 deletion

File tree

src/vs/workbench/contrib/chat/browser/chatStatus/chatStatusDashboard.ts

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
import { $, append, EventType, addDisposableListener, EventHelper, disposableWindowInterval, getWindow } from '../../../../../base/browser/dom.js';
77
import { Gesture, EventType as TouchEventType } from '../../../../../base/browser/touch.js';
88
import { ActionBar } from '../../../../../base/browser/ui/actionbar/actionbar.js';
9+
import { renderLabelWithIcons } from '../../../../../base/browser/ui/iconLabel/iconLabels.js';
910
import { Button } from '../../../../../base/browser/ui/button/button.js';
1011
import { Checkbox } from '../../../../../base/browser/ui/toggle/toggle.js';
1112
import { IAction, toAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from '../../../../../base/common/actions.js';
1213
import { CancellationToken, cancelOnDispose } from '../../../../../base/common/cancellation.js';
1314
import { Codicon } from '../../../../../base/common/codicons.js';
1415
import { safeIntl } from '../../../../../base/common/date.js';
1516
import { MarkdownString } from '../../../../../base/common/htmlContent.js';
16-
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
17+
import { MutableDisposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
18+
import { parseLinkedText } from '../../../../../base/common/linkedText.js';
1719
import { language } from '../../../../../base/common/platform.js';
1820
import { ThemeIcon } from '../../../../../base/common/themables.js';
1921
import { isObject } from '../../../../../base/common/types.js';
@@ -29,6 +31,7 @@ import { ICommandService } from '../../../../../platform/commands/common/command
2931
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
3032
import { IHoverService, nativeHoverDelegate } from '../../../../../platform/hover/browser/hover.js';
3133
import { IMarkdownRendererService } from '../../../../../platform/markdown/browser/markdownRenderer.js';
34+
import { Link } from '../../../../../platform/opener/browser/link.js';
3235
import { IOpenerService } from '../../../../../platform/opener/common/opener.js';
3336
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
3437
import { defaultButtonStyles, defaultCheckboxStyles } from '../../../../../platform/theme/browser/defaultStyles.js';
@@ -37,6 +40,7 @@ import { EditorResourceAccessor, SideBySideEditor } from '../../../../common/edi
3740
import { IChatEntitlementService, ChatEntitlementService, ChatEntitlement, IQuotaSnapshot, getChatPlanName } from '../../../../services/chat/common/chatEntitlementService.js';
3841
import { IEditorService } from '../../../../services/editor/common/editorService.js';
3942
import { isNewUser } from './chatStatus.js';
43+
import { IChatStatusItemService, ChatStatusEntry } from './chatStatusItemService.js';
4044
import product from '../../../../../platform/product/common/product.js';
4145
import { contrastBorder, inputValidationErrorBorder, inputValidationInfoBorder, inputValidationWarningBorder, registerColor, transparent } from '../../../../../platform/theme/common/colorRegistry.js';
4246
import { Color } from '../../../../../base/common/color.js';
@@ -134,6 +138,7 @@ export class ChatStatusDashboard extends DomWidget {
134138
constructor(
135139
private readonly options: IChatStatusDashboardOptions | undefined,
136140
@IChatEntitlementService private readonly chatEntitlementService: ChatEntitlementService,
141+
@IChatStatusItemService private readonly chatStatusItemService: IChatStatusItemService,
137142
@ICommandService private readonly commandService: ICommandService,
138143
@IConfigurationService private readonly configurationService: IConfigurationService,
139144
@IEditorService private readonly editorService: IEditorService,
@@ -257,6 +262,30 @@ export class ChatStatusDashboard extends DomWidget {
257262
this.renderInlineSuggestionsContent(this.element, token, updatePromise);
258263
}
259264

265+
// Contributions
266+
{
267+
for (const item of this.chatStatusItemService.getEntries()) {
268+
this.element.appendChild($('hr'));
269+
270+
const itemDisposables = this._store.add(new MutableDisposable());
271+
272+
let rendered = this.renderContributedChatStatusItem(item);
273+
itemDisposables.value = rendered.disposables;
274+
this.element.appendChild(rendered.element);
275+
276+
this._store.add(this.chatStatusItemService.onDidChange(e => {
277+
if (e.entry.id === item.id) {
278+
const previousElement = rendered.element;
279+
280+
rendered = this.renderContributedChatStatusItem(e.entry);
281+
itemDisposables.value = rendered.disposables;
282+
283+
previousElement.replaceWith(rendered.element);
284+
}
285+
}));
286+
}
287+
}
288+
260289
// New to Chat / Signed out
261290
{
262291
const newUser = isNewUser(this.chatEntitlementService);
@@ -460,6 +489,47 @@ export class ChatStatusDashboard extends DomWidget {
460489
}
461490
}
462491

492+
private renderContributedChatStatusItem(item: ChatStatusEntry): { element: HTMLElement; disposables: DisposableStore } {
493+
const disposables = new DisposableStore();
494+
495+
const itemElement = $('div.contribution');
496+
497+
const headerLabel = typeof item.label === 'string' ? item.label : item.label.label;
498+
const headerLink = typeof item.label === 'string' ? undefined : item.label.link;
499+
this.renderHeader(itemElement, disposables, headerLabel, headerLink ? toAction({
500+
id: 'workbench.action.openChatStatusItemLink',
501+
label: localize('learnMore', "Learn More"),
502+
tooltip: localize('learnMore', "Learn More"),
503+
class: ThemeIcon.asClassName(Codicon.linkExternal),
504+
run: () => this.runCommandAndClose(() => this.openerService.open(URI.parse(headerLink))),
505+
}) : undefined);
506+
507+
const itemBody = itemElement.appendChild($('div.body'));
508+
509+
const description = itemBody.appendChild($('span.description'));
510+
this.renderTextPlus(description, item.description, disposables);
511+
512+
if (item.detail) {
513+
const separator = itemBody.appendChild($('span.separator'));
514+
separator.textContent = '\u2014';
515+
const detail = itemBody.appendChild($('span.detail-item'));
516+
this.renderTextPlus(detail, item.detail, disposables);
517+
}
518+
519+
return { element: itemElement, disposables };
520+
}
521+
522+
private renderTextPlus(target: HTMLElement, text: string, store: DisposableStore): void {
523+
for (const node of parseLinkedText(text).nodes) {
524+
if (typeof node === 'string') {
525+
const parts = renderLabelWithIcons(node);
526+
target.append(...parts);
527+
} else {
528+
store.add(new Link(target, node, undefined, this.hoverService, this.openerService));
529+
}
530+
}
531+
}
532+
463533
private runCommandAndClose(commandOrFn: string | ((...args: unknown[]) => void), ...args: unknown[]): void {
464534
if (typeof commandOrFn === 'function') {
465535
commandOrFn(...args);

src/vs/workbench/contrib/chat/browser/chatStatus/media/chatStatus.css

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,29 @@
383383
.chat-status-bar-entry-tooltip .snooze-completions .snooze-action-bar {
384384
margin-left: auto;
385385
}
386+
387+
.chat-status-bar-entry-tooltip .contribution .body {
388+
display: flex;
389+
align-items: center;
390+
gap: 4px;
391+
font-size: 11px;
392+
overflow: hidden;
393+
min-width: 0;
394+
}
395+
396+
.chat-status-bar-entry-tooltip .contribution .body .description,
397+
.chat-status-bar-entry-tooltip .contribution .body .detail-item {
398+
overflow: hidden;
399+
text-overflow: ellipsis;
400+
white-space: nowrap;
401+
min-width: 0;
402+
}
403+
404+
.chat-status-bar-entry-tooltip .contribution .body .detail-item {
405+
color: var(--vscode-descriptionForeground);
406+
}
407+
408+
.chat-status-bar-entry-tooltip .contribution .body .separator {
409+
opacity: 0.6;
410+
padding: 0 2px;
411+
}

0 commit comments

Comments
 (0)