@droppii-org/chat-sdk 0.1.66 → 0.1.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/components/conversation-detail/PinnedMessageBar.d.ts.map +1 -1
  2. package/dist/components/conversation-detail/PinnedMessageBar.js +11 -4
  3. package/dist/components/conversation-detail/PinnedMessagesPanel.js +1 -1
  4. package/dist/components/conversation-inbox/ConversationInboxItem.d.ts.map +1 -1
  5. package/dist/components/conversation-inbox/ConversationInboxItem.js +2 -2
  6. package/dist/components/message/item/CustomMessage.d.ts +7 -0
  7. package/dist/components/message/item/CustomMessage.d.ts.map +1 -0
  8. package/dist/components/message/item/CustomMessage.js +26 -0
  9. package/dist/components/message/item/TextMessage.d.ts.map +1 -1
  10. package/dist/components/message/item/TextMessage.js +0 -6
  11. package/dist/components/message/item/index.d.ts.map +1 -1
  12. package/dist/components/message/item/index.js +6 -51
  13. package/dist/components/message/item/renderMessageContent.d.ts.map +1 -1
  14. package/dist/components/message/item/renderMessageContent.js +3 -0
  15. package/dist/components/message/reply/ReplyQuoteContent.d.ts.map +1 -1
  16. package/dist/components/message/reply/ReplyQuoteContent.js +1 -1
  17. package/dist/components/message/toolbox/MessageToolboxMenu.js +1 -1
  18. package/dist/components/message/toolbox/types.d.ts +1 -0
  19. package/dist/components/message/toolbox/types.d.ts.map +1 -1
  20. package/dist/components/message/toolbox/types.js +1 -0
  21. package/dist/context/ChatContext.d.ts +1 -1
  22. package/dist/context/ChatContext.d.ts.map +1 -1
  23. package/dist/context/ChatContext.js +2 -1
  24. package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
  25. package/dist/hooks/global/useGlobalEvent.js +8 -10
  26. package/dist/hooks/message/useMessage.d.ts +1 -0
  27. package/dist/hooks/message/useMessage.d.ts.map +1 -1
  28. package/dist/hooks/message/useMessage.js +16 -1
  29. package/dist/hooks/message/useRevokeMessage.d.ts +1 -0
  30. package/dist/hooks/message/useRevokeMessage.d.ts.map +1 -1
  31. package/dist/hooks/message/useRevokeMessage.js +22 -0
  32. package/dist/hooks/message/useSendCustomMessage.d.ts +7 -0
  33. package/dist/hooks/message/useSendCustomMessage.d.ts.map +1 -0
  34. package/dist/hooks/message/useSendCustomMessage.js +5 -0
  35. package/dist/hooks/message/useSendMessage.d.ts +9 -2
  36. package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
  37. package/dist/hooks/message/useSendMessage.js +49 -3
  38. package/dist/index.d.ts +5 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +4 -0
  41. package/dist/locales/vi/common.json +6 -1
  42. package/dist/store/conversation.d.ts.map +1 -1
  43. package/dist/store/conversation.js +6 -0
  44. package/dist/store/type.d.ts +3 -0
  45. package/dist/store/type.d.ts.map +1 -1
  46. package/dist/styles/global.css +1 -1
  47. package/dist/tsconfig.tsbuildinfo +1 -1
  48. package/dist/types/chat.d.ts +5 -2
  49. package/dist/types/chat.d.ts.map +1 -1
  50. package/dist/types/chat.js +4 -4
  51. package/dist/types/customMessage.d.ts +25 -0
  52. package/dist/types/customMessage.d.ts.map +1 -0
  53. package/dist/types/customMessage.js +4 -0
  54. package/dist/utils/common.d.ts +5 -2
  55. package/dist/utils/common.d.ts.map +1 -1
  56. package/dist/utils/common.js +26 -11
  57. package/dist/utils/customMessage.d.ts +5 -0
  58. package/dist/utils/customMessage.d.ts.map +1 -0
  59. package/dist/utils/customMessage.js +36 -0
  60. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"PinnedMessageBar.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageBar.tsx"],"names":[],"mappings":"AA8GA,QAAA,MAAM,gBAAgB,sDAuErB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"PinnedMessageBar.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageBar.tsx"],"names":[],"mappings":"AAgHA,QAAA,MAAM,gBAAgB,sDAyFrB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState } from "react";
3
4
  import clsx from "clsx";
4
5
  import { useTranslation } from "react-i18next";
5
6
  import { MessageType } from "@openim/wasm-client-sdk";
@@ -9,6 +10,7 @@ import useAuthStore from "../../store/auth";
9
10
  import useConversationStore from "../../store/conversation";
10
11
  import { usePinnedMessages } from "../../hooks/message/usePinnedMessages";
11
12
  import { parseUrlMetadata } from "../../utils/common";
