@cometchat/chat-uikit-react
Version:
Ready-to-use Chat UI Components for React
605 lines (599 loc) • 23.6 kB
JavaScript
'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;