@droppii-org/chat-sdk 0.1.49 → 0.1.51

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 (101) hide show
  1. package/dist/assets/svg/expand.d.ts +7 -0
  2. package/dist/assets/svg/expand.d.ts.map +1 -0
  3. package/dist/assets/svg/expand.js +2 -0
  4. package/dist/assets/svg/expand.tsx +44 -0
  5. package/dist/assets/svg/index.ts +1 -1
  6. package/dist/components/biz-inbox/BizThreadCard.d.ts.map +1 -1
  7. package/dist/components/biz-inbox/BizThreadCard.js +3 -11
  8. package/dist/components/biz-thread-detail/BizAttachmentPreview.d.ts.map +1 -1
  9. package/dist/components/biz-thread-detail/BizAttachmentPreview.js +1 -5
  10. package/dist/components/biz-thread-detail/BizLinkMessageCard.d.ts +3 -2
  11. package/dist/components/biz-thread-detail/BizLinkMessageCard.d.ts.map +1 -1
  12. package/dist/components/biz-thread-detail/BizLinkMessageCard.js +4 -8
  13. package/dist/components/biz-thread-detail/BizMessageContent.d.ts.map +1 -1
  14. package/dist/components/biz-thread-detail/BizMessageContent.js +59 -5
  15. package/dist/components/biz-thread-detail/BizMessageList.js +2 -2
  16. package/dist/components/biz-thread-detail/BizThreadDetailInput.d.ts.map +1 -1
  17. package/dist/components/biz-thread-detail/BizThreadDetailInput.js +20 -17
  18. package/dist/components/biz-thread-detail/BizVideoViewer.d.ts +8 -0
  19. package/dist/components/biz-thread-detail/BizVideoViewer.d.ts.map +1 -0
  20. package/dist/components/biz-thread-detail/BizVideoViewer.js +103 -0
  21. package/dist/components/biz-thread-detail/index.d.ts +0 -4
  22. package/dist/components/biz-thread-detail/index.d.ts.map +1 -1
  23. package/dist/components/biz-thread-detail/index.js +0 -2
  24. package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
  25. package/dist/components/conversation/ConversationBySessionItem.js +6 -5
  26. package/dist/components/conversation/ThreadCard.d.ts +14 -0
  27. package/dist/components/conversation/ThreadCard.d.ts.map +1 -0
  28. package/dist/components/conversation/ThreadCard.js +16 -0
  29. package/dist/components/media-collection/ImageCollection.d.ts.map +1 -1
  30. package/dist/components/media-collection/ImageCollection.js +3 -17
  31. package/dist/components/message/MessageList.d.ts.map +1 -1
  32. package/dist/components/message/MessageList.js +1 -7
  33. package/dist/components/message/footer/ComposerTextSyncPlugin.d.ts +6 -0
  34. package/dist/components/message/footer/ComposerTextSyncPlugin.d.ts.map +1 -0
  35. package/dist/components/message/footer/ComposerTextSyncPlugin.js +16 -0
  36. package/dist/components/message/footer/FilePreview.d.ts +3 -2
  37. package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
  38. package/dist/components/message/footer/FilePreview.js +61 -21
  39. package/dist/components/message/footer/LinkInputPreview.d.ts +7 -0
  40. package/dist/components/message/footer/LinkInputPreview.d.ts.map +1 -0
  41. package/dist/components/message/footer/LinkInputPreview.js +16 -0
  42. package/dist/components/message/footer/MediaActions.d.ts.map +1 -1
  43. package/dist/components/message/footer/MediaActions.js +8 -5
  44. package/dist/components/message/footer/index.d.ts.map +1 -1
  45. package/dist/components/message/footer/index.js +48 -35
  46. package/dist/components/message/item/FileMessage.d.ts +2 -2
  47. package/dist/components/message/item/FileMessage.d.ts.map +1 -1
  48. package/dist/components/message/item/FileMessage.js +20 -12
  49. package/dist/components/message/item/ImageMessage.d.ts.map +1 -1
  50. package/dist/components/message/item/ImageMessage.js +11 -15
  51. package/dist/components/message/item/LinkCard.d.ts +7 -0
  52. package/dist/components/message/item/LinkCard.d.ts.map +1 -0
  53. package/dist/components/message/item/LinkCard.js +17 -0
  54. package/dist/components/message/item/LinkText.d.ts +6 -0
  55. package/dist/components/message/item/LinkText.d.ts.map +1 -0
  56. package/dist/components/message/item/LinkText.js +13 -0
  57. package/dist/components/message/item/MergeImageMessage.d.ts +7 -0
  58. package/dist/components/message/item/MergeImageMessage.d.ts.map +1 -0
  59. package/dist/components/message/item/MergeImageMessage.js +30 -0
  60. package/dist/components/message/item/MessageBubble.d.ts +13 -0
  61. package/dist/components/message/item/MessageBubble.d.ts.map +1 -0
  62. package/dist/components/message/item/MessageBubble.js +19 -0
  63. package/dist/components/message/item/RevokeMessage.js +1 -1
  64. package/dist/components/message/item/TextMessage.d.ts.map +1 -1
  65. package/dist/components/message/item/TextMessage.js +20 -9
  66. package/dist/components/message/item/UrlTextMessage.d.ts.map +1 -1
  67. package/dist/components/message/item/UrlTextMessage.js +19 -17
  68. package/dist/components/message/item/VideoMessage.d.ts.map +1 -1
  69. package/dist/components/message/item/VideoMessage.js +4 -12
  70. package/dist/components/message/item/imagePreviewToolbar.d.ts +5 -0
  71. package/dist/components/message/item/imagePreviewToolbar.d.ts.map +1 -0
  72. package/dist/components/message/item/imagePreviewToolbar.js +14 -0
  73. package/dist/components/message/item/index.d.ts +2 -1
  74. package/dist/components/message/item/index.d.ts.map +1 -1
  75. package/dist/components/message/item/index.js +38 -41
  76. package/dist/components/message/item/textStyle.d.ts +2 -0
  77. package/dist/components/message/item/textStyle.d.ts.map +1 -0
  78. package/dist/components/message/item/textStyle.js +1 -0
  79. package/dist/hooks/message/useSendMessage.d.ts +7 -13
  80. package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
  81. package/dist/hooks/message/useSendMessage.js +87 -113
  82. package/dist/styles/global.css +1 -1
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/dist/types/chat.d.ts +8 -1
  85. package/dist/types/chat.d.ts.map +1 -1
  86. package/dist/utils/bizMessage.d.ts +1 -14
  87. package/dist/utils/bizMessage.d.ts.map +1 -1
  88. package/dist/utils/bizMessage.js +1 -26
  89. package/dist/utils/common.d.ts +3 -1
  90. package/dist/utils/common.d.ts.map +1 -1
  91. package/dist/utils/common.js +16 -3
  92. package/dist/utils/fileValidation.d.ts +1 -0
  93. package/dist/utils/fileValidation.d.ts.map +1 -1
  94. package/dist/utils/fileValidation.js +10 -17
  95. package/dist/utils/link.d.ts +13 -0
  96. package/dist/utils/link.d.ts.map +1 -0
  97. package/dist/utils/link.js +77 -0
  98. package/dist/utils/openLink.d.ts +3 -0
  99. package/dist/utils/openLink.d.ts.map +1 -0
  100. package/dist/utils/openLink.js +19 -0
  101. package/package.json +126 -127