13
+ import PinnedMessagesPanel from "./PinnedMessagesPanel";
12
14
  const PINNED_SUBTITLE_KEY_BY_TYPE = {
13
15
  [MessageType.UrlTextMessage]: "pinned_from_link",
14
16
  [MessageType.PictureMessage]: "pinned_from_image",
@@ -73,6 +75,7 @@ const PinnedMessageBar = () => {
73
75
  const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
74
76
  const conversationId = selectedConversationId || (conversation === null || conversation === void 0 ? void 0 : conversation.conversationID) || "";
75
77
  const { pinnedMessageList, pinnedTotalCount } = usePinnedMessages(conversationId);
78
+ const [isPanelOpen, setIsPanelOpen] = useState(false);
76
79
  const latestPinnedMessage = pinnedMessageList[0];
77
80
  if (!latestPinnedMessage)
78
81
  return null;
@@ -80,16 +83,20 @@ const PinnedMessageBar = () => {
80
83
  const senderName = isMe
81
84
  ? t("your_self")
82
85
  : latestPinnedMessage.senderNickname || t("message_sender_unnamed");
86
+ const isRevoked = latestPinnedMessage.contentType === MessageType.RevokeMessage;
83
87
  const subtitleKey = PINNED_SUBTITLE_KEY_BY_TYPE[latestPinnedMessage.contentType] ||
84
88
  "pinned_from_text";
85
- const title = getPinnedMessageTitle(latestPinnedMessage);
89
+ const title = isRevoked
90
+ ? t("revoked")
91
+ : getPinnedMessageTitle(latestPinnedMessage);
86
92
  const showTitle = !TITLE_LESS_MESSAGE_TYPES.includes(latestPinnedMessage.contentType) &&
87
93
  Boolean(title);
88
- const hasThumbnail = latestPinnedMessage.contentType !== MessageType.TextMessage &&
94
+ const hasThumbnail = !isRevoked &&
95
+ latestPinnedMessage.contentType !== MessageType.TextMessage &&
89
96
  latestPinnedMessage.contentType !== MessageType.QuoteMessage;
90
97
  const hasFlushThumbnail = hasThumbnail &&
91
98
  latestPinnedMessage.contentType !== MessageType.FileMessage;
92
99
  const remainingPinnedCount = pinnedTotalCount - 1;
93
- return (_jsxs("div", { "data-testid": "pinned-message-bar", className: clsx("flex w-full shrink-0 items-center gap-3 bg-gray-cool-25 pr-3", hasFlushThumbnail ? "py-0 pl-0" : "py-1 pl-3"), children: [hasThumbnail && _jsx(PinnedMessageThumbnail, { message: latestPinnedMessage }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center", children: [showTitle && (_jsx("p", { className: "truncate text-sm font-medium leading-[160%] text-gray-900", children: title })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-primary-400" }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: t(subtitleKey, { name: senderName }) })] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [remainingPinnedCount > 0 && (_jsxs("span", { className: "flex min-w-[26px] items-center justify-center rounded-full border-2 border-white bg-gradient-danger-light px-1 text-xs font-bold leading-[160%] text-white", children: ["+", remainingPinnedCount] })), _jsx(Icon, { icon: "angle-down-o", size: 20, className: "text-gray-600" })] })] }));
100
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "pinned-message-bar", role: "button", tabIndex: 0, onClick: () => setIsPanelOpen(true), className: clsx("flex w-full shrink-0 cursor-pointer items-center gap-3 bg-gray-cool-25 pr-3", hasFlushThumbnail ? "py-0 pl-0" : "py-1 pl-3"), children: [hasThumbnail && (_jsx(PinnedMessageThumbnail, { message: latestPinnedMessage })), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center", children: [showTitle && (_jsx("p", { className: "truncate text-sm font-medium leading-[160%] text-gray-900", children: title })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-primary-400" }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: t(subtitleKey, { name: senderName }) })] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [remainingPinnedCount > 0 && (_jsxs("span", { className: "flex min-w-[26px] items-center justify-center rounded-full border-2 border-white bg-gradient-danger-light px-1 text-xs font-bold leading-[160%] text-white", children: ["+", remainingPinnedCount] })), _jsx(Icon, { icon: "angle-down-o", size: 20, className: "text-gray-600" })] })] }), _jsx(PinnedMessagesPanel, { open: isPanelOpen, onClose: () => setIsPanelOpen(false) })] }));
94
101
  };
95
102
  export default PinnedMessageBar;
