UNPKG

isomtrik-quickchat

Version:

isomtrik-quickchat is a lightweight, real-time chat component built with Stencil JS. It is designed to be seamlessly integrated into web applications, offering customizable and responsive chat functionalities. The module supports both CommonJS and ES modu

526 lines (525 loc) 30.4 kB
import { h, getAssetPath, Host } from "@stencil/core"; import "../../../stories/Components/MessageBubble/DocumentMessageBubble/DocumentMessageBubble"; import "../../../stories/Components/MessageBubble/ImageMessageBubble/ImageMessageBubble"; import "../../../stories/Components/MessageBubble/VideoMessageBubble/VideoMessageBubble"; import "../../../stories/Components/MessageBubble/IncomingTextMessageBubble/IncomingTextMessageBubble"; import "../../../stories/Components/MessageBubble/OutgoingTextMessageBubble/OutgoingTextMessageBubble"; import { getDeviceID } from "../../../lib/helpers"; import { formatMessageDateFromTimestamp } from "../../../utils/getFomattedDate"; import "../../../stories/Components/MessageDatePill/MessageDatePill"; import "../../../stories/Components/Loader/Spinner/Spinner"; import ChatSDK from "test-iso-chat-sdk"; import "../../../global/dark-theme.css"; class ChatBody { constructor() { this.openPopup = (event, messageId) => { event.stopPropagation(); this.isPopupOpen = this.isPopupOpen === messageId ? null : messageId; }; // Function to handle scroll event and trigger API call when scrolled near the bottom this.handleScroll = () => { const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body'); if (chatBodyDiv) { const scrollTop = chatBodyDiv.scrollTop; if (scrollTop === 0 && !this.isMessageLimitEnd) { this.updateSkip(); } // if (this.scrollTimeout) { // clearTimeout(this.scrollTimeout); // } // this.scrollTimeout = setTimeout(() => { // }, 300); this.onScrollEnd(); } }; this.onScrollEnd = () => { const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body'); const scrollTop = chatBodyDiv.scrollTop; this.previousTotalScrollHeight = chatBodyDiv.scrollHeight - scrollTop; }; // Function to scroll the chat body to the bottom this.scrollToBottom = () => { const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body'); const scrollTop = chatBodyDiv.scrollTop; if (chatBodyDiv) { setTimeout(() => { chatBodyDiv.scrollTop = chatBodyDiv.scrollHeight; // Scroll to the bottom this.previousTotalScrollHeight = chatBodyDiv.scrollHeight - scrollTop; }, 200); } }; this.scrollToTop = () => { const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body'); if (chatBodyDiv) { setTimeout(() => { const toScroll = chatBodyDiv.scrollHeight - this.previousTotalScrollHeight; chatBodyDiv.scrollTop = toScroll; this.previousTotalScrollHeight = chatBodyDiv.scrollHeight; }, 0); } }; this.putReadAll = async () => { var _a; const hasUnreadMessages = this.allMessages.some(message => { var _a, _b; return ((message === null || message === void 0 ? void 0 : message.senderId) || ((_a = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _a === void 0 ? void 0 : _a.userId)) != ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId) && !message.readByAll; }); if (hasUnreadMessages) { await ChatSDK.getInstance().message.putRead({ conversationId: this.conversationId }); const newUpdatedAllMessages = (_a = this.allMessages) === null || _a === void 0 ? void 0 : _a.map(message => { var _a, _b; return (message === null || message === void 0 ? void 0 : message.readByAll) != true && ((message === null || message === void 0 ? void 0 : message.senderId) || ((_a = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _a === void 0 ? void 0 : _a.userId)) != ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId) ? Object.assign(Object.assign({}, message), { readByAll: true }) : message; }); this.updateAllMessages(newUpdatedAllMessages); } }; this.handleVisibilityChange = async () => { if (document.visibilityState === 'visible') { this.isTabActive = true; this.putReadAll(); } else { this.isTabActive = false; } }; // Add a new method to handle document clicks this.handleDocumentClick = (event) => { const target = event.target; if (!target.closest('.popup') && !target.closest('.kebab-menu')) { this.isPopupOpen = null; } }; this.isSelf = false; this.conversationId = undefined; this.skip = undefined; this.isDark = undefined; this.allMessages = undefined; this.userMetaData = undefined; this.isMessagesLoading = undefined; this.isMessageSending = undefined; this.isMessageLimitEnd = undefined; this.updateSkip = undefined; this.isScrollToBottom = undefined; this.isScrollToTop = undefined; this.deleteForAll = undefined; this.deleteForSelf = undefined; this.changeScrollToBottomState = undefined; this.changeScrollToTopState = undefined; this.updateAllMessages = undefined; this.isChatClosed = undefined; this.isChatMinimized = undefined; this.previousTotalScrollHeight = 0; this.deviceId = ''; this.scrollTimeout = null; this.isPopupOpen = null; this.deletedMessages = new Set(); this.isTabActive = true; } deleteMessageForSelf(messageId) { this.deleteForSelf({ conversationId: this.conversationId, messageIds: messageId }); this.isPopupOpen = null; } deleteMessageForEveryone(messageId) { this.deleteForAll({ conversationId: this.conversationId, messageIds: messageId }); this.isPopupOpen = null; } async componentWillLoad() { const deviceId = await getDeviceID(); this.deviceId = deviceId; } // Attach the scroll listener after the component has loaded async componentDidLoad() { document.addEventListener('visibilitychange', this.handleVisibilityChange); document.addEventListener('click', this.handleDocumentClick); const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body'); if (chatBodyDiv) { chatBodyDiv.addEventListener('scroll', this.handleScroll); // Listen to the scroll event } this.scrollToBottom(); this.putReadAll(); } async handleDataChange() { var _a, _b; if (this.isScrollToBottom && this.allMessages.length > 0 && ((_a = this.userMetaData) === null || _a === void 0 ? void 0 : _a.userId)) { this.scrollToBottom(); this.changeScrollToBottomState(false); } else if (this.allMessages.length > 0 && ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId) && !this.isScrollToBottom && this.isScrollToTop) { this.scrollToTop(); this.changeScrollToTopState(false); } if (!this.isChatMinimized && !this.isChatClosed && this.isTabActive) { this.putReadAll(); } } // Clean up the scroll listener when the component is removed disconnectedCallback() { document.removeEventListener('visibilitychange', this.handleVisibilityChange); document.removeEventListener('click', this.handleDocumentClick); const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body'); if (chatBodyDiv) { chatBodyDiv.removeEventListener('scroll', this.handleScroll); // Remove the scroll listener } } render() { var _a; const backgroundImage = getAssetPath('https://isometrik-website-bucket.s3.ap-south-1.amazonaws.com/chat_BG_8a53348931.png'); return (h(Host, { key: '3986d01d3b846ad517b2c61f6fe716bf7503b394' }, h("div", { key: '05072e8c6db5067a8176f1aaaed88fe4239326f7', id: 'lol', class: "chat-body chat-body-bg", style: { backgroundColor: 'var(--chat-body-bg)', backgroundImage: `url(${backgroundImage})`, display: 'flex', flexGrow: '1', flexDirection: 'column', gap: '20px', padding: '10px 15px 35px 10px', overflowY: 'scroll', } }, this.isMessagesLoading && (h("spinner-loader", { key: '95f62ae1152616164dba87849942e87d4c16cc0a', height: "20px", width: "20px", spinTime: "1s", spinnerPrimaryColor: "#000", spinnerSecondaryColor: "#F9E3FF", spinnerBorderWidth: "3px" })), this.allMessages.length > 0 && ((_a = this.userMetaData) === null || _a === void 0 ? void 0 : _a.userId) && this.allMessages.map((message, index) => { var _a, _b, _c; const currentMessageDate = formatMessageDateFromTimestamp(this.allMessages[index].sentAt); const previousMessageDate = formatMessageDateFromTimestamp(((_a = this.allMessages[index - 1]) === null || _a === void 0 ? void 0 : _a.sentAt) || ''); const showDatePill = currentMessageDate !== previousMessageDate; if (message.attachments) { return (h("div", { style: { display: 'flex', width: '100%', flexDirection: 'column', gap: '15px' } }, showDatePill && (h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))), message.attachments.map((attachment) => { var _a, _b; if (((message === null || message === void 0 ? void 0 : message.senderId) || ((_a = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _a === void 0 ? void 0 : _a.userId)) == ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId)) { return (h("div", { id: "outgoing-message", style: { position: 'relative', display: 'flex', width: '100%', justifyContent: 'right' } }, attachment.mimeType.startsWith('application/') ? (h("document-message", { docType: attachment.mimeType, fileName: attachment.name, href: attachment.mediaUrl, bgColor: 'var(--chat-outgoing-msg-bg)', width: "220px", padding: "10px 10px 30px 10px", borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, docName: attachment.name, isRead: message.readByAll, isSelf: true, isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` })) : attachment.mimeType.startsWith('video/') ? (h("video-message", { height: '180px', width: '200px', padding: "10px 10px 20px 10px", bgColor: 'var(--chat-outgoing-msg-bg)', isSelf: true, borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, type: attachment.mimeType, videoSrc: attachment.mediaUrl, isRead: message.readByAll, isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` })) : attachment.mimeType.startsWith('image/') ? (h("image-message", { bgColor: 'var(--chat-outgoing-msg-bg)', padding: "10px 10px 20px 10px", isSelf: true, borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, imageSrc: attachment.mediaUrl, height: '150px', width: '150px', isRead: message.readByAll, borderWidth: '5px', borderColor: 'var(--chat-outgoing-msg-bg)', borderStyle: 'solid', isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` })) : (''), h("span", { class: "kebab-menu", style: { cursor: 'pointer', position: 'absolute', right: '-12px ', top: '5px' }, onClick: e => this.openPopup(e, message === null || message === void 0 ? void 0 : message.messageId) }, h("svg", { width: "14px", height: "14px", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg", fill: 'var(--chat-msg-info-icon)', class: "bi bi-three-dots-vertical" }, h("g", { id: "SVGRepo_bgCarrier", "stroke-width": "0" }), h("g", { id: "SVGRepo_tracerCarrier", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("g", { id: "SVGRepo_iconCarrier" }, h("path", { d: "M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" })))), this.isPopupOpen === (message === null || message === void 0 ? void 0 : message.messageId) ? (h("div", { class: "popup" }, h("span", { class: "deleteText", onClick: () => this.deleteMessageForSelf(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For Me"), h("span", { class: "deleteText", onClick: () => this.deleteMessageForEveryone(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For All"))) : null)); } else { return (h("div", { style: { display: 'flex', width: '100%', justifyContent: 'left' } }, attachment.mimeType.startsWith('application/') ? (h("document-message", { docType: attachment.mimeType, fileName: attachment.name, href: attachment.mediaUrl, bgColor: 'var(--chat-incoming-msg-bg)', width: "220px", padding: "10px 10px 30px 10px", borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, docName: attachment.name, isSelf: false })) : attachment.mimeType.startsWith('video/') ? (h("video-message", { height: '180px', width: '200px', bgColor: 'var(--chat-incoming-msg-bg)', padding: "10px 10px 20px 10px", borderRadius: "6px", isSelf: false, time: message === null || message === void 0 ? void 0 : message.sentAt, type: attachment.mimeType, videoSrc: attachment.mediaUrl })) : attachment.mimeType.startsWith('image/') ? (h("image-message", { bgColor: 'var(--chat-incoming-msg-bg)', padding: "10px 10px 20px 10px", borderRadius: "6px", isSelf: false, time: message === null || message === void 0 ? void 0 : message.sentAt, imageSrc: attachment.mediaUrl, height: '150px', width: '150px', borderWidth: '5px', borderColor: 'var(--chat-incoming-msg-bg)', borderStyle: 'solid' })) : (''))); } }))); } else if (message.body) { if (((message === null || message === void 0 ? void 0 : message.senderId) || ((_b = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _b === void 0 ? void 0 : _b.userId)) == ((_c = this.userMetaData) === null || _c === void 0 ? void 0 : _c.userId)) { return (h("div", { style: { display: 'flex', width: '100%', flexDirection: 'column', gap: '15px' } }, showDatePill && (h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))), h("div", { id: "outgoing-message", style: { position: 'relative', display: 'flex', width: '100%', justifyContent: 'end' } }, h("outgoing-text-message-bubble", { msgTextColor: 'var(--chat-outgoing-msg-text)', msgTextTimeColor: 'var(--chat-outgoing-msg-time-text)', isRead: message.readByAll, padding: "10px 10px 1px 10px", borderRadius: "10px 10px 0 10px", textContent: message === null || message === void 0 ? void 0 : message.body, time: message === null || message === void 0 ? void 0 : message.sentAt, bgColor: 'var(--chat-outgoing-msg-bg)', isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` }), h("span", { class: "kebab-menu", style: { cursor: 'pointer', position: 'absolute', right: '-12px ', top: '5px' }, onClick: e => this.openPopup(e, message === null || message === void 0 ? void 0 : message.messageId) }, h("svg", { width: "14px", height: "14px", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg", fill: 'var(--chat-msg-info-icon, #000)', class: "bi bi-three-dots-vertical" }, h("g", { id: "SVGRepo_bgCarrier", "stroke-width": "0" }), h("g", { id: "SVGRepo_tracerCarrier", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("g", { id: "SVGRepo_iconCarrier" }, h("path", { d: "M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" })))), this.isPopupOpen === (message === null || message === void 0 ? void 0 : message.messageId) ? (h("div", { class: "popup" }, h("span", { class: "deleteText", onClick: () => this.deleteMessageForSelf(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For Me"), h("span", { class: "deleteText", onClick: () => this.deleteMessageForEveryone(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For All"))) : null))); } else { return (h("div", { style: { display: 'flex', width: '100%', flexDirection: 'column', gap: '15px' } }, showDatePill && (h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))), h("incoming-text-message-bubble", { bgColor: 'var(--chat-incoming-msg-bg)', msgTextTimeColor: 'var(--chat-incoming-msg-time-text)', msgTextColor: 'var(--chat-incoming-msg-text)', borderRadius: "10px 10px 10px 0", time: message === null || message === void 0 ? void 0 : message.sentAt, textContent: message === null || message === void 0 ? void 0 : message.body }))); } } else if (message.action == 'conversationCreated') { return (h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, showDatePill && h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))); } })))); } static get is() { return "chat-body"; } static get encapsulation() { return "shadow"; } static get styles() { return ":host {\n flex-grow: 1;\n overflow: hidden;\n display: flex;\n background-color: var(--chat-body-bg);\n}\n \n\n #outgoing-message > * {\n display: flex;\n width: 100%;\n justify-content: end;\n }\n\n ::-webkit-scrollbar {\n width: 5px;\n }\n\n ::-webkit-scrollbar-track {\n background: transparent;\n }\n ::-webkit-scrollbar-thumb {\n background-color: #F9E3FF !important;\n border-radius: 10px;\n }\n .popup {\n position: absolute;\n bottom: 100%;\n box-shadow: 0px 0px 10px 0px GRAY;\n z-index: 10;\n display: flex !important;\n flex-direction: column !important;\n align-items: center !important;\n justify-content: center !important;\n width: 30% !important;\n gap: 16px !important;\n background-color: #FFFFFF;\n font-family: 'Roboto';\n padding: 10px;\n font-weight:500;\n border-radius: 8px;\n }\n\n .popup span {\n cursor: pointer;\n }\n #outgoing-message .kebab-menu {\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n #outgoing-message:hover .kebab-menu {\n opacity: 1;\n }\n\n .deleteText {\n font-size: 14px;\n font-weight: 700;\n }"; } static get properties() { return { "conversationId": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "conversation-id", "reflect": false }, "skip": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "skip", "reflect": false }, "isDark": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "" }, "attribute": "is-dark", "reflect": false }, "allMessages": { "type": "any", "mutable": false, "complexType": { "original": "any", "resolved": "any", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "all-messages", "reflect": false }, "userMetaData": { "type": "any", "mutable": false, "complexType": { "original": "any", "resolved": "any", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "user-meta-data", "reflect": false }, "isMessagesLoading": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-messages-loading", "reflect": false }, "isMessageSending": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-message-sending", "reflect": false }, "isMessageLimitEnd": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-message-limit-end", "reflect": false }, "updateSkip": { "type": "unknown", "mutable": false, "complexType": { "original": "() => void", "resolved": "() => void", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" } }, "isScrollToBottom": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-scroll-to-bottom", "reflect": false }, "isScrollToTop": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-scroll-to-top", "reflect": false }, "deleteForAll": { "type": "unknown", "mutable": false, "complexType": { "original": "({ conversationId, messageIds }) => void", "resolved": "({ conversationId, messageIds }: { conversationId: any; messageIds: any; }) => void", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" } }, "deleteForSelf": { "type": "unknown", "mutable": false, "complexType": { "original": "({ conversationId, messageIds }) => void", "resolved": "({ conversationId, messageIds }: { conversationId: any; messageIds: any; }) => void", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" } }, "changeScrollToBottomState": { "type": "unknown", "mutable": false, "complexType": { "original": "(newState: boolean) => void", "resolved": "(newState: boolean) => void", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" } }, "changeScrollToTopState": { "type": "unknown", "mutable": false, "complexType": { "original": "(newState: boolean) => void", "resolved": "(newState: boolean) => void", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" } }, "updateAllMessages": { "type": "unknown", "mutable": false, "complexType": { "original": "(newMessages: any) => void", "resolved": "(newMessages: any) => void", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" } }, "isChatClosed": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-chat-closed", "reflect": false }, "isChatMinimized": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "is-chat-minimized", "reflect": false } }; } static get states() { return { "isSelf": {}, "previousTotalScrollHeight": {}, "deviceId": {}, "scrollTimeout": {}, "isPopupOpen": {}, "deletedMessages": {}, "isTabActive": {} }; } static get elementRef() { return "chatBodyElement"; } static get watchers() { return [{ "propName": "allMessages", "methodName": "handleDataChange" }, { "propName": "userMetaData", "methodName": "handleDataChange" }]; } } export { ChatBody }; //# sourceMappingURL=ChatBody.js.map