Path: blob/main/src/vs/workbench/contrib/chat/browser/chatContentParts/chatProgressContentPart.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 { $, append } from '../../../../../base/browser/dom.js';6import { alert } from '../../../../../base/browser/ui/aria/aria.js';7import { Codicon } from '../../../../../base/common/codicons.js';8import { MarkdownString } from '../../../../../base/common/htmlContent.js';9import { Disposable } from '../../../../../base/common/lifecycle.js';10import { ThemeIcon } from '../../../../../base/common/themables.js';11import { MarkdownRenderer } from '../../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';12import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';13import { localize } from '../../../../../nls.js';14import { IChatProgressMessage, IChatTask, IChatTaskSerialized } from '../../common/chatService.js';15import { IChatRendererContent, isResponseVM } from '../../common/chatViewModel.js';16import { ChatTreeItem } from '../chat.js';17import { renderFileWidgets } from '../chatInlineAnchorWidget.js';18import { IChatContentPart, IChatContentPartRenderContext } from './chatContentParts.js';19import { IChatMarkdownAnchorService } from './chatMarkdownAnchorService.js';2021export class ChatProgressContentPart extends Disposable implements IChatContentPart {22public readonly domNode: HTMLElement;2324private readonly showSpinner: boolean;25private readonly isHidden: boolean;2627constructor(28progress: IChatProgressMessage | IChatTask | IChatTaskSerialized,29renderer: MarkdownRenderer,30context: IChatContentPartRenderContext,31forceShowSpinner: boolean | undefined,32forceShowMessage: boolean | undefined,33icon: ThemeIcon | undefined,34@IInstantiationService private readonly instantiationService: IInstantiationService,35@IChatMarkdownAnchorService private readonly chatMarkdownAnchorService: IChatMarkdownAnchorService,36) {37super();3839const followingContent = context.content.slice(context.contentIndex + 1);40this.showSpinner = forceShowSpinner ?? shouldShowSpinner(followingContent, context.element);41this.isHidden = forceShowMessage !== true && followingContent.some(part => part.kind !== 'progressMessage');42if (this.isHidden) {43// Placeholder, don't show the progress message44this.domNode = $('');45return;46}4748if (this.showSpinner) {49// TODO@roblourens is this the right place for this?50// this step is in progress, communicate it to SR users51alert(progress.content.value);52}53const codicon = icon ? icon : this.showSpinner ? ThemeIcon.modify(Codicon.loading, 'spin') : Codicon.check;54const result = this._register(renderer.render(progress.content));55result.element.classList.add('progress-step');56renderFileWidgets(result.element, this.instantiationService, this.chatMarkdownAnchorService, this._store);5758this.domNode = $('.progress-container');59const iconElement = $('div');60iconElement.classList.add(...ThemeIcon.asClassNameArray(codicon));61append(this.domNode, iconElement);62append(this.domNode, result.element);63}6465hasSameContent(other: IChatRendererContent, followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {66// Progress parts render render until some other content shows up, then they hide.67// When some other content shows up, need to signal to be rerendered as hidden.68if (followingContent.some(part => part.kind !== 'progressMessage') && !this.isHidden) {69return false;70}7172// Needs rerender when spinner state changes73const showSpinner = shouldShowSpinner(followingContent, element);74return other.kind === 'progressMessage' && this.showSpinner === showSpinner;75}76}7778function shouldShowSpinner(followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {79return isResponseVM(element) && !element.isComplete && followingContent.length === 0;80}818283export class ChatCustomProgressPart {84public readonly domNode: HTMLElement;8586constructor(87messageElement: HTMLElement,88icon: ThemeIcon,89) {90this.domNode = $('.progress-container');91const iconElement = $('div');92iconElement.classList.add(...ThemeIcon.asClassNameArray(icon));93append(this.domNode, iconElement);9495messageElement.classList.add('progress-step');96append(this.domNode, messageElement);97}98}99100export class ChatWorkingProgressContentPart extends ChatProgressContentPart implements IChatContentPart {101constructor(102_workingProgress: { kind: 'working' },103renderer: MarkdownRenderer,104context: IChatContentPartRenderContext,105@IInstantiationService instantiationService: IInstantiationService,106@IChatMarkdownAnchorService chatMarkdownAnchorService: IChatMarkdownAnchorService,107) {108const progressMessage: IChatProgressMessage = {109kind: 'progressMessage',110content: new MarkdownString().appendText(localize('workingMessage', "Working..."))111};112super(progressMessage, renderer, context, undefined, undefined, undefined, instantiationService, chatMarkdownAnchorService);113}114115override hasSameContent(other: IChatRendererContent, followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {116return other.kind === 'working';117}118}119120121