@@ -26,9 +26,9 @@ const PinnedMessagesPanel = ({ open, onClose }) => {
26
26
  setOpenContextMenuId(null);
27
27
  try {
28
28
  await unpinMessage(conversationId, message.clientMsgID);
29
+ toastMessage.success(t("unpin_message_success"));
29
30
  }
30
31
  catch (error) {
31
- console.error("unpinMessage failed", error);
32
32
  toastMessage.error(t("unpin_message_failed"));
33
33
  }
34
34
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ConversationInboxItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/ConversationInboxItem.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAajE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;CAC/C;AAQD,QAAA,MAAM,qBAAqB,GAAI,mBAAmB,0BAA0B,4CA2C3E,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"ConversationInboxItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-inbox/ConversationInboxItem.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAYjE,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;CAC/C;AAQD,QAAA,MAAM,qBAAqB,GAAI,mBAAmB,0BAA0B,4CA0C3E,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -4,7 +4,7 @@ import dayjs from "dayjs";
4
4
  import { useTranslation } from "react-i18next";
5
5
  import useAuthStore from "../../store/auth";
6
6
  import { formatTimestamp, parseLatestMessage } from "../../utils/common";
7
- import { isBotPeer, resolvePeerBadgeLabel, resolveConversationDisplayName, } from "../../utils/conversation";
7
+ import { resolvePeerBadgeLabel, resolveConversationDisplayName, } from "../../utils/conversation";
8
8
  import { useConversationAvatarUrl } from "../../hooks/conversation/useConversationAvatarUrl";
9
9
  import ThreadCard from "../../components/conversation/ThreadCard";
10
10
  import ConversationPeerAvatar from "./ConversationPeerAvatar";
@@ -23,7 +23,7 @@ const ConversationInboxItem = ({ item, onClick }) => {
23
23
  const displayName = resolveConversationDisplayName(item, t);
24
24
  const avatarUrl = useConversationAvatarUrl(item);
25
25
  const badgeLabel = resolvePeerBadgeLabel(item.peerType, t);
26
- const latestMessagePreview = parseLatestMessage(item.latestMsg, currentUserId, tCommon, isBotPeer(item));
26
+ const latestMessagePreview = parseLatestMessage(item.latestMsg, currentUserId, tCommon);
27
27
  const latestMessageTime = formatLatestMessageTime(item.latestMsgSendTime || null);
28
28
  const unreadCount = (_a = item.unreadCount) !== null && _a !== void 0 ? _a : 0;
29
29
  return (_jsx(ThreadCard, { testId: "conversation-inbox-thread-card", onClick: () => onClick(item), unreadCount: unreadCount, time: latestMessageTime, preview: latestMessagePreview, avatar: _jsx(ConversationPeerAvatar, { peerType: item.peerType, displayName: displayName, avatarUrl: avatarUrl, badgeLabel: badgeLabel }), title: _jsx(ConversationInboxTitle, { peerType: item.peerType, displayName: displayName, hasUnread: unreadCount > 0 }) }));
@@ -0,0 +1,7 @@
1
+ import { MessageItem } from "@openim/wasm-client-sdk";
2
+ interface CustomMessageItemProps {
3
+ message: MessageItem;
4
+ }
5
+ declare const CustomMessageItem: ({ message }: CustomMessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
6
+ export default CustomMessageItem;
7
+ //# sourceMappingURL=CustomMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/CustomMessage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMtD,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,iBAAiB,GAAI,aAAa,sBAAsB,mDAwC7D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
+ import clsx from "clsx";
4
+ import { useTranslation } from "react-i18next";
5
+ import { useChatContext } from "../../../context/ChatContext";
6
+ import { parseCustomMessagePayload } from "../../../utils/customMessage";
7
+ import { MESSAGE_TEXT_CLASS } from "./textStyle";
8
+ const CustomMessageItem = ({ message }) => {
9
+ var _a, _b;
10
+ const { t } = useTranslation();
11
+ const { renderCustomMessage } = useChatContext();
12
+ const payload = parseCustomMessagePayload(message);
13
+ const renderedContent = renderCustomMessage === null || renderCustomMessage === void 0 ? void 0 : renderCustomMessage({ message, payload });
14
+ if (renderedContent) {
15
+ return _jsx(_Fragment, { children: renderedContent });
16
+ }
17
+ const fallbackText = ((_a = message === null || message === void 0 ? void 0 : message.textElem) === null || _a === void 0 ? void 0 : _a.content) || ((_b = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _b === void 0 ? void 0 : _b.text);
18
+ if (fallbackText) {
19
+ return (_jsx("p", { className: clsx("min-w-0 whitespace-pre-wrap [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), children: fallbackText }));
20
+ }
21
+ if (!payload) {
22
+ return null;
23
+ }
24
+ return (_jsx("p", { className: clsx("min-w-0 whitespace-pre-wrap [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), children: t("invalid_message") }));
25
+ };
26
+ export default CustomMessageItem;
@@ -1 +1 @@
1
- {"version":3,"file":"TextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/TextMessage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAQnE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,mDAqDnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"TextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/TextMessage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAOtD,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,mDAgDnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,8 +1,6 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import clsx from "clsx";
4
- import { MessageType } from "@openim/wasm-client-sdk";
5
- import useAuthStore from "../../../store/auth";
6
4
  import { htmlHasFormatting, sanitizeHtml, stripHtml } from "../../../utils/common";
7
5
  import { extractLinkUrls } from "../../../utils/link";
8
6
  import LinkText from "./LinkText";
@@ -10,7 +8,6 @@ import { MESSAGE_TEXT_CLASS } from "./textStyle";
10
8
  const TextMessageItem = (props) => {
11
9
  var _a, _b, _c, _d;
12
10
  const { message } = props;
13
- const isCrm = useAuthStore((state) => state.isCrm);
14
11
  let extendMessageInfo = null;
15
12
  try {
16
13
  extendMessageInfo = JSON.parse((message === null || message === void 0 ? void 0 : message.ex) || "{}");
@@ -19,9 +16,6 @@ const TextMessageItem = (props) => {
19
16
  extendMessageInfo = {};
20
17
  console.error("Failed to parse extendMessageInfo", error);
21
18
  }
22
- if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.CustomMessage && !isCrm) {
23
- return null;
24
- }
25
19
  const richHtmlContent = ((_b = (_a = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.content) || "";
26
20
  if (richHtmlContent && htmlHasFormatting(richHtmlContent)) {
27
21
  const sanitizedContent = sanitizeHtml(richHtmlContent);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,yBAAyB,CAAC;AAwCjC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAeD,QAAA,MAAM,WAAW,GAAI,qMAalB,gBAAgB,mDA4UlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,yBAAyB,CAAC;AAiCjC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAeD,QAAA,MAAM,WAAW,GAAI,qMAalB,gBAAgB,mDA8QlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -1,29 +1,22 @@
1
1
  import { createElement as _createElement } from "react";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import dayjs from "dayjs";
4
4
  import clsx from "clsx";
5
5
  import { Dropdown, message as toastMessage } from "antd";
6
6
  import { MessageStatus, MessageType, } from "@openim/wasm-client-sdk";
7
- import TextMessageItem from "./TextMessage";
8
- import ImageMessageItem from "./ImageMessage";
9
- import FileMessageItem from "./FileMessage";
10
- import VideoMessageItem from "./VideoMessage";
11
- import MergeImageMessageItem from "./MergeImageMessage";
12
7
  import MessageBubble from "./MessageBubble";
13
- import { getVisibleNeighbor, visibleTypeMessage, } from "../../../hooks/message/useMessage";
8
+ import { renderBubbleContent } from "./renderMessageContent";
9
+ import { getVisibleNeighbor, isMessageHiddenForViewer, } from "../../../hooks/message/useMessage";
14
10
  import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../../constants";
15
11
  import { formatTimestamp } from "../../../utils/common";
16
12
  import useAuthStore from "../../../store/auth";
17
13
  import useConversationStore from "../../../store/conversation";
18
- import { useCallback, useMemo, useRef } from "react";
14
+ import { useMemo, useRef } from "react";
19
15
  import { useLongPress } from "ahooks";
20
16
  import { Trans, useTranslation } from "react-i18next";
21
- import UrlTextMessageItem from "./UrlTextMessage";
22
17
  import MessageStatusIndicator from "./MessageStatusIndicator";
23
18
  import { useSendMessage, isMediaResendable, } from "../../../hooks/message/useSendMessage";
24
19
  import { Icon } from "../../../components/icon";
25
- import RevokeMessageItem from "./RevokeMessage";
26
- import QuoteMessageItem from "./QuoteMessage";
27
20
  import SystemLogMessageItem from "./SystemLogMessage";
28
21
  import { isSystemLogMessageType } from "../../../utils/messageLog";
29
22
  import { buildMessageToolboxMenuItems, getCopyableMessageText, isCopyableMessageType, isPinnableMessageType, MessageToolboxActionKey, MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, useMessageToolboxVisibility, } from "../../../components/message/toolbox";
@@ -35,29 +28,6 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
35
28
  const userID = useAuthStore((state) => state.userID);
36
29
  const isCrm = useAuthStore((state) => state.isCrm);
37
30
  const conversationData = useConversationStore((state) => state.conversationData);
38
- const renderMessageByType = useCallback((item) => {
39
- switch (item === null || item === void 0 ? void 0 : item.contentType) {
40
- case MessageType.TextMessage:
41
- case MessageType.QuoteMessage:
42
- return _jsx(TextMessageItem, { message: item });
43
- case MessageType.PictureMessage:
44
- return _jsx(ImageMessageItem, { message: item });
45
- case MessageType.FileMessage:
46
- return _jsx(FileMessageItem, { message: item });
47
- case MessageType.VideoMessage:
48
- return _jsx(VideoMessageItem, { message: item });
49
- case MessageType.MergeMessage:
50
- return _jsx(MergeImageMessageItem, { message: item });
51
- case MessageType.UrlTextMessage:
52
- return _jsx(UrlTextMessageItem, { message: item });
53
- case MessageType.LogTextMessage:
54
- return _jsx(SystemLogMessageItem, { message: item });
55
- case MessageType.RevokeMessage:
56
- return _jsx(RevokeMessageItem, {});
57
- default:
58
- return _jsx(TextMessageItem, { message: item });
59
- }
60
- }, []);
61
31
  const { isDeliveredForUi, isRevocable, isMine } = useMessageToolboxVisibility(message, userID);
62
32
  const contextMenuItems = useMemo(() => {
63
33
  if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.RevokeMessage ||
@@ -157,13 +127,7 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
157
127
  const showAvatar = showPeerInfo && !isMine && !nextSameUser;
158
128
  const showSenderName = showPeerInfo && !isMine && !prevSameUser;
159
129
  const showTip = forceHideTip ? false : !nextSameUser;
160
- if (!isCrm && isInternalMessage) {
161
- return null;
162
- }
163
- if ((!isCrm &&
164
- (MessageType.CustomMessage === (message === null || message === void 0 ? void 0 : message.contentType) ||
165
- isSystemLogMessage)) ||
166
- !visibleTypeMessage.includes(message === null || message === void 0 ? void 0 : message.contentType)) {
130
+ if (isMessageHiddenForViewer(message, isCrm)) {
167
131
  return null;
168
132
  }
169
133
  const messageContainerProps = {
@@ -176,16 +140,7 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
176
140
  timeBreakNode,
177
141
  _jsx(SystemLogMessageItem, { message: message })));
178
142
  }
179
- const renderBubbleContent = () => {
180
- if (message === null || message === void 0 ? void 0 : message.quoteElem) {
181
- return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(QuoteMessageItem, { message: message, onPressQuoteMessage: onPressQuoteMessage }), renderMessageByType(message)] }));
182
- }
183
- if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.MergeMessage) {
184
- return (_jsxs(_Fragment, { children: [_jsx(MergeImageMessageItem, { message: message }), (message === null || message === void 0 ? void 0 : message.textElem) && _jsx(TextMessageItem, { message: message })] }));
185
- }
186
- return renderMessageByType(message);
187
- };
188
- const bubbleNode = (_jsx(MessageBubble, { isMine: isMine, isInternal: isInternalMessage, senderName: message === null || message === void 0 ? void 0 : message.senderNickname, showSenderName: showSenderName, showTip: showTip, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, content: renderBubbleContent() }));
143
+ const bubbleNode = (_jsx(MessageBubble, { isMine: isMine, isInternal: isInternalMessage, senderName: message === null || message === void 0 ? void 0 : message.senderNickname, showSenderName: showSenderName, showTip: showTip, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, content: renderBubbleContent(message, onPressQuoteMessage) }));
189
144
  const showPinnedBadge = Boolean(message === null || message === void 0 ? void 0 : message.isPinned) && Boolean(onPinMessage);
190
145
  const pinnedBadgeNode = showPinnedBadge ? (_jsx("span", { "data-testid": "message-pinned-badge", className: clsx("absolute -top-2.5 z-[1] flex h-[22px] w-[26px] items-center justify-center rounded-full border border-white bg-gray-25", isMine ? "left-0" : "right-0"), children: _jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-primary-400" }) })) : null;
191
146
  const wrappedBubble = hasContextMenu ? (_jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsxs("div", { ref: bubbleWrapperRef, className: "relative min-w-0", children: [bubbleNode, pinnedBadgeNode] }) })) : (_jsxs("div", { className: "relative min-w-0", children: [bubbleNode, pinnedBadgeNode] }));
@@ -1 +1 @@
1
- {"version":3,"file":"renderMessageContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/renderMessageContent.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAe,MAAM,yBAAyB,CAAC;AAWtF,eAAO,MAAM,mBAAmB,GAAI,SAAS,eAAe,4CAuB3D,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,eAAe,EACxB,sBAAsB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,4CAwBpD,CAAC"}
1
+ {"version":3,"file":"renderMessageContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/renderMessageContent.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAe,MAAM,yBAAyB,CAAC;AAYtF,eAAO,MAAM,mBAAmB,GAAI,SAAS,eAAe,4CAyB3D,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,eAAe,EACxB,sBAAsB,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,4CAwBpD,CAAC"}
@@ -9,6 +9,7 @@ import UrlTextMessageItem from "./UrlTextMessage";
9
9
  import RevokeMessageItem from "./RevokeMessage";
10
10
  import QuoteMessageItem from "./QuoteMessage";
11
11
  import SystemLogMessageItem from "./SystemLogMessage";
12
+ import CustomMessageItem from "./CustomMessage";
12
13
  export const renderMessageByType = (message) => {
13
14
  switch (message === null || message === void 0 ? void 0 : message.contentType) {
14
15
  case MessageType.TextMessage:
@@ -28,6 +29,8 @@ export const renderMessageByType = (message) => {
28
29
  return _jsx(SystemLogMessageItem, { message: message });
29
30
  case MessageType.RevokeMessage:
30
31
  return _jsx(RevokeMessageItem, {});
32
+ case MessageType.CustomMessage:
33
+ return _jsx(CustomMessageItem, { message: message });
31
34
  default:
32
35
  return _jsx(TextMessageItem, { message: message });
33
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ReplyQuoteContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyQuoteContent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AASnE,eAAO,MAAM,oBAAoB,GAAI,aAAa,WAAW,YACb,CAAC;AAEjD,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iBAAiB,GAAI,qBAG/B,sBAAsB,4CAsBxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"ReplyQuoteContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyQuoteContent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AASnE,eAAO,MAAM,oBAAoB,GAAI,aAAa,WAAW,YACb,CAAC;AAEjD,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iBAAiB,GAAI,qBAG/B,sBAAsB,4CAuBxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -12,6 +12,6 @@ export const ReplyQuoteContent = ({ message, title = "", }) => {
12
12
  var _a, _b;
13
13
  const { t } = useTranslation();
14
14
  const hasMedia = hasReplyMediaPreview(message.contentType);
15
- return (_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-0.5 pr-2 self-stretch", children: [_jsx("div", { className: "w-[3px] shrink-0 self-stretch rounded bg-gray-cool-200" }), hasMedia && _jsx(ReplyPreviewMedia, { message: message }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center py-1 pl-2", children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[160%] text-gray-900", children: title }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-400", children: generateContentBasedOnMessageType(message.contentType, ((_a = message.textElem) === null || _a === void 0 ? void 0 : _a.content) || ((_b = message.quoteElem) === null || _b === void 0 ? void 0 : _b.text), t) })] })] }));
15
+ return (_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-0.5 pr-2 self-stretch", children: [_jsx("div", { className: "w-[3px] shrink-0 self-stretch rounded bg-gray-cool-200" }), hasMedia && _jsx(ReplyPreviewMedia, { message: message }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center py-1 pl-2", children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[160%] text-gray-900", children: title }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-400", children: generateContentBasedOnMessageType(message.contentType, ((_a = message.textElem) === null || _a === void 0 ? void 0 : _a.content) || ((_b = message.quoteElem) === null || _b === void 0 ? void 0 : _b.text), t, message.customElem) })] })] }));
16
16
  };