@@ -1,23 +1,19 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { MessageStatus } from "@openim/wasm-client-sdk";
3
3
  import { Image, Spin } from "antd";
4
- const min = (a, b) => (a > b ? b : a);
4
+ import { useTranslation } from "react-i18next";
5
+ import { renderImagePreviewToolbar } from "./imagePreviewToolbar";
5
6
  const ImageMessageItem = (props) => {
6
- var _a, _b, _c, _d;
7
+ var _a, _b, _c;
7
8
  const { message } = props;
8
- const imageHeight = message.pictureElem.sourcePicture.height;
9
- const imageWidth = message.pictureElem.sourcePicture.width;
10
- const snapshotMaxHeight = (_b = (_a = message.pictureElem.snapshotPicture) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : imageHeight;
11
- const minHeight = min(200, imageWidth) * (imageHeight / imageWidth) + 2;
12
- const adaptedHight = min(minHeight, snapshotMaxHeight) + 10;
13
- const adaptedWidth = min(imageWidth, 200) + 10;
14
- const sourceUrl = ((_c = message.pictureElem.sourcePicture) === null || _c === void 0 ? void 0 : _c.url) ||
15
- ((_d = message.pictureElem.snapshotPicture) === null || _d === void 0 ? void 0 : _d.url);
9
+ const { t } = useTranslation();
10
+ const pictureElem = message.pictureElem;
11
+ const sourceUrl = ((_a = pictureElem === null || pictureElem === void 0 ? void 0 : pictureElem.sourcePicture) === null || _a === void 0 ? void 0 : _a.url) || ((_b = pictureElem === null || pictureElem === void 0 ? void 0 : pictureElem.snapshotPicture) === null || _b === void 0 ? void 0 : _b.url) || "";
12
+ const bigUrl = ((_c = pictureElem === null || pictureElem === void 0 ? void 0 : pictureElem.bigPicture) === null || _c === void 0 ? void 0 : _c.url) || sourceUrl;
16
13
  const isSending = message.status === MessageStatus.Sending;
17
- const minStyle = {
18
- minHeight: `${adaptedHight}px`,
19
- minWidth: `${adaptedWidth}px`,
20
- };
21
- return (_jsx(Spin, { spinning: isSending, children: _jsx("div", { className: "relative max-w-[200px]", style: minStyle, children: _jsx(Image, { rootClassName: "message-image cursor-pointer", className: "rounded-md", src: sourceUrl, preview: true, placeholder: _jsx("div", { style: minStyle, className: "flex items-center justify-center", children: _jsx(Spin, {}) }) }) }) }));
14
+ return (_jsx("div", { className: "-mx-1", children: _jsx(Spin, { spinning: isSending, children: _jsx(Image, { src: sourceUrl, width: 205, height: 205, className: "cursor-pointer rounded-xl object-cover", preview: {
15
+ src: bigUrl,
16
+ toolbarRender: (originalNode, info) => { var _a; return renderImagePreviewToolbar(originalNode, (_a = info === null || info === void 0 ? void 0 : info.image) === null || _a === void 0 ? void 0 : _a.url, t); },
17
+ }, placeholder: _jsx("div", { className: "flex h-[205px] w-[205px] items-center justify-center rounded-xl bg-black/10", children: _jsx(Spin, {}) }) }) }) }));
22
18
  };
23
19
  export default ImageMessageItem;
@@ -0,0 +1,7 @@
1
+ import type { UrlMetadataInfo } from "../../../types/chat";
2
+ export interface LinkCardProps {
3
+ metadata: UrlMetadataInfo;
4
+ }
5
+ declare const LinkCard: ({ metadata }: LinkCardProps) => import("react/jsx-runtime").JSX.Element | null;
6
+ export default LinkCard;
7
+ //# sourceMappingURL=LinkCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkCard.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/LinkCard.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,QAAA,MAAM,QAAQ,GAAI,cAAc,aAAa,mDA0C5C,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useTranslation } from "react-i18next";
4
+ import { getHostLabel } from "../../../utils/link";
5
+ import { openLink } from "../../../utils/openLink";
6
+ const LinkCard = ({ metadata }) => {
7
+ const { t } = useTranslation("biz-inbox");
8
+ const { url, title, description, image } = metadata;
9
+ if (!title && !description && !image) {
10
+ return null;
11
+ }
12
+ const handleOpen = () => {
13
+ openLink(url, t);
14
+ };
15
+ return (_jsxs("button", { type: "button", onClick: handleOpen, "data-testid": "link-message-card", className: "flex w-full max-w-[292px] flex-col overflow-hidden rounded-[12px] border border-[rgba(57,62,64,0.1)] bg-white text-left", children: [image && (_jsx("div", { className: "aspect-[16/9] w-full overflow-hidden", children: _jsx("img", { src: image, alt: "", className: "h-full w-full object-cover" }) })), _jsxs("div", { className: "flex flex-col px-3 py-2", children: [title && (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-[#393E40]", children: title })), _jsx("p", { className: "truncate text-[12px] font-medium leading-[1.6] tracking-[0.12px] text-[#1B3FE4]", children: getHostLabel(url) }), description && (_jsx("p", { className: "line-clamp-2 text-[12px] leading-[1.6] text-[#5C6366]", children: description }))] })] }));
16
+ };
17
+ export default LinkCard;
@@ -0,0 +1,6 @@
1
+ export interface LinkTextProps {
2
+ text: string;
3
+ }
4
+ declare const LinkText: ({ text }: LinkTextProps) => import("react/jsx-runtime").JSX.Element;
5
+ export default LinkText;
6
+ //# sourceMappingURL=LinkText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkText.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/LinkText.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,QAAQ,GAAI,UAAU,aAAa,4CA2BxC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import clsx from "clsx";
4
+ import { useTranslation } from "react-i18next";
5
+ import { parseTextWithLinks } from "../../../utils/link";
6
+ import { openLink } from "../../../utils/openLink";
7
+ import { MESSAGE_TEXT_CLASS } from "./textStyle";
8
+ const LinkText = ({ text }) => {
9
+ const { t } = useTranslation("biz-inbox");
10
+ const segments = parseTextWithLinks(text);
11
+ return (_jsx("span", { className: clsx("min-w-0 whitespace-pre-wrap text-left [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), children: segments.map((segment, index) => segment.type === "link" ? (_jsx("button", { type: "button", onClick: () => openLink(segment.url, t), className: "inline text-left font-medium text-[#1B3FE4] underline-offset-2 hover:underline", children: segment.value }, `${segment.url}-${index}`)) : (_jsx("span", { children: segment.value }, `text-${index}`))) }));
12
+ };
13
+ export default LinkText;
@@ -0,0 +1,7 @@
1
+ import { MessageItem } from "@openim/wasm-client-sdk";
2
+ interface MergeImageMessageItemProps {
3
+ message: MessageItem;
4
+ }
5
+ declare const MergeImageMessageItem: (props: MergeImageMessageItemProps) => import("react/jsx-runtime").JSX.Element;
6
+ export default MergeImageMessageItem;
7
+ //# sourceMappingURL=MergeImageMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MergeImageMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/MergeImageMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;AAMrE,UAAU,0BAA0B;IAClC,OAAO,EAAE,WAAW,CAAC;CACtB;AAQD,QAAA,MAAM,qBAAqB,GAAI,OAAO,0BAA0B,4CA4C/D,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { MessageStatus } from "@openim/wasm-client-sdk";
3
+ import { Image, Spin } from "antd";
4
+ import clsx from "clsx";
5
+ import { useTranslation } from "react-i18next";
6
+ import { renderImagePreviewToolbar } from "./imagePreviewToolbar";
7
+ const MERGE_IMAGE_GRID_COLS_CLASS = {
8
+ 1: "grid-cols-[repeat(1,100px)]",
9
+ 2: "grid-cols-[repeat(2,100px)]",
10
+ 3: "grid-cols-[repeat(3,100px)]",
11
+ };
12
+ const MergeImageMessageItem = (props) => {
13
+ var _a, _b;
14
+ const { message } = props;
15
+ const { t } = useTranslation();
16
+ const subMessages = (_b = (_a = message.mergeElem) === null || _a === void 0 ? void 0 : _a.multiMessage) !== null && _b !== void 0 ? _b : [];
17
+ const isSending = message.status === MessageStatus.Sending;
18
+ const cols = Math.min(subMessages.length, 3);
19
+ return (_jsx("div", { className: "-mx-1", children: _jsx(Spin, { spinning: isSending, children: _jsx(Image.PreviewGroup, { preview: {
20
+ toolbarRender: (originalNode, info) => { var _a; return renderImagePreviewToolbar(originalNode, (_a = info === null || info === void 0 ? void 0 : info.image) === null || _a === void 0 ? void 0 : _a.url, t); },
21
+ }, children: _jsx("div", { className: clsx("grid gap-1", MERGE_IMAGE_GRID_COLS_CLASS[cols]), children: subMessages.map((item) => {
22
+ var _a, _b, _c, _d, _e, _f;
23
+ const sourceUrl = ((_b = (_a = item.pictureElem) === null || _a === void 0 ? void 0 : _a.sourcePicture) === null || _b === void 0 ? void 0 : _b.url) ||
24
+ ((_d = (_c = item.pictureElem) === null || _c === void 0 ? void 0 : _c.snapshotPicture) === null || _d === void 0 ? void 0 : _d.url) ||
25
+ "";
26
+ const bigUrl = ((_f = (_e = item.pictureElem) === null || _e === void 0 ? void 0 : _e.bigPicture) === null || _f === void 0 ? void 0 : _f.url) || sourceUrl;
27
+ return (_jsx(Image, { src: sourceUrl, width: 100, height: 100, className: "cursor-pointer rounded-xl object-cover", preview: { src: bigUrl }, placeholder: _jsx("div", { className: "flex h-[100px] w-[100px] items-center justify-center rounded-xl bg-black/10", children: _jsx(Spin, {}) }) }, item.clientMsgID));
28
+ }) }) }) }) }));
29
+ };
30
+ export default MergeImageMessageItem;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from "react";
2
+ export interface MessageBubbleProps {
3
+ isMine: boolean;
4
+ content: ReactNode;
5
+ senderName?: string;
6
+ showSenderName?: boolean;
7
+ showTip?: boolean;
8
+ isInternal?: boolean;
9
+ id?: string;
10
+ }
11
+ declare const MessageBubble: ({ isMine, content, senderName, showSenderName, showTip, isInternal, id, }: MessageBubbleProps) => import("react/jsx-runtime").JSX.Element;
12
+ export default MessageBubble;
13
+ //# sourceMappingURL=MessageBubble.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/MessageBubble.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,SAAS,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAmCD,QAAA,MAAM,aAAa,GAAI,2EAQpB,kBAAkB,4CAsCpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import clsx from "clsx";
4
+ const INCOMING_TAIL_PATH = "M1.3798 18H4V0C3.51762 4.5 3.34269 10.5 0.966518 14C-0.568384 16.2608 -0.159364 18 1.3798 18Z";
5
+ const OUTGOING_TAIL_PATH = "M2.6202 18H0V0C0.482375 4.5 0.657308 10.5 3.03348 14C4.56838 16.2608 4.15936 18 2.6202 18Z";
6
+ const MessageBubbleTail = ({ isMine, isInternal, }) => (_jsx("div", { className: "flex shrink-0 items-center justify-center", children: _jsx("div", { className: "flex-none", children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "4", height: "18", viewBox: "0 0 4 18", fill: "none", "aria-hidden": true, children: _jsx("path", { d: isMine ? OUTGOING_TAIL_PATH : INCOMING_TAIL_PATH, fill: isInternal ? "#FF9500" : isMine ? "#0051FF" : "#83899D", fillOpacity: "0.1" }) }) }) }));
7
+ const MessageBubble = ({ isMine, content, senderName, showSenderName, showTip = true, isInternal = false, id, }) => {
8
+ const bubbleClass = clsx("relative max-w-full p-2", showTip
9
+ ? isMine
10
+ ? "rounded-[20px] rounded-br-none"
11
+ : "rounded-[20px] rounded-bl-none"
12
+ : "rounded-[20px]", isInternal
13
+ ? "bg-[rgba(255,149,0,0.1)]"
14
+ : isMine
15
+ ? "bg-[rgba(0,81,255,0.1)]"
16
+ : "bg-[rgba(131,137,157,0.1)]");
17
+ return (_jsxs("div", { className: "relative flex items-end", "data-testid": "message-bubble", children: [!isMine && showTip && (_jsx(MessageBubbleTail, { isMine: isMine, isInternal: isInternal })), _jsx("div", { className: bubbleClass, id: id, children: _jsxs("div", { className: "flex flex-col gap-1 px-1", children: [showSenderName && senderName && (_jsx("span", { className: "text-[12px] font-medium leading-[160%] tracking-[0.12px] text-[#747B7E]", children: senderName })), _jsx("div", { className: "flex flex-col gap-2", children: content })] }) }), isMine && showTip && (_jsx(MessageBubbleTail, { isMine: isMine, isInternal: isInternal }))] }));
18
+ };
19
+ export default MessageBubble;
@@ -3,6 +3,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useTranslation } from "react-i18next";
4
4
  const RevokeMessageItem = (_) => {
5
5
  const { t } = useTranslation();
6
- return (_jsx("span", { className: "!text-sm sm:text-base whitespace-pre-wrap italic text-gray-500", children: t("revoked") }));
6
+ return (_jsx("span", { className: "whitespace-pre-wrap text-[16px] leading-[160%] italic text-gray-500", children: t("revoked") }));
7
7
  };
8
8
  export default RevokeMessageItem;
@@ -1 +1 @@
1
- {"version":3,"file":"TextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/TextMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAKnE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AACD,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,mDAoCnD,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;AAQnE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,mDAiDnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,10 +1,14 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
+ import clsx from "clsx";
3
4
  import { MessageType } from "@openim/wasm-client-sdk";
4
5
  import useAuthStore from "../../../store/auth";
5
- import { sanitizeHtml } from "../../../utils/common";
6
+ import { htmlHasFormatting, sanitizeHtml, stripHtml } from "../../../utils/common";
7
+ import { extractLinkUrls } from "../../../utils/link";
8
+ import LinkText from "./LinkText";
9
+ import { MESSAGE_TEXT_CLASS } from "./textStyle";
6
10
  const TextMessageItem = (props) => {
7
- var _a, _b, _c;
11
+ var _a, _b, _c, _d;
8
12
  const { message } = props;
9
13
  const isCrm = useAuthStore((state) => state.isCrm);
10
14
  let extendMessageInfo = null;
@@ -18,13 +22,20 @@ const TextMessageItem = (props) => {
18
22
  if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.CustomMessage && !isCrm) {
19
23
  return null;
20
24
  }
21
- if (Object.keys(extendMessageInfo).length > 0 &&
22
- (extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo)) {
23
- const htmlContent = ((_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) || "";
24
- // 🔒 Sanitize HTML to prevent XSS attacks
25
- const sanitizedContent = sanitizeHtml(htmlContent);
26
- return (_jsx("div", { className: "!text-sm sm:text-base break-normal whitespace-pre-line flex-1", style: { overflowWrap: "anywhere" }, dangerouslySetInnerHTML: { __html: sanitizedContent } }));
25
+ 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
+ if (richHtmlContent && htmlHasFormatting(richHtmlContent)) {
27
+ const sanitizedContent = sanitizeHtml(richHtmlContent);
28
+ return (_jsx("div", { className: clsx("break-normal whitespace-pre-line flex-1", MESSAGE_TEXT_CLASS), style: { overflowWrap: "anywhere" }, dangerouslySetInnerHTML: { __html: sanitizedContent } }));
27
29
  }
28
- return (_jsx("span", { className: "!text-sm sm:text-base whitespace-pre-wrap", children: ((_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) || "" }));
30
+ const text = ((_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) ||
31
+ ((_d = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _d === void 0 ? void 0 : _d.text) ||
32
+ stripHtml(richHtmlContent) ||
33
+ "";
34
+ if (!text)
35
+ return null;
36
+ if (extractLinkUrls(text).length > 0) {
37
+ return _jsx(LinkText, { text: text });
38
+ }
39
+ return (_jsx("p", { className: clsx("whitespace-pre-wrap break-words", MESSAGE_TEXT_CLASS), children: text }));
29
40
  };
30
41
  export default TextMessageItem;
@@ -1 +1 @@
1
- {"version":3,"file":"UrlTextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/UrlTextMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAUtD,UAAU,uBAAuB;IAC/B,OAAO,EAAE,WAAW,CAAC;CACtB;AACD,QAAA,MAAM,kBAAkB,GAAI,OAAO,uBAAuB,4CAwEzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"UrlTextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/UrlTextMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAatD,UAAU,uBAAuB;IAC/B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,kBAAkB,GAAI,OAAO,uBAAuB,4CA6DzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1,18 +1,14 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { getHostFromUrl, wrapLinksInHtml, sanitizeHtml, } from "../../../utils/common";
4
- import { useFetchExternalLink } from "../../../hooks/common/useFetchExternalLink";
5
- import { Image } from "antd";
3
+ import { wrapLinksInHtml, sanitizeHtml, htmlHasFormatting, stripHtml, } from "../../../utils/common";
4
+ import clsx from "clsx";
5
+ import LinkText from "./LinkText";
6
+ import LinkCard from "./LinkCard";
7
+ import { MESSAGE_TEXT_CLASS } from "./textStyle";
6
8
  const UrlTextMessageItem = (props) => {
7
- var _a, _b, _c, _d, _e, _f, _g, _h;
9
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
8
10
  const { message } = props;
9
- const { data: externalLinkData } = useFetchExternalLink(((_b = (_a = message === null || message === void 0 ? void 0 : message.urlTextElem) === null || _a === void 0 ? void 0 : _a.urls) === null || _b === void 0 ? void 0 : _b[0]) || "");
10
11
  let extendMessageInfo = null;
11
- const onPressExternalLink = (url) => {
12
- if (!url)
13
- return;
14
- window.open(url, "_blank", "noopener,noreferrer");
15
- };
16
12
  try {
17
13
  extendMessageInfo = JSON.parse((message === null || message === void 0 ? void 0 : message.ex) || "{}");
18
14
  }
@@ -20,13 +16,19 @@ const UrlTextMessageItem = (props) => {
20
16
  extendMessageInfo = {};
21
17
  console.error("Failed to parse extendMessageInfo", error);
22
18
  }
23
- if (Object.keys(extendMessageInfo).length > 0 &&
24
- (extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo)) {
25
- const htmlContent = ((_d = (_c = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.content) || "";
26
- // 🔒 Sanitize HTML to prevent XSS attacks
27
- const sanitizedContent = sanitizeHtml(wrapLinksInHtml(htmlContent));
28
- return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "!text-sm sm:text-base break-normal whitespace-pre-line flex-1", style: { overflowWrap: "anywhere" }, dangerouslySetInnerHTML: { __html: sanitizedContent } }), !!externalLinkData && (_jsxs("div", { className: "flex items-center rounded-md px-3 py-2 border-l-4 border-l-blue-500 bg-blue-50 gap-2 cursor-pointer overflow-hidden", style: { wordBreak: "break-word", overflowWrap: "anywhere" }, onClick: () => onPressExternalLink((externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.url) || ""), children: [_jsxs("div", { className: "flex flex-1 flex-col gap-1", children: [(externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.title) && (_jsx("span", { className: "!text-sm font-semibold truncate break-normal", children: externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.title })), (externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.description) && (_jsx("span", { className: "!text-sm text-gray-500 line-clamp-2", children: externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.description })), (externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.url) && (_jsx("span", { className: "!text-sm font-medium text-blue-500", children: getHostFromUrl(externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.url) }))] }), ((_e = externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.logo) === null || _e === void 0 ? void 0 : _e.url) && (_jsx(Image, { src: (_f = externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.logo) === null || _f === void 0 ? void 0 : _f.url, width: 48, height: 48 }))] }))] }));
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) || "";
20
+ if (richHtmlContent && htmlHasFormatting(richHtmlContent)) {
21
+ const sanitizedContent = sanitizeHtml(wrapLinksInHtml(richHtmlContent));
22
+ return (_jsx("div", { className: clsx("break-normal whitespace-pre-line flex-1", MESSAGE_TEXT_CLASS), style: { overflowWrap: "anywhere" }, dangerouslySetInnerHTML: { __html: sanitizedContent } }));
29
23
  }
30
- return (_jsx("span", { className: "!text-sm sm:text-base break-normal whitespace-pre-line flex-1", style: { overflowWrap: "anywhere" }, children: ((_h = (_g = message === null || message === void 0 ? void 0 : message.urlTextElem) === null || _g === void 0 ? void 0 : _g.urls) === null || _h === void 0 ? void 0 : _h[0]) || "" }));
24
+ const text = (_h = (_g = (_f = (_d = (_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) !== null && _d !== void 0 ? _d : (_e = message === null || message === void 0 ? void 0 : message.urlTextElem) === null || _e === void 0 ? void 0 : _e.content) !== null && _f !== void 0 ? _f : message === null || message === void 0 ? void 0 : message.content) !== null && _g !== void 0 ? _g : stripHtml(richHtmlContent)) !== null && _h !== void 0 ? _h : "";
25
+ const urlMetadata = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.urlMetadata;
26
+ if (urlMetadata === null || urlMetadata === void 0 ? void 0 : urlMetadata.url) {
27
+ return (_jsxs("div", { className: "flex max-w-[292px] flex-col gap-2", children: [text && _jsx(LinkText, { text: text }), _jsx(LinkCard, { metadata: urlMetadata })] }));
28
+ }
29
+ if (text) {
30
+ return _jsx(LinkText, { text: text });
31
+ }
32
+ return (_jsx("span", { className: clsx("break-normal whitespace-pre-line flex-1", MESSAGE_TEXT_CLASS), style: { overflowWrap: "anywhere" }, children: ((_k = (_j = message === null || message === void 0 ? void 0 : message.urlTextElem) === null || _j === void 0 ? void 0 : _j.urls) === null || _k === void 0 ? void 0 : _k[0]) || "" }));
31
33
  };
32
34
  export default UrlTextMessageItem;
@@ -1 +1 @@
1
- {"version":3,"file":"VideoMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/VideoMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;AAGrE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;CACtB;AAID,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CAsBrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"VideoMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/VideoMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;AAGrE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CAmBrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -1,20 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { MessageStatus } from "@openim/wasm-client-sdk";
3
3
  import { Spin } from "antd";
4
- const min = (a, b) => (a > b ? b : a);
5
4
  const VideoMessageItem = (props) => {
6
5
  const { message } = props;
7
- const imageHeight = message.videoElem.snapshotHeight;
8
- const imageWidth = message.videoElem.snapshotWidth;
9
- const minHeight = min(200, imageWidth) * (imageHeight / imageWidth) + 2;
10
- const adaptedHight = min(minHeight, imageHeight) + 10;
11
- const adaptedWidth = min(imageWidth, 200) + 10;
12
- const sourceUrl = message.videoElem.videoUrl;
6
+ const videoElem = message.videoElem;
7
+ const videoUrl = (videoElem === null || videoElem === void 0 ? void 0 : videoElem.videoUrl) || "";
8
+ const posterUrl = (videoElem === null || videoElem === void 0 ? void 0 : videoElem.snapshotUrl) || "";
13
9
  const isSending = message.status === MessageStatus.Sending;
14
- const minStyle = {
15
- minHeight: `${adaptedHight}px`,
16
- minWidth: `${adaptedWidth}px`,
17
- };
18
- return (_jsx(Spin, { spinning: isSending, children: _jsx("div", { className: "relative max-w-[200px]", style: minStyle, children: _jsx("video", { className: "rounded-md", src: sourceUrl, controls: true }) }) }));
10
+ return (_jsx("div", { className: "-mx-1", children: _jsx(Spin, { spinning: isSending, children: _jsx("video", { src: videoUrl, poster: posterUrl, controls: true, className: "h-[150px] w-[215px] rounded-xl object-cover" }) }) }));
19
11
  };
20
12
  export default VideoMessageItem;
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from "react";
2
+ import type { TFunction } from "i18next";
3
+ export declare const downloadImage: (imageUrl?: string) => void;
4
+ export declare const renderImagePreviewToolbar: (originalNode: ReactNode, imageUrl: string | undefined, t: TFunction) => ReactNode;
5
+ //# sourceMappingURL=imagePreviewToolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imagePreviewToolbar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/imagePreviewToolbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAIzC,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,SAQ9C,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,cAAc,SAAS,EACvB,UAAU,MAAM,GAAG,SAAS,EAC5B,GAAG,SAAS,KACX,SAcF,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "antd";
3
+ import { Icon } from "../../../components/icon";
4
+ export const downloadImage = (imageUrl) => {
5
+ if (!imageUrl)
6
+ return;
7
+ const link = document.createElement("a");
8
+ link.href = imageUrl;
9
+ link.download = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
10
+ document.body.appendChild(link);
11
+ link.click();
12
+ document.body.removeChild(link);
13
+ };
14
+ export const renderImagePreviewToolbar = (originalNode, imageUrl, t) => (_jsxs("div", { className: "flex flex-col justify-center gap-2", children: [originalNode, imageUrl && (_jsx(Button, { type: "primary", icon: _jsx(Icon, { icon: "download-o", size: 16, className: "text-white" }), className: "self-center", onClick: () => downloadImage(imageUrl), children: t("download") }))] }));
@@ -2,12 +2,13 @@ import { MessageItem as MessageItemType } from "@openim/wasm-client-sdk";
2
2
  interface MessageItemProps {
3
3
  message: MessageItemType;
4
4
  allMessages: MessageItemType[];
5
+ isGroupChat?: boolean;
5
6
  contextMenuOpen?: boolean;
6
7
  onContextMenuOpenChange?: (open: boolean) => void;
7
8
  onRevokeMessage?: (clientMsgID: string) => void;
8
9
  onQuoteMessage?: (message: MessageItemType) => void;
9
10
  onPressQuoteMessage?: (clientMsgID: string) => void;
10
11
  }
11
- declare const MessageItem: ({ message, allMessages, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, }: MessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
12
+ declare const MessageItem: ({ message, allMessages, isGroupChat, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, }: MessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
12
13
  export default MessageItem;
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -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;AA6BjC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,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;CACrD;AAED,QAAA,MAAM,WAAW,GAAI,2HAQlB,gBAAgB,mDA6RlB,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;AA+BjC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,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;CACrD;AAeD,QAAA,MAAM,WAAW,GAAI,wIASlB,gBAAgB,mDAqQlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -1,13 +1,15 @@
1
1
  import { createElement as _createElement } from "react";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import dayjs from "dayjs";
4
4
  import clsx from "clsx";
5
- import { Avatar, Dropdown } from "antd";
5
+ import { Dropdown } from "antd";
6
6
  import { MessageStatus, MessageType, } from "@openim/wasm-client-sdk";
7
7
  import TextMessageItem from "./TextMessage";
8
8
  import ImageMessageItem from "./ImageMessage";
9
9
  import FileMessageItem from "./FileMessage";
10
10
  import VideoMessageItem from "./VideoMessage";
11
+ import MergeImageMessageItem from "./MergeImageMessage";
12
+ import MessageBubble from "./MessageBubble";
11
13
  import { getVisibleNeighbor, visibleTypeMessage, } from "../../../hooks/message/useMessage";
12
14
  import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../../constants";
13
15
  import { formatTimestamp } from "../../../utils/common";
@@ -24,34 +26,37 @@ import QuoteMessageItem from "./QuoteMessage";
24
26
  import SystemLogMessageItem from "./SystemLogMessage";
25
27
  import { isSystemLogMessageType } from "../../../utils/messageLog";
26
28
  const ICON_COLOR = "#3278f7";
27
- const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, }) => {
28
- var _a, _b, _c, _d, _e;
29
+ const MessageAvatar = ({ avatarUrl }) => avatarUrl ? (_jsx("img", { src: avatarUrl, alt: "", className: "h-6 w-6 shrink-0 self-end rounded-full object-cover" })) : (_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center self-end rounded-full bg-[#0C5CFF]", children: _jsx(Icon, { icon: "droppii-o-1", size: 14, className: "text-white" }) }));
30
+ const MessageItem = ({ message, allMessages, isGroupChat = false, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, }) => {
31
+ var _a;
29
32
  const { t } = useTranslation();
30
33
  const { resendMessage } = useSendMessage();
31
34
  const userID = useAuthStore((state) => state.userID);
32
35
  const isCrm = useAuthStore((state) => state.isCrm);
33
36
  const conversationData = useConversationStore((state) => state.conversationData);
34
- const renderMessageByType = useCallback((message) => {
35
- switch (message === null || message === void 0 ? void 0 : message.contentType) {
37
+ const renderMessageByType = useCallback((item) => {
38
+ switch (item === null || item === void 0 ? void 0 : item.contentType) {
36
39
  case MessageType.TextMessage:
37
40
  case MessageType.QuoteMessage:
38
- return _jsx(TextMessageItem, { message: message });
41
+ return _jsx(TextMessageItem, { message: item });
39
42
  case MessageType.PictureMessage:
40
- return _jsx(ImageMessageItem, { message: message });
43
+ return _jsx(ImageMessageItem, { message: item });
41
44
  case MessageType.FileMessage:
42
- return _jsx(FileMessageItem, { message: message });
45
+ return _jsx(FileMessageItem, { message: item });
43
46
  case MessageType.VideoMessage:
44
- return _jsx(VideoMessageItem, { message: message });
47
+ return _jsx(VideoMessageItem, { message: item });
48
+ case MessageType.MergeMessage:
49
+ return _jsx(MergeImageMessageItem, { message: item });
45
50
  case MessageType.UrlTextMessage:
46
- return _jsx(UrlTextMessageItem, { message: message });
51
+ return _jsx(UrlTextMessageItem, { message: item });
47
52
  case MessageType.LogTextMessage:
48
- return _jsx(SystemLogMessageItem, { message: message });
53
+ return _jsx(SystemLogMessageItem, { message: item });
49
54
  case MessageType.RevokeMessage:
50
55
  return _jsx(RevokeMessageItem, {});
51
56
  default:
52
- return _jsx(TextMessageItem, { message: message });
57
+ return _jsx(TextMessageItem, { message: item });
53
58
  }
54
- }, [message]);
59
+ }, []);
55
60
  const { isReplyable, isRevocable, isMine } = useMemo(() => {
56
61
  const isMyMessage = (message === null || message === void 0 ? void 0 : message.sendID) === userID;
57
62
  const isOlderThanOneDay = dayjs().diff(dayjs(message === null || message === void 0 ? void 0 : message.sendTime), "days", true) >= 1;
@@ -69,7 +74,7 @@ const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenC
69
74
  return [];
70
75
  }
71
76
  return [
72
- ...(isReplyable
77
+ ...(isReplyable && onQuoteMessage
73
78
  ? [
74
79
  {
75
80
  key: "TB01",
@@ -79,7 +84,7 @@ const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenC
79
84
  },
80
85
  ]
81
86
  : []),
82
- ...(isRevocable
87
+ ...(isRevocable && onRevokeMessage
83
88
  ? [
84
89
  {
85
90
  key: "TB05",
@@ -95,20 +100,20 @@ const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenC
95
100
  isRevocable,
96
101
  t,
97
102
  onRevokeMessage,
98
- message === null || message === void 0 ? void 0 : message.contentType,
99
- message === null || message === void 0 ? void 0 : message.clientMsgID,
103
+ message,
100
104
  onQuoteMessage,
101
105
  ]);
102
106
  const showSenderInfo = useMemo(() => {
103
107
  var _a, _b, _c;
104
108
  try {
105
109
  const isChatSupport = (_c = (_b = (_a = JSON.parse((conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex) || "{}")) === null || _a === void 0 ? void 0 : _a.sessionInfo) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.botId;
106
- return isChatSupport && isCrm && !isMine;
110
+ return Boolean(isChatSupport && isCrm && (message === null || message === void 0 ? void 0 : message.sendID) !== userID);
107
111
  }
108
112
  catch (_d) {
109
113
  console.log("Failed to parse conversationData.ex");
114
+ return false;
110
115
  }
111
- }, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, isCrm, isMine]);
116
+ }, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, isCrm, message === null || message === void 0 ? void 0 : message.sendID, userID]);
112
117
  const isInternalMessage = Boolean(message === null || message === void 0 ? void 0 : message.isInternal);
113
118
  const isSystemLogMessage = isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType);
114
119
  const hasContextMenu = contextMenuItems.length > 0;
@@ -118,11 +123,12 @@ const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenC
118
123
  const nextMessage = getVisibleNeighbor(allMessages, message, "next");
119
124
  const prevSameUser = (previousMessage === null || previousMessage === void 0 ? void 0 : previousMessage.sendID) === (message === null || message === void 0 ? void 0 : message.sendID);
120
125
  const nextSameUser = (nextMessage === null || nextMessage === void 0 ? void 0 : nextMessage.sendID) === (message === null || message === void 0 ? void 0 : message.sendID);
121
- const prevTimeBreak = !previousMessage ||
126
+ const showTimeBreak = !previousMessage ||
122
127
  !dayjs(message.sendTime).isSame(previousMessage.sendTime, "days");
123
- const showTimeBreak = prevTimeBreak;
124
- const showSenderAvatar = !nextSameUser;
125
- const showSenderName = !prevSameUser && !isMine;
128
+ const showPeerInfo = isGroupChat || showSenderInfo;
129
+ const showAvatar = showPeerInfo && !isMine && !nextSameUser;
130
+ const showSenderName = showPeerInfo && !isMine && !prevSameUser;
131
+ const showTip = !nextSameUser;
126
132
  if (!isCrm && isInternalMessage) {
127
133
  return null;
128
134
  }
@@ -136,29 +142,20 @@ const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenC
136
142
  className: "flex flex-col gap-2 py-1 px-3 sm:px-4 min-w-0",
137
143
  id: `${MSG_ITEM_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`,
138
144
  };
139
- const timeBreakNode = showTimeBreak ? (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "text-xs text-gray-600 text-center bg-neutral-100 px-2 py-1 rounded-full", children: formatTimestamp(message.sendTime, {
140
- dateMonthFormat: "DD MMMM",
141
- }) }) })) : null;
145
+ const timeBreakNode = showTimeBreak ? (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "rounded-full bg-neutral-100 px-2 py-1 text-center text-xs text-gray-600", children: formatTimestamp(message.sendTime, { hasTime: true }) }) })) : null;
142
146
  if (isSystemLogMessage) {
143
147
  return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
144
148
  timeBreakNode,
145
149
  _jsx(SystemLogMessageItem, { message: message })));
146
150
  }
151
+ 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: (message === null || message === void 0 ? void 0 : message.contentType) === MessageType.MergeMessage ? (_jsxs(_Fragment, { children: [_jsx(MergeImageMessageItem, { message: message }), (message === null || message === void 0 ? void 0 : message.textElem) && _jsx(TextMessageItem, { message: message })] })) : (renderMessageByType(message)) }));
152
+ const wrappedBubble = hasContextMenu ? (_jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, children: _jsx("div", { className: "min-w-0", children: bubbleNode }) })) : (bubbleNode);
147
153
  return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
148
154
  timeBreakNode,
149
- _jsx("div", { className: clsx("flex min-w-0", isMine ? "justify-end" : "justify-start"), children: _jsxs("div", { className: clsx("flex flex-1 items-end gap-2 min-w-0", isMine ? "justify-end" : "justify-start"), children: [showSenderInfo && (_jsx("div", { className: "flex items-center justify-center w-[32px] h-[32px]", children: showSenderAvatar && (_jsx(Avatar, { src: message === null || message === void 0 ? void 0 : message.senderFaceUrl, children: ((_c = (_b = message === null || message === void 0 ? void 0 : message.senderNickname) === null || _b === void 0 ? void 0 : _b.charAt) === null || _c === void 0 ? void 0 : _c.call(_b, 0)) || "A" })) })), _jsxs("div", { className: clsx("flex flex-col max-w-[75%] min-w-0", isMine ? "items-end" : "items-start"), children: [showSenderName && showSenderInfo && (_jsx("span", { className: "text-xs font-bold mb-1 px-3 mt-2", children: message === null || message === void 0 ? void 0 : message.senderNickname })), _jsxs("div", { className: clsx("flex flex-col flex-1 w-full", isMine ? "items-end" : "items-start"), children: [(message === null || message === void 0 ? void 0 : message.quoteElem) && (_jsx(QuoteMessageItem, { message: message, isMine: isMine, onPressQuoteMessage: onPressQuoteMessage })), _jsxs("div", { className: "flex items-end gap-1.5", children: [isMine && (_jsx(MessageStatusIndicator, { message: message, isLatest: isLatestMine })), _jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: hasContextMenu ? ["contextMenu"] : [], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, children: _jsxs("div", { className: clsx("px-3 py-2 rounded-2xl max-w-full min-w-0 break-normal flex flex-col flex-1 text-gray-900 gap-1 w-fit", isMine
150
- ? isInternalMessage
151
- ? "bg-orange-100"
152
- : "bg-blue-100"
153
- : isInternalMessage
154
- ? "bg-orange-100"
155
- : "bg-white"), style: {
156
- wordBreak: "break-word",
157
- overflowWrap: "anywhere",
158
- }, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, children: [(message === null || message === void 0 ? void 0 : message.contentType) === MessageType.MergeMessage ? (_jsxs("div", { children: [(_e = (_d = message === null || message === void 0 ? void 0 : message.mergeElem) === null || _d === void 0 ? void 0 : _d.multiMessage) === null || _e === void 0 ? void 0 : _e.map((item) => {
159
- return renderMessageByType(item);
160
- }), (message === null || message === void 0 ? void 0 : message.textElem) && (_jsx(TextMessageItem, { message: message }))] })) : (renderMessageByType(message)), _jsx("span", { className: clsx("text-xs text-gray-500 text-right"), children: dayjs(message === null || message === void 0 ? void 0 : message.sendTime).format("HH:mm") })] }) })] })] }), isMine && message.status === MessageStatus.Failed && (_jsx("span", { className: "text-red-500 text-xs mt-1", children: isMediaResendable(message) ? (_jsx(Trans, { i18nKey: "message_send_failed", components: {
161
- bold: (_jsx("strong", { className: "cursor-pointer", onClick: () => resendMessage(message) })),
162
- } })) : (t("message_send_failed_no_retry")) }))] })] }) })));
155
+ _jsxs("div", { className: clsx("flex min-w-0 items-end gap-1", isMine ? "justify-end pl-12 pr-3" : "justify-start pl-3 pr-12"), children: [!isMine &&
156
+ showPeerInfo &&
157
+ (showAvatar ? (_jsx(MessageAvatar, { avatarUrl: message === null || message === void 0 ? void 0 : message.senderFaceUrl })) : (_jsx("div", { className: "h-6 w-6 shrink-0 self-end" }))), _jsxs("div", { className: clsx("flex min-w-0 max-w-[75%] flex-col gap-1", isMine ? "items-end" : "items-start"), children: [(message === null || message === void 0 ? void 0 : message.quoteElem) && (_jsx(QuoteMessageItem, { message: message, isMine: isMine, onPressQuoteMessage: onPressQuoteMessage })), _jsxs("div", { className: "flex items-end gap-1.5", children: [isMine && (_jsx(MessageStatusIndicator, { message: message, isLatest: isLatestMine })), wrappedBubble] }), isMine && message.status === MessageStatus.Failed && (_jsx("span", { className: "mt-1 text-xs text-red-500", children: isMediaResendable(message) ? (_jsx(Trans, { i18nKey: "message_send_failed", components: {
158
+ bold: (_jsx("strong", { className: "cursor-pointer", onClick: () => resendMessage(message) })),
159
+ } })) : (t("message_send_failed_no_retry")) }))] })] })));
163
160
  };
164
161
  export default MessageItem;
@@ -0,0 +1,2 @@
1
+ export declare const MESSAGE_TEXT_CLASS = "text-[16px] leading-[160%] tracking-[0.16px] text-[#393E40]";
2
+ //# sourceMappingURL=textStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textStyle.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/textStyle.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,gEACgC,CAAC"}
@@ -0,0 +1 @@
1
+ export const MESSAGE_TEXT_CLASS = "text-[16px] leading-[160%] tracking-[0.16px] text-[#393E40]";