UNPKG

@cometchat/chat-uikit-react

Version:

Ready-to-use Chat UI Components for React

605 lines (599 loc) 23.6 kB
'use strict'; var chunkXBXSZ3KO_cjs = require('./chunk-XBXSZ3KO.cjs'); var chunkUY4YZAGJ_cjs = require('./chunk-UY4YZAGJ.cjs'); var chunkC7J4AZRB_cjs = require('./chunk-C7J4AZRB.cjs'); var chunkKMTY4OFY_cjs = require('./chunk-KMTY4OFY.cjs'); var react = require('react'); var chatSdkJavascript = require('@cometchat/chat-sdk-javascript'); var jsxRuntime = require('react/jsx-runtime'); require('./index.css'); var CometChatMessageInformationContext = react.createContext(null); function useCometChatMessageInformationContext() { const ctx = react.useContext(CometChatMessageInformationContext); if (!ctx) { throw new Error( "useCometChatMessageInformationContext must be used within <CometChatMessageInformation.Root>" ); } return ctx; } async function fetchReceipts(messageId) { return chatSdkJavascript.CometChat.getMessageReceipts(messageId); } function attachReceiptListener(listenerId, callbacks) { chatSdkJavascript.CometChat.addMessageListener( listenerId, new chatSdkJavascript.CometChat.MessageListener({ onMessagesDelivered: callbacks.onMessagesDelivered, onMessagesRead: callbacks.onMessagesRead }) ); return () => { chatSdkJavascript.CometChat.removeMessageListener(listenerId); }; } function attachConnectionListener(listenerId, onConnected) { chatSdkJavascript.CometChat.addConnectionListener( listenerId, new chatSdkJavascript.CometChat.ConnectionListener({ onConnected, onDisconnected: () => { } }) ); return () => { chatSdkJavascript.CometChat.removeConnectionListener(listenerId); }; } // src/components/CometChatMessageInformation/CometChatMessageInformation.reducer.ts var initialState = { fetchState: "idle", userReceipts: [], oneOnOneReadAt: 0, oneOnOneDeliveredAt: 0, error: null }; function messageInformationReducer(state, action) { switch (action.type) { case "FETCH_START": return { ...state, fetchState: "loading", error: null }; case "FETCH_SUCCESS_GROUP": return { ...state, fetchState: action.userReceipts.length === 0 ? "empty" : "loaded", userReceipts: action.userReceipts }; case "FETCH_SUCCESS_ONE_ON_ONE": return { ...state, fetchState: "loaded", oneOnOneReadAt: action.readAt, oneOnOneDeliveredAt: action.deliveredAt }; case "FETCH_ERROR": return { ...state, fetchState: "error", error: action.error }; case "UPDATE_RECEIPT": { const updated = state.userReceipts.map( (r) => r.user.getUid() === action.uid ? { ...r, readAt: action.readAt ?? r.readAt, deliveredAt: action.deliveredAt ?? r.deliveredAt } : r ); return { ...state, userReceipts: updated }; } case "UPDATE_ONE_ON_ONE_RECEIPT": return { ...state, oneOnOneReadAt: action.readAt ?? state.oneOnOneReadAt, oneOnOneDeliveredAt: action.deliveredAt ?? state.oneOnOneDeliveredAt }; case "RESET": return initialState; default: return state; } } // src/components/CometChatMessageInformation/useCometChatMessageInformation.ts function useCometChatMessageInformation(options) { const { message, onError } = options; const [state, dispatch] = react.useReducer(messageInformationReducer, initialState); const fetchIdRef = react.useRef(""); const loggedInUserRef = react.useRef(""); const instanceId = react.useId(); const isGroupMessage = message.getReceiverType() === chatSdkJavascript.CometChat.RECEIVER_TYPE.GROUP; const handleError = react.useCallback( (error) => { onError?.(error); const errorMessage = error instanceof Error ? error.message : "Unknown error"; dispatch({ type: "FETCH_ERROR", error: errorMessage }); }, [onError] ); const doFetchReceipts = react.useCallback(async () => { const currentFetchId = `fetch_${String(Date.now())}`; fetchIdRef.current = currentFetchId; dispatch({ type: "FETCH_START" }); try { if (!loggedInUserRef.current) { const user = await chatSdkJavascript.CometChat.getLoggedinUser(); if (user) { loggedInUserRef.current = user.getUid(); } } if (isGroupMessage) { const receipts = await fetchReceipts(message.getId()); if (fetchIdRef.current !== currentFetchId) return; if (receipts.length === 0) { dispatch({ type: "FETCH_SUCCESS_GROUP", userReceipts: [] }); return; } const userReceiptMap = /* @__PURE__ */ new Map(); for (const receipt of receipts) { const sender = receipt.getSender(); if (sender.getUid() === loggedInUserRef.current) { continue; } const uid = sender.getUid(); const readAt = receipt.getReadAt(); const deliveredAt = receipt.getDeliveredAt(); const existing = userReceiptMap.get(uid); if (existing) { if (readAt > existing.readAt) existing.readAt = readAt; if (deliveredAt > existing.deliveredAt) existing.deliveredAt = deliveredAt; } else { userReceiptMap.set(uid, { user: sender, readAt, deliveredAt }); } } dispatch({ type: "FETCH_SUCCESS_GROUP", userReceipts: Array.from(userReceiptMap.values()) }); } else { if (fetchIdRef.current !== currentFetchId) return; dispatch({ type: "FETCH_SUCCESS_ONE_ON_ONE", readAt: message.getReadAt(), deliveredAt: message.getDeliveredAt() }); } } catch (error) { if (fetchIdRef.current !== currentFetchId) return; handleError(error); } }, [message, isGroupMessage, handleError]); react.useEffect(() => { dispatch({ type: "RESET" }); void doFetchReceipts(); }, [doFetchReceipts]); react.useEffect(() => { const listenerId = `CometChatMessageInformation_receipt_${instanceId}`; let cleanup; try { cleanup = attachReceiptListener(listenerId, { onMessagesDelivered: (receipt) => { const sender = receipt.getSender(); if (isGroupMessage) { if (sender.getUid() !== loggedInUserRef.current) { dispatch({ type: "UPDATE_RECEIPT", uid: sender.getUid(), deliveredAt: receipt.getDeliveredAt() }); } } else { dispatch({ type: "UPDATE_ONE_ON_ONE_RECEIPT", deliveredAt: receipt.getDeliveredAt() }); } }, onMessagesRead: (receipt) => { const sender = receipt.getSender(); if (isGroupMessage) { if (sender.getUid() !== loggedInUserRef.current) { dispatch({ type: "UPDATE_RECEIPT", uid: sender.getUid(), readAt: receipt.getReadAt() }); } } else { dispatch({ type: "UPDATE_ONE_ON_ONE_RECEIPT", readAt: receipt.getReadAt() }); } } }); } catch { } return () => { cleanup?.(); }; }, [instanceId, isGroupMessage]); react.useEffect(() => { const listenerId = `CometChatMessageInformation_conn_${instanceId}`; let cleanup; try { cleanup = attachConnectionListener(listenerId, () => { dispatch({ type: "RESET" }); void doFetchReceipts(); }); } catch { } return () => { cleanup?.(); }; }, [instanceId, doFetchReceipts]); const retry = react.useCallback(() => { dispatch({ type: "RESET" }); void doFetchReceipts(); }, [doFetchReceipts]); return { ...state, isGroupMessage, retry }; } var CometChatMessageInformationHeader = ({ className }) => { const { onClose } = useCometChatMessageInformationContext(); const { getLocalizedString } = chunkKMTY4OFY_cjs.useLocale(); const headerClass = ["cometchat-message-information__header", className ?? ""].filter(Boolean).join(" "); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: headerClass, children: [ /* @__PURE__ */ jsxRuntime.jsx( "h2", { id: "cometchat-message-info-title", className: "cometchat-message-information__header-title", children: getLocalizedString("message_information_title") } ), /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", className: "cometchat-message-information__header-close-button", "aria-label": getLocalizedString("message_information_close_hover"), "data-cometchat-message-info-close": true, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__header-close-icon", "aria-hidden": "true" }) } ) ] }); }; var CometChatMessageInformationMessagePreview = ({ className }) => { const { message, showScrollbar } = useCometChatMessageInformationContext(); const { getLocalizedString } = chunkKMTY4OFY_cjs.useLocale(); const registry = react.useContext(chunkXBXSZ3KO_cjs.CometChatPluginRegistryContext); const contentView = react.useMemo(() => { if (!registry) return null; const plugin = registry.findPlugin(message); if (!plugin) return null; const sender = message.getSender(); const pluginContext = { loggedInUser: sender, alignment: "right", // Always show as outgoing in the info panel theme: "light", getLocalizedString }; try { return plugin.renderBubble(message, pluginContext); } catch { return null; } }, [registry, message, getLocalizedString]); const sectionClass = [ "cometchat-message-information__message-preview", !showScrollbar ? "cometchat-message-information__message-preview--hide-scrollbar" : "", className ?? "" ].filter(Boolean).join(" "); if (contentView) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className: sectionClass, children: /* @__PURE__ */ jsxRuntime.jsx( chunkXBXSZ3KO_cjs.CometChatMessageBubble, { message, alignment: "right", contentView, hideAvatar: true, hideSenderName: true, hideReceipts: true, hideThreadView: true, disableInteraction: true } ) }); } const messageType = message.getType(); let previewText = ""; if (messageType === "text") { const textMsg = message; previewText = textMsg.getText(); } else if (messageType === "image") { previewText = "\u{1F4F7} Photo"; } else if (messageType === "video") { previewText = "\u{1F3A5} Video"; } else if (messageType === "audio") { previewText = "\u{1F3B5} Audio"; } else if (messageType === "file") { previewText = "\u{1F4CE} File"; } else { previewText = getLocalizedString("message_fallback_text"); } return /* @__PURE__ */ jsxRuntime.jsx("div", { className: sectionClass, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cometchat-message-information__message-preview-content", children: previewText }) }); }; var CometChatMessageInformationLoadingState = ({ className }) => { const loadingClass = ["cometchat-message-information__loading", className ?? ""].filter(Boolean).join(" "); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: loadingClass, role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cometchat-message-information__spinner" }) }); }; var CometChatMessageInformationErrorState = ({ className }) => { const { retry } = useCometChatMessageInformationContext(); const { getLocalizedString } = chunkKMTY4OFY_cjs.useLocale(); const errorClass = ["cometchat-message-information__error", className ?? ""].filter(Boolean).join(" "); return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: errorClass, role: "alert", children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__error-text", children: getLocalizedString("message_information_error") }), /* @__PURE__ */ jsxRuntime.jsx( "button", { type: "button", className: "cometchat-message-information__error-retry-button", onClick: retry, children: getLocalizedString("retry") } ) ] }); }; var CometChatMessageInformationEmptyState = ({ className }) => { const { getLocalizedString } = chunkKMTY4OFY_cjs.useLocale(); const emptyClass = ["cometchat-message-information__empty", className ?? ""].filter(Boolean).join(" "); return /* @__PURE__ */ jsxRuntime.jsx("div", { className: emptyClass, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__empty-text", children: getLocalizedString("message_information_group_message_receipt_empty") }) }); }; var CometChatMessageInformationReceiptList = ({ className }) => { const { fetchState, userReceipts, oneOnOneReadAt, oneOnOneDeliveredAt, isGroupMessage, showScrollbar, messageInfoDateTimeFormat } = useCometChatMessageInformationContext(); const { getLocalizedString } = chunkKMTY4OFY_cjs.useLocale(); const contentClass = [ "cometchat-message-information__content", !showScrollbar ? "cometchat-message-information__content--hide-scrollbar" : "", className ?? "" ].filter(Boolean).join(" "); if (fetchState === "loading" && userReceipts.length === 0 && !oneOnOneReadAt && !oneOnOneDeliveredAt) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClass, children: /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationLoadingState, {}) }); } if (fetchState === "error" && userReceipts.length === 0 && !oneOnOneReadAt && !oneOnOneDeliveredAt) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className: contentClass, children: /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationErrorState, {}) }); } return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: contentClass, children: [ isGroupMessage && fetchState !== "loading" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: userReceipts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx( "ul", { className: "cometchat-message-information__user-list", role: "list", "aria-label": getLocalizedString("message_information_title"), children: userReceipts.map((receipt) => /* @__PURE__ */ jsxRuntime.jsxs( "li", { className: "cometchat-message-information__user-item", role: "listitem", children: [ /* @__PURE__ */ jsxRuntime.jsx( "div", { className: "cometchat-message-information__user-item-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx( chunkUY4YZAGJ_cjs.CometChatAvatar, { image: receipt.user.getAvatar(), name: receipt.user.getName(), size: "large" } ) } ), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cometchat-message-information__user-item-content", children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__user-item-name", children: receipt.user.getName() }), receipt.readAt > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cometchat-message-information__user-item-receipt-row", children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__user-item-receipt-label", children: getLocalizedString("message_information_read") }), /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__user-item-receipt-time", children: /* @__PURE__ */ jsxRuntime.jsx( chunkXBXSZ3KO_cjs.CometChatDate, { timestamp: receipt.readAt, formatConfig: messageInfoDateTimeFormat } ) }) ] }), receipt.deliveredAt > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cometchat-message-information__user-item-receipt-row", children: [ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__user-item-receipt-label", children: getLocalizedString("message_information_delivered") }), /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cometchat-message-information__user-item-receipt-time", children: /* @__PURE__ */ jsxRuntime.jsx( chunkXBXSZ3KO_cjs.CometChatDate, { timestamp: receipt.deliveredAt, formatConfig: messageInfoDateTimeFormat } ) }) ] }) ] }) ] }, receipt.user.getUid() )) } ) : fetchState !== "error" && /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationEmptyState, {}) }), !isGroupMessage && fetchState !== "loading" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cometchat-message-information__section", children: [ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "cometchat-message-information__section-title", children: getLocalizedString("message_information_read") }), oneOnOneReadAt > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cometchat-message-information__section-time", children: /* @__PURE__ */ jsxRuntime.jsx( chunkXBXSZ3KO_cjs.CometChatDate, { timestamp: oneOnOneReadAt, formatConfig: messageInfoDateTimeFormat } ) }) : /* @__PURE__ */ jsxRuntime.jsx( "span", { className: "cometchat-message-information__section-empty-dash", "aria-label": getLocalizedString("message_information_not_read"), children: "\u2014" } ) ] }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cometchat-message-information__section", children: [ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "cometchat-message-information__section-title", children: getLocalizedString("message_information_delivered") }), oneOnOneDeliveredAt > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cometchat-message-information__section-time", children: /* @__PURE__ */ jsxRuntime.jsx( chunkXBXSZ3KO_cjs.CometChatDate, { timestamp: oneOnOneDeliveredAt, formatConfig: messageInfoDateTimeFormat } ) }) : /* @__PURE__ */ jsxRuntime.jsx( "span", { className: "cometchat-message-information__section-empty-dash", "aria-label": getLocalizedString("message_information_not_delivered"), children: "\u2014" } ) ] }) ] }) ] }); }; var DEFAULT_DATE_FORMAT = { today: "DD MMM, hh:mm A", yesterday: "DD MMM, hh:mm A", otherDays: "DD MMM, hh:mm A" }; var CometChatMessageInformationRoot = ({ message, onClose, onError, messageInfoDateTimeFormat, messageSentAtDateTimeFormat, textFormatters, showScrollbar = false, children, className }) => { const panelRef = react.useRef(null); const previousFocusRef = react.useRef(null); const IframeContext = chunkC7J4AZRB_cjs.useCometChatFrameContext(); const getCurrentDocument = react.useCallback(() => { return IframeContext.iframeDocument ?? document; }, [IframeContext.iframeDocument]); const { fetchState, userReceipts, oneOnOneReadAt, oneOnOneDeliveredAt, error, isGroupMessage, retry } = useCometChatMessageInformation({ message, onError }); const handleClose = react.useCallback(() => { onClose?.(); }, [onClose]); react.useEffect(() => { previousFocusRef.current = getCurrentDocument().activeElement; panelRef.current?.focus(); return () => { previousFocusRef.current?.focus(); }; }, [getCurrentDocument]); const handleKeyDown = react.useCallback( (event) => { if (event.key === "Escape") { event.preventDefault(); handleClose(); return; } if (event.key === "Tab" && panelRef.current) { const focusableElements = panelRef.current.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); if (focusableElements.length === 0) return; const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; if (event.shiftKey) { if (getCurrentDocument().activeElement === firstElement) { event.preventDefault(); lastElement?.focus(); } } else { if (getCurrentDocument().activeElement === lastElement) { event.preventDefault(); firstElement?.focus(); } } } }, [handleClose, getCurrentDocument] ); const contextValue = react.useMemo( () => ({ message, fetchState, userReceipts, oneOnOneReadAt, oneOnOneDeliveredAt, error, isGroupMessage, messageInfoDateTimeFormat: messageInfoDateTimeFormat ?? DEFAULT_DATE_FORMAT, messageSentAtDateTimeFormat, textFormatters: textFormatters ?? [], showScrollbar, onClose: handleClose, retry }), [ message, fetchState, userReceipts, oneOnOneReadAt, oneOnOneDeliveredAt, error, isGroupMessage, messageInfoDateTimeFormat, messageSentAtDateTimeFormat, textFormatters, showScrollbar, handleClose, retry ] ); const rootClass = ["cometchat-message-information", className ?? ""].filter(Boolean).join(" "); return /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx( "div", { ref: panelRef, className: rootClass, tabIndex: -1, role: "dialog", "aria-modal": "true", "aria-labelledby": "cometchat-message-info-title", onKeyDown: handleKeyDown, children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [ /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationHeader, {}), /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationMessagePreview, {}), /* @__PURE__ */ jsxRuntime.jsx(CometChatMessageInformationReceiptList, {}) ] }) } ) }); }; exports.CometChatMessageInformationEmptyState = CometChatMessageInformationEmptyState; exports.CometChatMessageInformationErrorState = CometChatMessageInformationErrorState; exports.CometChatMessageInformationHeader = CometChatMessageInformationHeader; exports.CometChatMessageInformationLoadingState = CometChatMessageInformationLoadingState; exports.CometChatMessageInformationMessagePreview = CometChatMessageInformationMessagePreview; exports.CometChatMessageInformationReceiptList = CometChatMessageInformationReceiptList; exports.CometChatMessageInformationRoot = CometChatMessageInformationRoot; exports.useCometChatMessageInformationContext = useCometChatMessageInformationContext;