Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/browser/chatContentParts/chatProgressContentPart.ts
3296 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 { $, append } from '../../../../../base/browser/dom.js';
7
import { alert } from '../../../../../base/browser/ui/aria/aria.js';
8
import { Codicon } from '../../../../../base/common/codicons.js';
9
import { MarkdownString } from '../../../../../base/common/htmlContent.js';
10
import { Disposable } from '../../../../../base/common/lifecycle.js';
11
import { ThemeIcon } from '../../../../../base/common/themables.js';
12
import { MarkdownRenderer } from '../../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';
13
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
14
import { localize } from '../../../../../nls.js';
15
import { IChatProgressMessage, IChatTask, IChatTaskSerialized } from '../../common/chatService.js';
16
import { IChatRendererContent, isResponseVM } from '../../common/chatViewModel.js';
17
import { ChatTreeItem } from '../chat.js';
18
import { renderFileWidgets } from '../chatInlineAnchorWidget.js';
19
import { IChatContentPart, IChatContentPartRenderContext } from './chatContentParts.js';
20
import { IChatMarkdownAnchorService } from './chatMarkdownAnchorService.js';
21
22
export class ChatProgressContentPart extends Disposable implements IChatContentPart {
23
public readonly domNode: HTMLElement;
24
25
private readonly showSpinner: boolean;
26
private readonly isHidden: boolean;
27
28
constructor(
29
progress: IChatProgressMessage | IChatTask | IChatTaskSerialized,
30
renderer: MarkdownRenderer,
31
context: IChatContentPartRenderContext,
32
forceShowSpinner: boolean | undefined,
33
forceShowMessage: boolean | undefined,
34
icon: ThemeIcon | undefined,
35
@IInstantiationService private readonly instantiationService: IInstantiationService,
36
@IChatMarkdownAnchorService private readonly chatMarkdownAnchorService: IChatMarkdownAnchorService,
37
) {
38
super();
39
40
const followingContent = context.content.slice(context.contentIndex + 1);
41
this.showSpinner = forceShowSpinner ?? shouldShowSpinner(followingContent, context.element);
42
this.isHidden = forceShowMessage !== true && followingContent.some(part => part.kind !== 'progressMessage');
43
if (this.isHidden) {
44
// Placeholder, don't show the progress message
45
this.domNode = $('');
46
return;
47
}
48
49
if (this.showSpinner) {
50
// TODO@roblourens is this the right place for this?
51
// this step is in progress, communicate it to SR users
52
alert(progress.content.value);
53
}
54
const codicon = icon ? icon : this.showSpinner ? ThemeIcon.modify(Codicon.loading, 'spin') : Codicon.check;
55
const result = this._register(renderer.render(progress.content));
56
result.element.classList.add('progress-step');
57
renderFileWidgets(result.element, this.instantiationService, this.chatMarkdownAnchorService, this._store);
58
59
this.domNode = $('.progress-container');
60
const iconElement = $('div');
61
iconElement.classList.add(...ThemeIcon.asClassNameArray(codicon));
62
append(this.domNode, iconElement);
63
append(this.domNode, result.element);
64
}
65
66
hasSameContent(other: IChatRendererContent, followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {
67
// Progress parts render render until some other content shows up, then they hide.
68
// When some other content shows up, need to signal to be rerendered as hidden.
69
if (followingContent.some(part => part.kind !== 'progressMessage') && !this.isHidden) {
70
return false;
71
}
72
73
// Needs rerender when spinner state changes
74
const showSpinner = shouldShowSpinner(followingContent, element);
75
return other.kind === 'progressMessage' && this.showSpinner === showSpinner;
76
}
77
}
78
79
function shouldShowSpinner(followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {
80
return isResponseVM(element) && !element.isComplete && followingContent.length === 0;
81
}
82
83
84
export class ChatCustomProgressPart {
85
public readonly domNode: HTMLElement;
86
87
constructor(
88
messageElement: HTMLElement,
89
icon: ThemeIcon,
90
) {
91
this.domNode = $('.progress-container');
92
const iconElement = $('div');
93
iconElement.classList.add(...ThemeIcon.asClassNameArray(icon));
94
append(this.domNode, iconElement);
95
96
messageElement.classList.add('progress-step');
97
append(this.domNode, messageElement);
98
}
99
}
100
101
export class ChatWorkingProgressContentPart extends ChatProgressContentPart implements IChatContentPart {
102
constructor(
103
_workingProgress: { kind: 'working' },
104
renderer: MarkdownRenderer,
105
context: IChatContentPartRenderContext,
106
@IInstantiationService instantiationService: IInstantiationService,
107
@IChatMarkdownAnchorService chatMarkdownAnchorService: IChatMarkdownAnchorService,
108
) {
109
const progressMessage: IChatProgressMessage = {
110
kind: 'progressMessage',
111
content: new MarkdownString().appendText(localize('workingMessage', "Working..."))
112
};
113
super(progressMessage, renderer, context, undefined, undefined, undefined, instantiationService, chatMarkdownAnchorService);
114
}
115
116
override hasSameContent(other: IChatRendererContent, followingContent: IChatRendererContent[], element: ChatTreeItem): boolean {
117
return other.kind === 'working';
118
}
119
}
120
121