Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 92 additions & 1 deletion packages/devextreme/js/__internal/ui/chat/messagebubble.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import messageLocalization from '@js/common/core/localization/message';
import { getPublicElement } from '@js/core/element';
import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import type { Attachment, AttachmentDownloadClickEvent, Message } from '@js/ui/chat';
import type {
Attachment, AttachmentDownloadClickEvent, Message, MetaData,
} from '@js/ui/chat';
import type { WidgetOptions } from '@js/ui/widget/ui.widget';
import { ICON_CLASS } from '@ts/core/utils/m_icon';
import type { OptionChanged } from '@ts/core/widget/types';
import Widget from '@ts/core/widget/widget';
import Accordion from '@ts/ui/accordion';
import FileView from '@ts/ui/chat/file_view/file_view';

export const CHAT_MESSAGEBUBBLE_CLASS = 'dx-chat-messagebubble';
Expand All @@ -15,6 +18,7 @@ export const CHAT_MESSAGEBUBBLE_CONTENT_CLASS = 'dx-chat-messagebubble-content';
export const CHAT_MESSAGEBUBBLE_ICON_PROHIBITION_CLASS = `${ICON_CLASS}-cursorprohibition`;
export const CHAT_MESSAGEBUBBLE_HAS_IMAGE_CLASS = 'dx-has-image';
export const CHAT_MESSAGEBUBBLE_IMAGE_CLASS = 'dx-chat-messagebubble-image';
export const CHAT_MESSAGEBUBBLE_FUNCTIONCALL_CLASS = 'dx-chat-messagebubble-functioncall';

export const MESSAGE_DATA_KEY = 'dxMessageData';