17
17
  export default ReplyQuoteContent;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import clsx from "clsx";
3
3
  import { Icon } from "../../../components/icon";
4
- export const MESSAGE_TOOLBOX_OVERLAY_CLASSNAME = clsx("[&_.ant-dropdown-menu]:min-w-[200px]", "[&_.ant-dropdown-menu]:rounded-2xl", "[&_.ant-dropdown-menu]:p-0", "[&_.ant-dropdown-menu]:py-2", "[&_.ant-dropdown-menu]:shadow-message-toolbox", "[&_.ant-dropdown-menu-item]:rounded-none", "[&_.ant-dropdown-menu-item]:px-4", "[&_.ant-dropdown-menu-item]:py-1.5");
4
+ export const MESSAGE_TOOLBOX_OVERLAY_CLASSNAME = clsx("[&_.ant-dropdown-menu]:min-w-[200px]", "[&_.ant-dropdown-menu]:rounded-2xl", "[&_.ant-dropdown-menu]:p-0", "[&_.ant-dropdown-menu]:py-2", "[&_.ant-dropdown-menu]:shadow-message-toolbox", "[&_.ant-dropdown-menu-item]:rounded-none", "[&_.ant-dropdown-menu-item]:!px-4", "[&_.ant-dropdown-menu-item]:!py-1.5");
5
5
  const ToolboxMenuRow = ({ icon, label, danger = false }) => (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Icon, { icon: icon, size: 24, className: danger ? "text-danger-400" : "text-gray-900" }), _jsx("span", { className: clsx("text-base font-medium", danger ? "text-danger-400" : "text-gray-900"), children: label })] }));
