devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
329 lines (328 loc) • 11.5 kB
JavaScript
/**
* DevExtreme (esm/__internal/ui/chat/chat.js)
* Version: 24.2.7
* Build date: Mon Apr 28 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
import _extends from "@babel/runtime/helpers/esm/extends";
import {
Guid
} from "../../../common";
import messageLocalization from "../../../common/core/localization/message";
import registerComponent from "../../../core/component_registrator";
import $ from "../../../core/renderer";
import {
isDefined
} from "../../../core/utils/type";
import DataHelperMixin from "../../../data_helper";
import Widget from "../../core/widget/widget";
import AlertList from "../../ui/chat/alertlist";
import MessageBox from "../../ui/chat/messagebox";
import MessageList from "../../ui/chat/messagelist";
const CHAT_CLASS = "dx-chat";
const TEXTEDITOR_INPUT_CLASS = "dx-texteditor-input";
class Chat extends Widget {
_getDefaultOptions() {
return _extends({}, super._getDefaultOptions(), {
showDayHeaders: true,
activeStateEnabled: true,
focusStateEnabled: true,
hoverStateEnabled: true,
items: [],
dataSource: null,
user: {
id: (new Guid).toString()
},
dayHeaderFormat: "shortdate",
messageTemplate: null,
messageTimestampFormat: "shorttime",
alerts: [],
showAvatar: true,
showUserName: true,
showMessageTimestamp: true,
typingUsers: [],
onMessageEntered: void 0,
reloadOnChange: true,
onTypingStart: void 0,
onTypingEnd: void 0
})
}
_init() {
super._init();
this._initDataController();
this._refreshDataSource();
this._createMessageEnteredAction();
this._createTypingStartAction();
this._createTypingEndAction()
}
_dataSourceLoadErrorHandler() {
this.option("items", [])
}
_dataSourceChangedHandler(newItems, e) {
if (null !== e && void 0 !== e && e.changes) {
this._messageList._modifyByChanges(e.changes);
this._setOptionWithoutOptionChange("items", newItems.slice());
this._messageList._setOptionWithoutOptionChange("items", newItems.slice());
this._messageList._toggleEmptyView()
} else {
this.option("items", newItems.slice())
}
}
_dataSourceLoadingChangedHandler(isLoading) {
var _this$_messageList;
null === (_this$_messageList = this._messageList) || void 0 === _this$_messageList || _this$_messageList.option("isLoading", isLoading)
}
_dataSourceOptions() {
return {
paginate: false
}
}
_initMarkup() {
$(this.element()).addClass("dx-chat");
super._initMarkup();
this._renderMessageList();
this._renderAlertList();
this._renderMessageBox();
this._updateRootAria();
this._updateMessageBoxAria()
}
_renderMessageList() {
const $messageList = $("<div>");
this.$element().append($messageList);
this._messageList = this._createComponent($messageList, MessageList, this._getMessageListOptions())
}
_getMessageListOptions() {
const {
items: items = [],
user: user,
showDayHeaders: showDayHeaders = false,
showAvatar: showAvatar = false,
showUserName: showUserName = false,
showMessageTimestamp: showMessageTimestamp = false,
dayHeaderFormat: dayHeaderFormat,
messageTimestampFormat: messageTimestampFormat,
typingUsers: typingUsers = []
} = this.option();
const isLoading = this._dataController.isLoading();
const currentUserId = null === user || void 0 === user ? void 0 : user.id;
const options = {
items: items,
currentUserId: currentUserId,
messageTemplate: this._getMessageTemplate(),
showDayHeaders: showDayHeaders,
showAvatar: showAvatar,
showUserName: showUserName,
showMessageTimestamp: showMessageTimestamp,
dayHeaderFormat: dayHeaderFormat,
messageTimestampFormat: messageTimestampFormat,
typingUsers: typingUsers,
isLoading: isLoading
};
return options
}
_getMessageTemplate() {
const {
messageTemplate: messageTemplate
} = this.option();
if (messageTemplate) {
return (message, $container) => {
const template = this._getTemplateByOption("messageTemplate");
template.render({
container: $container,
model: {
component: this,
message: message
}
})
}
}
return null
}
_renderAlertList() {
const $errors = $("<div>");
this.$element().append($errors);
const {
alerts: alerts = []
} = this.option();
this._alertList = this._createComponent($errors, AlertList, {
items: alerts
})
}
_renderMessageBox() {
const {
activeStateEnabled: activeStateEnabled,
focusStateEnabled: focusStateEnabled,
hoverStateEnabled: hoverStateEnabled
} = this.option();
const $messageBox = $("<div>");
this.$element().append($messageBox);
const configuration = {
activeStateEnabled: activeStateEnabled,
focusStateEnabled: focusStateEnabled,
hoverStateEnabled: hoverStateEnabled,
onMessageEntered: e => {
this._messageEnteredHandler(e)
},
onTypingStart: e => {
this._typingStartHandler(e)
},
onTypingEnd: () => {
this._typingEndHandler()
}
};
this._messageBox = this._createComponent($messageBox, MessageBox, configuration)
}
_updateRootAria() {
const aria = {
role: "group",
label: messageLocalization.format("dxChat-elementAriaLabel")
};
this.setAria(aria, this.$element())
}
_updateMessageBoxAria() {
const emptyViewId = this._messageList.getEmptyViewId();
this._messageBox.updateInputAria(emptyViewId)
}
_createMessageEnteredAction() {
this._messageEnteredAction = this._createActionByOption("onMessageEntered", {
excludeValidators: ["disabled"]
})
}
_createTypingStartAction() {
this._typingStartAction = this._createActionByOption("onTypingStart", {
excludeValidators: ["disabled"]
})
}
_createTypingEndAction() {
this._typingEndAction = this._createActionByOption("onTypingEnd", {
excludeValidators: ["disabled"]
})
}
_messageEnteredHandler(e) {
var _this$_messageEntered;
const {
text: text,
event: event
} = e;
const {
user: user
} = this.option();
const message = {
timestamp: new Date,
author: user,
text: text
};
const dataSource = this.getDataSource();
if (isDefined(dataSource)) {
dataSource.store().insert(message).done((() => {
const {
reloadOnChange: reloadOnChange
} = this.option();
if (reloadOnChange) {
dataSource.reload()
}
}))
}
null === (_this$_messageEntered = this._messageEnteredAction) || void 0 === _this$_messageEntered || _this$_messageEntered.call(this, {
message: message,
event: event
})
}
_typingStartHandler(e) {
var _this$_typingStartAct;
const {
event: event
} = e;
const {
user: user
} = this.option();
null === (_this$_typingStartAct = this._typingStartAction) || void 0 === _this$_typingStartAct || _this$_typingStartAct.call(this, {
user: user,
event: event
})
}
_typingEndHandler() {
var _this$_typingEndActio;
const {
user: user
} = this.option();
null === (_this$_typingEndActio = this._typingEndAction) || void 0 === _this$_typingEndActio || _this$_typingEndActio.call(this, {
user: user
})
}
_focusTarget() {
const $input = $(this.element()).find(".dx-texteditor-input");
return $input
}
_optionChanged(args) {
const {
name: name,
value: value
} = args;
switch (name) {
case "activeStateEnabled":
case "focusStateEnabled":
case "hoverStateEnabled":
this._messageBox.option(name, value);
break;
case "user": {
const author = value;
this._messageList.option("currentUserId", null === author || void 0 === author ? void 0 : author.id);
break
}
case "items":
this._messageList.option(name, value);
this._updateMessageBoxAria();
break;
case "dataSource":
this._refreshDataSource();
break;
case "alerts":
this._alertList.option("items", value ?? []);
break;
case "onMessageEntered":
this._createMessageEnteredAction();
break;
case "onTypingStart":
this._createTypingStartAction();
break;
case "onTypingEnd":
this._createTypingEndAction();
break;
case "showDayHeaders":
case "showAvatar":
case "showUserName":
case "showMessageTimestamp":
this._messageList.option(name, !!value);
break;
case "dayHeaderFormat":
case "messageTimestampFormat":
case "typingUsers":
this._messageList.option(name, value);
break;
case "messageTemplate":
this._messageList.option(name, this._getMessageTemplate());
break;
case "reloadOnChange":
break;
default:
super._optionChanged(args)
}
}
_insertNewItem(item) {
const {
items: items
} = this.option();
const newItems = [...items ?? [], item];
this.option("items", newItems)
}
renderMessage() {
let message = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
this._insertNewItem(message)
}
}
Chat.include(DataHelperMixin);
registerComponent("dxChat", Chat);
export default Chat;