Expand All @@ -26,6 +30,9 @@ export interface Properties extends WidgetOptions<MessageBubble> {
src?: string;
alt?: string;
attachments?: Attachment[];
metadata?: MetaData;
focusStateEnabled?: boolean;
hoverStateEnabled?: boolean;
Comment on lines +34 to +35
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The focusStateEnabled and hoverStateEnabled properties are being added to MessageBubble specifically to pass through to the Accordion component. However, these options shadow the inherited focusStateEnabled and hoverStateEnabled from the parent Widget class. This creates ambiguity: MessageBubble is a Widget that has its own focus/hover states, but these properties are being used exclusively for the nested Accordion. Consider using namespaced properties like accordionFocusStateEnabled and accordionHoverStateEnabled to avoid confusion and maintain clear separation between the MessageBubble's state and the Accordion's state.

Copilot uses AI. Check for mistakes.
onAttachmentDownloadClick?: (e: AttachmentDownloadClickEvent) => void;
template?: ((message: Message, container: Element) => void) | null;
}
Expand All @@ -35,12 +42,16 @@ class MessageBubble extends Widget<Properties> {

_$attachments?: dxElementWrapper;

_$functionCall?: dxElementWrapper;

_getDefaultOptions(): Properties {
return {
...super._getDefaultOptions(),
isDeleted: false,
isEdited: false,
text: '',
focusStateEnabled: true,
hoverStateEnabled: true,
Comment on lines +53 to +54
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting default values for focusStateEnabled and hoverStateEnabled to true overrides the parent Widget class defaults. Since these are now being used to control the Accordion's state rather than the MessageBubble's own state, this could lead to unexpected behavior if the parent class has different defaults or if these properties are meant to control the MessageBubble itself. Consider whether these defaults should be set at the Accordion initialization level instead.

Suggested change
focusStateEnabled: true,
hoverStateEnabled: true,

Copilot uses AI. Check for mistakes.
template: null,
};
}
Expand All @@ -53,9 +64,11 @@ class MessageBubble extends Widget<Properties> {
super._initMarkup();

this._renderContentContainer();
this._renderFunctionCallElement();
this._renderAttachmentsElement();

this._updateContent();
this._renderFunctionCall();
this._renderAttachments();
}

Expand All @@ -65,6 +78,19 @@ class MessageBubble extends Widget<Properties> {
.appendTo(this.$element());
}

_renderFunctionCallElement(): void {
const { metadata, isDeleted } = this.option();

this._$functionCall?.remove();
this._$functionCall = undefined;

if (metadata?.functionCall && !isDeleted) {
this._$functionCall = $('<div>')
.addClass(CHAT_MESSAGEBUBBLE_FUNCTIONCALL_CLASS)
.appendTo(this.$element());
}
}

_renderAttachmentsElement(): void {
const { attachments, isDeleted } = this.option();

Expand Down Expand Up @@ -132,6 +158,63 @@ class MessageBubble extends Widget<Properties> {
}
}

_renderFunctionCall(): void {
const { metadata } = this.option();

if (!this._$functionCall || !metadata?.functionCall) {
return;
}

this._$functionCall.empty();

const { functionCall } = metadata;

const accordionItems = [{
title: messageLocalization.format('dxChat-functionCallTitle'),
template: (): dxElementWrapper => {
const $content = $('<div>');

const $functionName = $('<div>')
.append($('<strong>').text(`${messageLocalization.format('dxChat-functionCallLabel')}: `))
.append($('<span>').text(functionCall.name));

const args = functionCall.arguments || [];
const argumentsText = args.length > 0
? args.map((arg) => Object.entries(arg)
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
.join(', '))
.join(', ')
: '';

const $arguments = $('<div>')
.append($('<strong>').text(`${messageLocalization.format('dxChat-argumentsLabel')}: `))
.append($('<span>').text(argumentsText));

const $result = $('<div>')
.append($('<strong>').text(`${messageLocalization.format('dxChat-resultLabel')}: `))
.append($('<span>').text(JSON.stringify(functionCall.result)));

$content.append($functionName).append($arguments).append($result);

return $content;
},
}];

const {
focusStateEnabled,
hoverStateEnabled,
} = this.option();

this._createComponent(this._$functionCall, Accordion, {
dataSource: accordionItems,
collapsible: true,
multiple: false,
selectedIndex: -1,
focusStateEnabled,
hoverStateEnabled,
});
Comment on lines +208 to +215
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Accordion component instance is created but not stored as a class property (e.g., this._accordionInstance). This makes it impossible to update the component's options later without re-creating it entirely. Store the instance returned by _createComponent to enable efficient updates when options change.

Copilot uses AI. Check for mistakes.
}

_renderAttachments(): void {
const {
attachments,
Expand Down Expand Up @@ -183,6 +266,14 @@ class MessageBubble extends Widget<Properties> {
case 'isEdited':
this._updateMessageData(name, value);
break;
case 'metadata':
this._renderFunctionCallElement();
this._renderFunctionCall();
break;
case 'focusStateEnabled':
case 'hoverStateEnabled':
this._renderFunctionCall();
break;
Comment on lines +273 to +276
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When focusStateEnabled or hoverStateEnabled options change, the entire function call accordion is re-rendered by calling _renderFunctionCall(). This completely destroys and recreates the Accordion component even when only state options need to be updated. Consider updating the existing Accordion instance's options using this._accordionInstance.option(name, value) instead of full re-rendering for better performance.

Copilot uses AI. Check for mistakes.
case 'onAttachmentDownloadClick':
case 'attachments':
this._renderAttachmentsElement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ class MessageGroup extends Widget<Properties> {
options.src = (message as ImageMessage).src;
} else {
options.text = (message as TextMessage).text;
options.metadata = (message as TextMessage).metadata;
}

if (messageTemplate) {
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "أحمر",
"dxColorView-ariaGreen": "أخضر",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Red",
"dxColorView-ariaGreen": "Green",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Vermell",
"dxColorView-ariaGreen": "Verd",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Červená",
"dxColorView-ariaGreen": "Zelená",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rød",
"dxColorView-ariaGreen": "Grøn",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rot",
"dxColorView-ariaGreen": "Grün",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Κόκκινο",
"dxColorView-ariaGreen": "Πράσινο",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent capitalization: 'function called' should be 'Function Called' to match the capitalization pattern of other similar labels in the localization file.

Copilot uses AI. Check for mistakes.
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Red",
"dxColorView-ariaGreen": "Green",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rojo",
"dxColorView-ariaGreen": "Verde",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "قرمز",
"dxColorView-ariaGreen": "سبز",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Punainen",
"dxColorView-ariaGreen": "Vihreä",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rouge",
"dxColorView-ariaGreen": "Vert",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/hu.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Piros",
"dxColorView-ariaGreen": "Zöld",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rosso",
"dxColorView-ariaGreen": "Verde",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "赤",
"dxColorView-ariaGreen": "緑",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/lt.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Raudona",
"dxColorView-ariaGreen": "Žalia",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/lv.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Sarkans",
"dxColorView-ariaGreen": "Zaļš",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rød",
"dxColorView-ariaGreen": "Grønn",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "Rood",
"dxColorView-ariaGreen": "Groen",
Expand Down
4 changes: 4 additions & 0 deletions packages/devextreme/js/localization/messages/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@
"dxChat-fileViewLabel": "File list",
"dxChat-downloadButtonLabel": "Download file {0}",
"dxChat-fileLimitReachedWarning": "You selected too many files. Select no more than {0} files and retry.",
"dxChat-functionCallTitle": "function called",
"dxChat-functionCallLabel": "Function Called",
"dxChat-argumentsLabel": "Arguments",
"dxChat-resultLabel": "Result",

"dxColorView-ariaRed": "czerwony",
"dxColorView-ariaGreen": "zielony",
Expand Down
Loading
Loading