6
6
  export const buildMessageToolboxMenuItems = (actions) => actions.map((action) => ({
7
7
  key: action.key,
@@ -2,6 +2,7 @@ export declare const MessageToolboxActionKey: {
2
2
  readonly REPLY: "REPLY";
3
3
  readonly PIN: "PIN";
4
4
  readonly UNPIN: "UNPIN";
5
+ readonly VIEW_ORIGINAL: "VIEW_ORIGINAL";
5
6
  readonly COPY_MESSAGE: "COPY_MESSAGE";
6
7
  readonly REVOKE: "REVOKE";
7
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;;CAM1B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,uBAAuB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/message/toolbox/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;;;CAO1B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,OAAO,uBAAuB,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,uBAAuB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB"}
@@ -2,6 +2,7 @@ export const MessageToolboxActionKey = {
2
2
  REPLY: "REPLY",
3
3
  PIN: "PIN",
4
4
  UNPIN: "UNPIN",
5
+ VIEW_ORIGINAL: "VIEW_ORIGINAL",
5
6
  COPY_MESSAGE: "COPY_MESSAGE",
6
7
  REVOKE: "REVOKE",
7
8
  };
@@ -2,5 +2,5 @@ import "../styles/global.css";
2
2
  import { ChatContextType, ChatProviderProps } from "../types/chat";
3
3
  export declare const ChatContext: import("react").Context<ChatContextType>;
4
4
  export declare const useChatContext: () => ChatContextType;
5
- export declare const ChatProvider: ({ children, config }: ChatProviderProps) => import("react/jsx-runtime").JSX.Element;
5
+ export declare const ChatProvider: ({ children, config, renderCustomMessage, }: ChatProviderProps) => import("react/jsx-runtime").JSX.Element;
6
6
  //# sourceMappingURL=ChatContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatContext.tsx"],"names":[],"mappings":"AAEA,OAAO,sBAAsB,CAAC;AAG9B,OAAO,EACL,eAAe,EACf,iBAAiB,EAGlB,MAAM,cAAc,CAAC;AAStB,eAAO,MAAM,WAAW,0CAOtB,CAAC;AAEH,eAAO,MAAM,cAAc,uBAAgC,CAAC;AAE5D,eAAO,MAAM,YAAY,GAAI,sBAAsB,iBAAiB,4CAqGnE,CAAC"}
1
+ {"version":3,"file":"ChatContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatContext.tsx"],"names":[],"mappings":"AAEA,OAAO,sBAAsB,CAAC;AAG9B,OAAO,EACL,eAAe,EACf,iBAAiB,EAGlB,MAAM,cAAc,CAAC;AAStB,eAAO,MAAM,WAAW,0CAOtB,CAAC;AAEH,eAAO,MAAM,cAAc,uBAAgC,CAAC;AAE5D,eAAO,MAAM,YAAY,GAAI,4CAI1B,iBAAiB,4CAsGnB,CAAC"}
@@ -18,7 +18,7 @@ export const ChatContext = createContext({
18
18
  updateSyncStatus: () => { },
19
19
  });
20
20
  export const useChatContext = () => useContext(ChatContext);
21
- export const ChatProvider = ({ children, config }) => {
21
+ export const ChatProvider = ({ children, config, renderCustomMessage, }) => {
22
22
  const [connectStatus, setConnectStatus] = useState(ConnectStatus.Disconnected);
23
23
  const [syncStatus, setSyncStatus] = useState(SyncStatus.Success);
24
24
  const [user, setUser] = useState(null);
@@ -91,5 +91,6 @@ export const ChatProvider = ({ children, config }) => {
91
91
  getSelfUserInfo,
92
92
  updateConnectStatus,
93
93
  updateSyncStatus,
94
+ renderCustomMessage,
94
95
  }, children: _jsx(ConfigProvider, { getPopupContainer: (triggerNode) => document.body, children: _jsx(QueryClientProvider, { client: queryClient, children: _jsx(MainLayout, { children: children }) }) }) }));
95
96
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useGlobalEvent.d.ts","sourceRoot":"","sources":["../../../src/hooks/global/useGlobalEvent.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,cAAc,YAmV1B,CAAC"}
1
+ {"version":3,"file":"useGlobalEvent.d.ts","sourceRoot":"","sources":["../../../src/hooks/global/useGlobalEvent.ts"],"names":[],"mappings":"AAqCA,eAAO,MAAM,cAAc,YA8U1B,CAAC"}
@@ -1,9 +1,11 @@
1
1
  import { useEffect } from "react";
2
+ import { useLatest } from "ahooks";
2
3
  import { DChatSDK } from "../../constants/sdk";
3
4
  import { CbEvents, MessageType, SessionType, } from "@openim/wasm-client-sdk";
4
5
  import { BusinessNotificationType, ConnectStatus, CustomType, SyncStatus, } from "../../types/chat";
5
6
  import { pushNewMessage, updateOneMessage } from "../../hooks/message/useMessage";
6
7
  import { fetchPinnedMessages } from "../../hooks/message/usePinnedMessages";
8
+ import { applyRevokedMessage } from "../../hooks/message/useRevokeMessage";
7
9
  import { useChatContext } from "../../context/ChatContext";
8
10
  import useConversationStore from "../../store/conversation";
9
11
  import useAuthStore from "../../store/auth";
@@ -17,6 +19,7 @@ import emitter from "../../utils/events";
17
19
  const notPushType = [MessageType.TypingMessage, MessageType.RevokeMessage];
18
20
  export const useGlobalEvent = () => {
19
21
  const { user } = useChatContext();
22
+ const userRef = useLatest(user);
20
23
  const queryClient = useQueryClient();
21
24
  const { updateConnectStatus, updateSyncStatus, getSelfUserInfo } = useChatContext();
22
25
  const updateConversationList = useConversationStore((state) => state.updateConversationList);
@@ -42,13 +45,7 @@ export const useGlobalEvent = () => {
42
45
  ]);
43
46
  };
44
47
  const revokedMessageHandler = ({ data }) => {
45
- updateOneMessage({
46
- clientMsgID: data.clientMsgID,
47
- contentType: MessageType.RevokeMessage,
48
- notificationElem: {
49
- detail: JSON.stringify(data),
50
- },
51
- });
48
+ applyRevokedMessage(data.clientMsgID);
52
49
  };
53
50
  const messagePinnedHandler = ({ data }) => {
54
51
  updateOneMessage({
@@ -64,11 +61,12 @@ export const useGlobalEvent = () => {
64
61
  }
65
62
  };
66
63
  const inCurrentConversation = (newServerMsg) => {
64
+ var _a;
67
65
  const selectedSourceId = useConversationStore.getState().selectedSourceId;
68
66
  switch (newServerMsg.sessionType) {
69
67
  case SessionType.Single:
70
68
  return (newServerMsg.sendID === selectedSourceId ||
71
- ((user === null || user === void 0 ? void 0 : user.userID) && newServerMsg.recvID === selectedSourceId));
69
+ !!(((_a = userRef.current) === null || _a === void 0 ? void 0 : _a.userID) && newServerMsg.recvID === selectedSourceId));
72
70
  case SessionType.Group:
73
71
  case SessionType.WorkingGroup:
74
72
  return newServerMsg.groupID === selectedSourceId;
@@ -79,7 +77,7 @@ export const useGlobalEvent = () => {
79
77
  }
80
78
  };
81
79
  const handleNewMessage = (newServerMsg) => {
82
- var _a, _b;
80
+ var _a, _b, _c;
83
81
  let customData = null;
84
82
  if (newServerMsg.contentType === MessageType.CustomMessage) {
85
83
  const rawCustomData = (_b = (_a = newServerMsg.customElem) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.trim();
@@ -102,7 +100,7 @@ export const useGlobalEvent = () => {
102
100
  if (!notPushType.includes(newServerMsg.contentType)) {
103
101
  pushNewMessage(newServerMsg);
104
102
  }
105
- if (newServerMsg.sendID !== (user === null || user === void 0 ? void 0 : user.userID)) {
103
+ if (newServerMsg.sendID !== ((_c = userRef.current) === null || _c === void 0 ? void 0 : _c.userID)) {
106
104
  queryClient.invalidateQueries({
107
105
  queryKey: [QUERY_KEYS.GET_LIST_SESSION_BY_CONVERSATION],
108
106
  });
@@ -1,5 +1,6 @@
1
1
  import { MessageItem, MessageType } from "@openim/wasm-client-sdk";
2
2
  export declare const visibleTypeMessage: MessageType[];
3
+ export declare const isMessageHiddenForViewer: (message: MessageItem, isCrm: boolean) => boolean;
3
4
  export declare const useMessage: (conversationId?: string, searchClientMsgID?: string, enabled?: boolean, useAppHistory?: boolean) => {
4
5
  loadState: {
5
6
  initLoading: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,WAAW,EACX,WAAW,EAEZ,MAAM,yBAAyB,CAAC;AAUjC,eAAO,MAAM,kBAAkB,eAgB9B,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,iBAAiB,MAAM,EACvB,oBAAoB,MAAM,EAC1B,iBAAc,EACd,uBAAqB;;;;;qBAeA,WAAW,EAAE;;;;;;qBAAb,WAAW,EAAE;;;;;;CA4RnC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,SACpB,CAAC;AAChC,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,SACpB,CAAC;AAClC,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,SACf,CAAC;AAEtC,eAAO,MAAM,kBAAkB,GAC7B,aAAa,WAAW,EAAE,EAC1B,SAAS,WAAW,EACpB,WAAW,MAAM,GAAG,MAAM,KACzB,WAAW,GAAG,SAkBhB,CAAC"}
1
+ {"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,WAAW,EACX,WAAW,EAEZ,MAAM,yBAAyB,CAAC;AAYjC,eAAO,MAAM,kBAAkB,eAgB9B,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,SAAS,WAAW,EACpB,OAAO,OAAO,KACb,OAWF,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,iBAAiB,MAAM,EACvB,oBAAoB,MAAM,EAC1B,iBAAc,EACd,uBAAqB;;;;;qBAeA,WAAW,EAAE;;;;;;qBAAb,WAAW,EAAE;;;;;;CAiSnC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,SACpB,CAAC;AAChC,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,SACpB,CAAC;AAClC,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,SACf,CAAC;AAEtC,eAAO,MAAM,kBAAkB,GAC7B,aAAa,WAAW,EAAE,EAC1B,SAAS,WAAW,EACpB,WAAW,MAAM,GAAG,MAAM,KACzB,WAAW,GAAG,SAkBhB,CAAC"}
@@ -8,6 +8,8 @@ import isEmpty from "lodash/isEmpty";
8
8
  import { useChatContext } from "../../context/ChatContext";
9
9
  import useAuthStore from "../../store/auth";
10
10
  import { ConnectStatus, SyncStatus } from "../../types/chat";
11
+ import { isSystemLogMessageType } from "../../utils/messageLog";
12
+ import { isRenderableCustomMessage } from "../../utils/customMessage";
11
13
  export const visibleTypeMessage = [
12
14
  MessageType.TextMessage,
13
15
  MessageType.PictureMessage,
@@ -25,6 +27,16 @@ export const visibleTypeMessage = [
25
27
  MessageType.RevokeMessage,
26
28
  MessageType.LogTextMessage,
27
29
  ];
30
+ export const isMessageHiddenForViewer = (message, isCrm) => {
31
+ if (!visibleTypeMessage.includes(message === null || message === void 0 ? void 0 : message.contentType))
32
+ return true;
33
+ if (isCrm)
34
+ return false;
35
+ const isCustomMessage = MessageType.CustomMessage === (message === null || message === void 0 ? void 0 : message.contentType);
36
+ return (Boolean(message === null || message === void 0 ? void 0 : message.isInternal) ||
37
+ isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType) ||
38
+ (isCustomMessage && !isRenderableCustomMessage(message)));
39
+ };
28
40
  export const useMessage = (conversationId, searchClientMsgID, enabled = true, useAppHistory = false) => {
29
41
  const { connectStatus, syncStatus } = useChatContext();
30
42
  const userID = useAuthStore((state) => state.userID);
@@ -176,7 +188,10 @@ export const useMessage = (conversationId, searchClientMsgID, enabled = true, us
176
188
  return;
177
189
  }
178
190
  setLoadState((preState) => {
179
- const messageList = [message, ...preState.messageList];
191
+ // sendTime is assigned once at creation (optimistic or server) and
192
+ // never changes afterwards, so sorting by it keeps messages in the
193
+ // right order regardless of network delay or how late seq comes back.
194
+ const messageList = [message, ...preState.messageList].sort((a, b) => (b.sendTime || 0) - (a.sendTime || 0));
180
195
  return Object.assign(Object.assign({}, preState), { messageList });
181
196
  });
182
197
  };
@@ -1,3 +1,4 @@
1
+ export declare const applyRevokedMessage: (clientMsgID: string, conversationID?: string) => void;
1
2
  export declare const useRevokeMessage: () => {
2
3
  revokeMessage: (conversationID: string, clientMsgID: string) => Promise<void>;
3
4
  loading: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useRevokeMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useRevokeMessage.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB;;;CAiB5B,CAAC"}
1
+ {"version":3,"file":"useRevokeMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useRevokeMessage.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,mBAAmB,GAC9B,aAAa,MAAM,EACnB,iBAAiB,MAAM,SAoBxB,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;CAkB5B,CAAC"}
@@ -1,11 +1,33 @@
1
+ import { MessageType } from "@openim/wasm-client-sdk";
1
2
  import { DChatSDK } from "../../constants/sdk";
2
3
  import { useRequest } from "ahooks";
4
+ import { updateOneMessage } from "../../hooks/message/useMessage";
5
+ import { fetchPinnedMessages } from "../../hooks/message/usePinnedMessages";
6
+ import useConversationStore from "../../store/conversation";
7
+ // Shared by the actor's own revoke call (conversationID known upfront) and by
8
+ // the OnNewRecvMessageRevoked socket handler (conversationID unknown, so we
9
+ // infer it from whichever conversation currently has this message pinned).
10
+ export const applyRevokedMessage = (clientMsgID, conversationID) => {
11
+ const revokedPatch = {
12
+ clientMsgID,
13
+ contentType: MessageType.RevokeMessage,
14
+ };
15
+ updateOneMessage(revokedPatch);
16
+ useConversationStore.getState().updatePinnedMessage(revokedPatch);
17
+ const { selectedConversationId, conversationData, pinnedMessageList } = useConversationStore.getState();
18
+ const targetConversationId = conversationID || selectedConversationId || (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID);
19
+ const isRevokedMessagePinned = pinnedMessageList.some((pinnedMessage) => pinnedMessage.clientMsgID === clientMsgID);
20
+ if (targetConversationId && isRevokedMessagePinned) {
21
+ void fetchPinnedMessages(targetConversationId);
22
+ }
23
+ };
3
24
  export const useRevokeMessage = () => {
4
25
  const { loading, runAsync: revokeMessage } = useRequest(async (conversationID, clientMsgID) => {
5
26
  await DChatSDK.revokeMessage({
6
27
  conversationID,
7
28
  clientMsgID,
8
29
  });
30
+ applyRevokedMessage(clientMsgID, conversationID);
9
31
  }, {
10
32
  manual: true,
11
33
  });
@@ -0,0 +1,7 @@
1
+ import { type UseSendMessageOptions } from "../../hooks/message/useSendMessage";
2
+ export declare const useSendCustomMessage: (options?: UseSendMessageOptions) => {
3
+ sendCustomMessage: (payload: import("../..").CustomMessagePayload, sendOptions?: {
4
+ currentSession?: import("../../types/dto").ISessionResponse;
5
+ }) => Promise<boolean>;
6
+ };
7
+ //# sourceMappingURL=useSendCustomMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSendCustomMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendCustomMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,gCAAgC,CAAC;AAExC,eAAO,MAAM,oBAAoB,GAAI,UAAU,qBAAqB;;sBAK84a,CAAC;;CADl9a,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { useSendMessage, } from "../../hooks/message/useSendMessage";
2
+ export const useSendCustomMessage = (options) => {
3
+ const { sendCustomMessage } = useSendMessage(options);
4
+ return { sendCustomMessage };
5
+ };
@@ -1,4 +1,5 @@
1
- import { MergerMsgParams, MessageItem } from "@openim/wasm-client-sdk";
1
+ import { CustomMsgParams, MergerMsgParams, MessageItem } from "@openim/wasm-client-sdk";
2
+ import { type CustomMessagePayload } from "../../types/customMessage";
2
3
  import { BotFlowMeta, ExtendMessageInfo, FileMsgParamsByFile, ImageMsgParamsByFile, UrlMetadataInfo, VideoMsgParamsByFile } from "../../types/chat";
3
4
  import { UploadFile } from "antd";
4
5
  import { ISessionResponse } from "../../types/dto";
@@ -12,6 +13,8 @@ export declare const createMergerMessage: (mergerMsgParams: MergerMsgParams) =>
12
13
  export declare const createVideoMessageByFile: (file: VideoMsgParamsByFile) => Promise<MessageItem | null>;
13
14
  export declare const createFileMessageByFile: (file: FileMsgParamsByFile) => Promise<MessageItem | null>;
14
15
  export declare const createUrlTextMessage: (text: string, urls: string[]) => Promise<MessageItem | null>;
16
+ export declare const createCustomMessageByParams: (params: CustomMsgParams) => Promise<MessageItem | null>;
17
+ export declare const createCustomMessage: (payload: CustomMessagePayload) => Promise<MessageItem | null>;
15
18
  export declare const createQuoteMessage: (text: string, quotedMessage: MessageItem) => Promise<MessageItem | null>;
16
19
  export type SendMessageScrollEvent = "CHAT_LIST_SCROLL_TO_BOTTOM" | "CONVERSATION_CHAT_SCROLL_TO_BOTTOM_IF_AT_BOTTOM";
17
20
  export interface OfflinePushMeta {
@@ -26,7 +29,7 @@ export interface UseSendMessageOptions {
26
29
  }) => OfflinePushMeta;
27
30
  }
28
31
  export declare const useSendMessage: (options?: UseSendMessageOptions) => {
29
- sendMergeMessage: ({ richText, plainText, files, currentSession, isInternal, urlMetadata, flow, }: {
32
+ sendMergeMessage: ({ richText, plainText, files, currentSession, isInternal, urlMetadata, flow, customMessage, }: {
30
33
  richText: string;
31
34
  plainText: string;
32
35
  files?: UploadFile[];
@@ -34,6 +37,10 @@ export declare const useSendMessage: (options?: UseSendMessageOptions) => {
34
37
  isInternal: boolean;
35
38
  urlMetadata?: UrlMetadataInfo;
36
39
  flow?: BotFlowMeta;
40
+ customMessage?: CustomMessagePayload;
41
+ }) => Promise<boolean>;
42
+ sendCustomMessage: (payload: CustomMessagePayload, sendOptions?: {
43
+ currentSession?: ISessionResponse;
37
44
  }) => Promise<boolean>;
38
45
  resendMessage: (failedMessage: MessageItem) => Promise<void>;
39
46
  };