@droppii-org/chat-sdk 0.3.8 → 0.4.0

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 (253) hide show
  1. package/dist/components/canned-response/CannedResponseBody.js +1 -1
  2. package/dist/components/canned-response/CannedResponseFooter.js +1 -1
  3. package/dist/components/canned-response/CannedResponseHeader.js +1 -1
  4. package/dist/components/canned-response/index.js +1 -1
  5. package/dist/components/canned-response/team/TeamItem.js +1 -1
  6. package/dist/components/common/ConfirmModal.d.ts.map +1 -1
  7. package/dist/components/common/ConfirmModal.js +1 -1
  8. package/dist/components/common/InfoModal.d.ts.map +1 -1
  9. package/dist/components/common/InfoModal.js +1 -1
  10. package/dist/components/compose/ComposeNewMessageModal.d.ts.map +1 -1
  11. package/dist/components/compose/ComposeNewMessageModal.js +1 -1
  12. package/dist/components/conversation/ConversationByGroupItem.d.ts.map +1 -1
  13. package/dist/components/conversation/ConversationByGroupItem.js +2 -1
  14. package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
  15. package/dist/components/conversation/ConversationBySessionItem.js +2 -1
  16. package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
  17. package/dist/components/conversation/DeskConversationList.js +1 -1
  18. package/dist/components/conversation/MentionIndicatorIcon.d.ts +7 -0
  19. package/dist/components/conversation/MentionIndicatorIcon.d.ts.map +1 -0
  20. package/dist/components/conversation/MentionIndicatorIcon.js +17 -0
  21. package/dist/components/conversation/SwipeActionButton.d.ts.map +1 -1
  22. package/dist/components/conversation/SwipeActionButton.js +1 -1
  23. package/dist/components/conversation/SwipeableRow.d.ts.map +1 -1
  24. package/dist/components/conversation/SwipeableRow.js +1 -1
  25. package/dist/components/conversation/ThreadCard.d.ts +2 -1
  26. package/dist/components/conversation/ThreadCard.d.ts.map +1 -1
  27. package/dist/components/conversation/ThreadCard.js +4 -4
  28. package/dist/components/conversation-detail/ConversationDetailHeader.d.ts.map +1 -1
  29. package/dist/components/conversation-detail/ConversationDetailHeader.js +2 -2
  30. package/dist/components/conversation-detail/ConversationDetailInput.d.ts.map +1 -1
  31. package/dist/components/conversation-detail/ConversationDetailInput.js +5 -1
  32. package/dist/components/conversation-detail/ConversationMessageList.d.ts.map +1 -1
  33. package/dist/components/conversation-detail/ConversationMessageList.js +1 -1
  34. package/dist/components/conversation-detail/ConversationMoreOptionItem.d.ts.map +1 -1
  35. package/dist/components/conversation-detail/ConversationMoreOptionItem.js +1 -1
  36. package/dist/components/conversation-detail/ConversationMoreOptionPanel.d.ts.map +1 -1
  37. package/dist/components/conversation-detail/ConversationMoreOptionPanel.js +1 -1
  38. package/dist/components/conversation-detail/PinLimitModal.d.ts.map +1 -1
  39. package/dist/components/conversation-detail/PinLimitModal.js +1 -1
  40. package/dist/components/conversation-detail/PinnedMessageBar.d.ts.map +1 -1
  41. package/dist/components/conversation-detail/PinnedMessageBar.js +8 -4
  42. package/dist/components/conversation-detail/PinnedMessageItem.d.ts.map +1 -1
  43. package/dist/components/conversation-detail/PinnedMessageItem.js +1 -1
  44. package/dist/components/conversation-detail/PinnedMessagesPanel.d.ts.map +1 -1
  45. package/dist/components/conversation-detail/PinnedMessagesPanel.js +1 -1
  46. package/dist/components/conversation-detail/ThreadProfilePanel.d.ts.map +1 -1
  47. package/dist/components/conversation-detail/ThreadProfilePanel.js +1 -1
  48. package/dist/components/conversation-detail/bot/BotButtonMessage.d.ts.map +1 -1
  49. package/dist/components/conversation-detail/bot/BotButtonMessage.js +1 -1
  50. package/dist/components/conversation-detail/bot/BotInactiveNotice.d.ts.map +1 -1
  51. package/dist/components/conversation-detail/bot/BotInactiveNotice.js +1 -1
  52. package/dist/components/conversation-detail/bot/BotMenuSheet.d.ts.map +1 -1
  53. package/dist/components/conversation-detail/bot/BotMenuSheet.js +1 -1
  54. package/dist/components/conversation-detail/bot/BotStartButton.d.ts.map +1 -1
  55. package/dist/components/conversation-detail/bot/BotStartButton.js +1 -1
  56. package/dist/components/conversation-detail/bot/BotSuggest.d.ts.map +1 -1
  57. package/dist/components/conversation-detail/bot/BotSuggest.js +2 -2
  58. package/dist/components/conversation-detail/bot/CsSessionConfirmModal.d.ts.map +1 -1
  59. package/dist/components/conversation-detail/bot/CsSessionConfirmModal.js +1 -1
  60. package/dist/components/conversation-inbox/ConversationInboxHeader.d.ts.map +1 -1
  61. package/dist/components/conversation-inbox/ConversationInboxHeader.js +1 -1
  62. package/dist/components/conversation-inbox/ConversationInboxItem.d.ts.map +1 -1
  63. package/dist/components/conversation-inbox/ConversationInboxItem.js +2 -1
  64. package/dist/components/conversation-inbox/ConversationInboxList.d.ts.map +1 -1
  65. package/dist/components/conversation-inbox/ConversationInboxList.js +1 -1
  66. package/dist/components/conversation-inbox/ConversationInboxTitle.d.ts.map +1 -1
  67. package/dist/components/conversation-inbox/ConversationInboxTitle.js +1 -1
  68. package/dist/components/conversation-inbox/ConversationPeerAvatar.d.ts.map +1 -1
  69. package/dist/components/conversation-inbox/ConversationPeerAvatar.js +1 -1
  70. package/dist/components/conversation-inbox/MuteConversationConfirmModal.d.ts.map +1 -1
  71. package/dist/components/conversation-inbox/MuteConversationConfirmModal.js +1 -1
  72. package/dist/components/group/AddMemberModal.d.ts.map +1 -1
  73. package/dist/components/group/AddMemberModal.js +1 -1
  74. package/dist/components/group/CreateGroupForm.d.ts.map +1 -1
  75. package/dist/components/group/CreateGroupForm.js +1 -3
  76. package/dist/components/group/GroupMemberPicker.js +1 -1
  77. package/dist/components/group/MemberPermissionPanel.js +1 -1
  78. package/dist/components/icon/index.d.ts.map +1 -1
  79. package/dist/components/icon/index.js +1 -1
  80. package/dist/components/media-collection/FileCollection.d.ts.map +1 -1
  81. package/dist/components/media-collection/FileCollection.js +1 -1
  82. package/dist/components/media-collection/ImageCollection.d.ts.map +1 -1
  83. package/dist/components/media-collection/ImageCollection.js +1 -1
  84. package/dist/components/media-collection/LinkCollection.d.ts.map +1 -1
  85. package/dist/components/media-collection/LinkCollection.js +2 -2
  86. package/dist/components/media-collection/VideoCollection.d.ts.map +1 -1
  87. package/dist/components/media-collection/VideoCollection.js +1 -1
  88. package/dist/components/media-collection/index.js +1 -1
  89. package/dist/components/media-resources/FileResourceList.d.ts.map +1 -1
  90. package/dist/components/media-resources/FileResourceList.js +1 -1
  91. package/dist/components/media-resources/ImageResourceGrid.d.ts.map +1 -1
  92. package/dist/components/media-resources/ImageResourceGrid.js +1 -1
  93. package/dist/components/media-resources/LinkResourceItem.d.ts.map +1 -1
  94. package/dist/components/media-resources/LinkResourceItem.js +1 -1
  95. package/dist/components/media-resources/LinkResourceList.d.ts.map +1 -1
  96. package/dist/components/media-resources/LinkResourceList.js +1 -1
  97. package/dist/components/media-resources/MediaEntryCard.d.ts.map +1 -1
  98. package/dist/components/media-resources/MediaEntryCard.js +1 -1
  99. package/dist/components/media-resources/MediaResourcePanel.d.ts.map +1 -1
  100. package/dist/components/media-resources/MediaResourcePanel.js +1 -1
  101. package/dist/components/media-resources/MediaResourceTabBar.d.ts.map +1 -1
  102. package/dist/components/media-resources/MediaResourceTabBar.js +1 -1
  103. package/dist/components/media-resources/MediaResourceTabs.js +1 -1
  104. package/dist/components/media-resources/ResourceEmptyState.d.ts.map +1 -1
  105. package/dist/components/media-resources/ResourceEmptyState.js +1 -1
  106. package/dist/components/media-resources/ResourceScrollContainer.d.ts.map +1 -1
  107. package/dist/components/media-resources/ResourceScrollContainer.js +1 -1
  108. package/dist/components/media-resources/VideoResourceGrid.d.ts.map +1 -1
  109. package/dist/components/media-resources/VideoResourceGrid.js +1 -1
  110. package/dist/components/message/GroupMembersDrawer.js +1 -1
  111. package/dist/components/message/MessageHeader.d.ts.map +1 -1
  112. package/dist/components/message/MessageHeader.js +3 -2
  113. package/dist/components/message/MessageInfiniteScroll.d.ts.map +1 -1
  114. package/dist/components/message/MessageInfiniteScroll.js +1 -1
  115. package/dist/components/message/MessageList.d.ts.map +1 -1
  116. package/dist/components/message/MessageList.js +22 -12
  117. package/dist/components/message/SelectSession.js +1 -1
  118. package/dist/components/message/UnassignedSessionFooter.d.ts.map +1 -1
  119. package/dist/components/message/UnassignedSessionFooter.js +1 -1
  120. package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
  121. package/dist/components/message/footer/ActionBar.js +4 -1
  122. package/dist/components/message/footer/ComposerEditor.js +1 -1
  123. package/dist/components/message/footer/ComposerTabs.d.ts.map +1 -1
  124. package/dist/components/message/footer/ComposerTabs.js +1 -1
  125. package/dist/components/message/footer/EmojiPicker.js +1 -1
  126. package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
  127. package/dist/components/message/footer/EnterHandler.js +10 -1
  128. package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
  129. package/dist/components/message/footer/FilePreview.js +4 -4
  130. package/dist/components/message/footer/LinkInputPreview.d.ts.map +1 -1
  131. package/dist/components/message/footer/LinkInputPreview.js +1 -1
  132. package/dist/components/message/footer/MediaActions.js +1 -1
  133. package/dist/components/message/footer/SessionClosedModal.d.ts.map +1 -1
  134. package/dist/components/message/footer/SessionClosedModal.js +1 -1
  135. package/dist/components/message/footer/ToolbarPlugin.js +1 -1
  136. package/dist/components/message/footer/editorConfig.d.ts +2 -1
  137. package/dist/components/message/footer/editorConfig.d.ts.map +1 -1
  138. package/dist/components/message/footer/editorConfig.js +2 -0
  139. package/dist/components/message/footer/index.d.ts.map +1 -1
  140. package/dist/components/message/footer/index.js +16 -2
  141. package/dist/components/message/footer/mention/MentionMenu.d.ts +6 -0
  142. package/dist/components/message/footer/mention/MentionMenu.d.ts.map +1 -0
  143. package/dist/components/message/footer/mention/MentionMenu.js +51 -0
  144. package/dist/components/message/footer/mention/MentionNode.d.ts +20 -0
  145. package/dist/components/message/footer/mention/MentionNode.d.ts.map +1 -0
  146. package/dist/components/message/footer/mention/MentionNode.js +39 -0
  147. package/dist/components/message/footer/mention/extractMentions.d.ts +6 -0
  148. package/dist/components/message/footer/mention/extractMentions.d.ts.map +1 -0
  149. package/dist/components/message/footer/mention/extractMentions.js +66 -0
  150. package/dist/components/message/footer/mention/useMentionOptions.d.ts +8 -0
  151. package/dist/components/message/footer/mention/useMentionOptions.d.ts.map +1 -0
  152. package/dist/components/message/footer/mention/useMentionOptions.js +45 -0
  153. package/dist/components/message/item/AtTextMessage.d.ts +16 -0
  154. package/dist/components/message/item/AtTextMessage.d.ts.map +1 -0
  155. package/dist/components/message/item/AtTextMessage.js +112 -0
  156. package/dist/components/message/item/FileMessage.js +1 -1
  157. package/dist/components/message/item/GroupNotificationMessage.d.ts.map +1 -1
  158. package/dist/components/message/item/GroupNotificationMessage.js +2 -2
  159. package/dist/components/message/item/ImageMessage.js +1 -1
  160. package/dist/components/message/item/LinkCard.d.ts.map +1 -1
  161. package/dist/components/message/item/LinkCard.js +1 -1
  162. package/dist/components/message/item/LinkText.d.ts.map +1 -1
  163. package/dist/components/message/item/LinkText.js +1 -1
  164. package/dist/components/message/item/MergeImageMessage.js +1 -1
  165. package/dist/components/message/item/MessageBubble.d.ts.map +1 -1
  166. package/dist/components/message/item/MessageBubble.js +2 -2
  167. package/dist/components/message/item/QuoteMessage.d.ts.map +1 -1
  168. package/dist/components/message/item/QuoteMessage.js +1 -1
  169. package/dist/components/message/item/RevokeMessage.d.ts.map +1 -1
  170. package/dist/components/message/item/RevokeMessage.js +1 -1
  171. package/dist/components/message/item/VideoMessage.js +1 -1
  172. package/dist/components/message/item/index.d.ts.map +1 -1
  173. package/dist/components/message/item/index.js +3 -3
  174. package/dist/components/message/item/renderMessageContent.d.ts.map +1 -1
  175. package/dist/components/message/item/renderMessageContent.js +3 -0
  176. package/dist/components/message/reply/ReplyPreviewBar.d.ts.map +1 -1
  177. package/dist/components/message/reply/ReplyPreviewBar.js +1 -1
  178. package/dist/components/message/reply/ReplyQuoteContent.d.ts.map +1 -1
  179. package/dist/components/message/reply/ReplyQuoteContent.js +7 -5
  180. package/dist/components/message/toolbox/MessageToolboxMenu.js +1 -1
  181. package/dist/components/message/toolbox/getCopyableMessageText.d.ts.map +1 -1
  182. package/dist/components/message/toolbox/getCopyableMessageText.js +5 -3
  183. package/dist/components/message/toolbox/isPinnableMessageType.d.ts.map +1 -1
  184. package/dist/components/message/toolbox/isPinnableMessageType.js +1 -0
  185. package/dist/components/search-conversation/SearchAll.d.ts.map +1 -1
  186. package/dist/components/search-conversation/SearchAll.js +1 -1
  187. package/dist/components/search-conversation/SearchConversationAsMessages.d.ts.map +1 -1
  188. package/dist/components/search-conversation/SearchConversationAsMessages.js +1 -1
  189. package/dist/components/search-conversation/SearchConversationAsUsers.d.ts.map +1 -1
  190. package/dist/components/search-conversation/SearchConversationAsUsers.js +1 -1
  191. package/dist/components/search-conversation/SearchConversationMyInbox.js +1 -1
  192. package/dist/components/search-conversation/SearchDrawer.js +1 -1
  193. package/dist/components/search-conversation/SearchMessageOnCurrentConversation.d.ts.map +1 -1
  194. package/dist/components/search-conversation/SearchMessageOnCurrentConversation.js +1 -1
  195. package/dist/components/search-conversation/index.js +1 -1
  196. package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
  197. package/dist/components/search-conversation/item/SearchItemAsMessage.js +1 -1
  198. package/dist/components/search-conversation/item/SearchItemAsUser.d.ts.map +1 -1
  199. package/dist/components/search-conversation/item/SearchItemAsUser.js +1 -1
  200. package/dist/components/session/DeskTeamInbox.d.ts.map +1 -1
  201. package/dist/components/session/DeskTeamInbox.js +3 -2
  202. package/dist/components/session/SessionFilterMenu.d.ts.map +1 -1
  203. package/dist/components/session/SessionFilterMenu.js +1 -1
  204. package/dist/components/thread/AssignConfirmModal.d.ts.map +1 -1
  205. package/dist/components/thread/AssignConfirmModal.js +1 -1
  206. package/dist/components/thread/GroupThreadInfo.d.ts.map +1 -1
  207. package/dist/components/thread/GroupThreadInfo.js +7 -4
  208. package/dist/components/thread/ManualAssignPopover.d.ts.map +1 -1
  209. package/dist/components/thread/ManualAssignPopover.js +1 -1
  210. package/dist/components/thread/SessionSection.d.ts.map +1 -1
  211. package/dist/components/thread/SessionSection.js +2 -2
  212. package/dist/components/thread/SingleThreadInfo.d.ts.map +1 -1
  213. package/dist/components/thread/SingleThreadInfo.js +1 -1
  214. package/dist/components/thread/ThreadInfo.js +1 -1
  215. package/dist/components/thread/UserSection.d.ts.map +1 -1
  216. package/dist/components/thread/UserSection.js +1 -1
  217. package/dist/components/video-player/VideoPlayerModal.d.ts.map +1 -1
  218. package/dist/components/video-player/VideoPlayerModal.js +1 -1
  219. package/dist/context/ChatContext.d.ts +1 -1
  220. package/dist/context/ChatContext.d.ts.map +1 -1
  221. package/dist/context/ChatContext.js +2 -1
  222. package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
  223. package/dist/hooks/global/useGlobalEvent.js +115 -25
  224. package/dist/hooks/group/useGroupPermission.d.ts +1 -1
  225. package/dist/hooks/group/useGroupPermission.d.ts.map +1 -1
  226. package/dist/hooks/group/useGroupPermission.js +2 -2
  227. package/dist/hooks/message/useMessage.d.ts +4 -1
  228. package/dist/hooks/message/useMessage.d.ts.map +1 -1
  229. package/dist/hooks/message/useMessage.js +9 -2
  230. package/dist/hooks/message/useSendMessage.d.ts +8 -4
  231. package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
  232. package/dist/hooks/message/useSendMessage.js +46 -12
  233. package/dist/hooks/session/useConversationSessionState.d.ts +2 -1
  234. package/dist/hooks/session/useConversationSessionState.d.ts.map +1 -1
  235. package/dist/hooks/session/useConversationSessionState.js +5 -5
  236. package/dist/layout/index.d.ts.map +1 -1
  237. package/dist/layout/index.js +10 -1
  238. package/dist/locales/vi/common.json +9 -0
  239. package/dist/locales/vi/conversation-inbox.json +4 -0
  240. package/dist/store/auth.js +1 -1
  241. package/dist/store/conversation.d.ts.map +1 -1
  242. package/dist/store/conversation.js +93 -51
  243. package/dist/store/type.d.ts +6 -2
  244. package/dist/store/type.d.ts.map +1 -1
  245. package/dist/styles/global.css +1 -1
  246. package/dist/types/chat.d.ts +28 -2
  247. package/dist/types/chat.d.ts.map +1 -1
  248. package/dist/utils/common.d.ts.map +1 -1
  249. package/dist/utils/common.js +19 -9
  250. package/dist/utils/messageLog.d.ts +2 -2
  251. package/dist/utils/messageLog.d.ts.map +1 -1
  252. package/dist/utils/messageLog.js +33 -3
  253. package/package.json +17 -3
@@ -24,6 +24,6 @@ const ResourceScrollContainer = ({ tabKey, itemCount, isLoading, isError, hasNex
24
24
  return _jsx(ResourceEmptyState, { tabKey: tabKey });
25
25
  }
26
26
  const scrollableId = `resource-scroll-${tabKey}`;
27
- return (_jsx("div", { id: scrollableId, className: "h-full overflow-auto", children: _jsx(InfiniteScroll, { dataLength: itemCount, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx(LoadingIndicator, {}), scrollableTarget: scrollableId, children: children }) }));
27
+ return (_jsx("div", { id: scrollableId, "data-cp-name": "ResourceScrollContainer", className: "h-full overflow-auto", children: _jsx(InfiniteScroll, { dataLength: itemCount, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx(LoadingIndicator, {}), scrollableTarget: scrollableId, children: children }) }));
28
28
  };
29
29
  export default ResourceScrollContainer;
@@ -1 +1 @@
1
- {"version":3,"file":"VideoResourceGrid.d.ts","sourceRoot":"","sources":["../../../src/components/media-resources/VideoResourceGrid.tsx"],"names":[],"mappings":"AAeA,QAAA,MAAM,iBAAiB,+CA8DtB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"VideoResourceGrid.d.ts","sourceRoot":"","sources":["../../../src/components/media-resources/VideoResourceGrid.tsx"],"names":[],"mappings":"AAeA,QAAA,MAAM,iBAAiB,+CA+DtB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -19,7 +19,7 @@ const VideoResourceGrid = () => {
19
19
  setPreviewIndex(index);
20
20
  openPreview();
21
21
  };
22
- return (_jsxs(ResourceScrollContainer, Object.assign({}, containerProps, { itemCount: videoSources.length, children: [_jsx("div", { className: "grid grid-cols-3 gap-2 p-3", children: videoSources.map((video, index) => {
22
+ return (_jsxs(ResourceScrollContainer, Object.assign({ "data-cp-name": "VideoResourceGrid" }, containerProps, { itemCount: videoSources.length, children: [_jsx("div", { className: "grid grid-cols-3 gap-2 p-3", children: videoSources.map((video, index) => {
23
23
  const durationLabel = video.duration
24
24
  ? formatDuration(video.duration / MILLISECONDS_PER_SECOND)
25
25
  : "";
@@ -350,7 +350,7 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
350
350
  return (_jsxs("div", { className: "flex items-center gap-3 px-4 py-2", children: [_jsx(Avatar, { src: member.faceURL, size: 40, className: "shrink-0", children: member.nickname.charAt(0) || "A" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [_jsx("p", { className: "text-sm font-semibold text-gray-900 truncate", children: member.nickname }), member.isCurrentUser && (_jsx("span", { className: "text-xs text-blue-500 shrink-0", children: t("current_account") }))] }), member.roleLabel && (_jsx("p", { className: "text-sm text-gray-500 truncate", children: member.roleLabel }))] }), (isRealGroup || member.isCurrentUser) && (_jsx(Dropdown, { menu: { items: menuItems }, trigger: ["click"], placement: "bottomRight", children: _jsx("button", { type: "button", className: "flex items-center justify-center w-8 h-8 rounded-full text-gray-500 hover:bg-gray-100", onClick: (event) => event.stopPropagation(), children: _jsx(Icon, { icon: "more-horizontal-b", size: 18 }) }) }))] }, member.userID));
351
351
  }) }));
352
352
  };
353
- return (_jsxs("div", { className: "inline-flex shrink-0", children: [_jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleOpenDrawer, disabled: disabled || !groupID, children: _jsx(Icon, { icon: "user-two-check-o", size: 22 }) }), _jsx(Drawer, { open: isOpen, onClose: handleCloseDrawer, mask: false, closeIcon: false, styles: {
353
+ return (_jsxs("div", { className: "inline-flex shrink-0", "data-cp-name": "GroupMembersDrawer", children: [_jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleOpenDrawer, disabled: disabled || !groupID, children: _jsx(Icon, { icon: "user-two-check-o", size: 22 }) }), _jsx(Drawer, { open: isOpen, onClose: handleCloseDrawer, mask: false, closeIcon: false, styles: {
354
354
  body: {
355
355
  padding: 0,
356
356
  height: "100%",
@@ -1 +1 @@
1
- {"version":3,"file":"MessageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageHeader.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQ/C,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,KAAK,sBAAsB,GAAG,aAAa,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,sBAAsB,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,QAAA,MAAM,aAAa,GAAI,0DAKpB,kBAAkB,4CAyOpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"MessageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageHeader.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQ/C,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,KAAK,sBAAsB,GAAG,aAAa,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,sBAAsB,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,QAAA,MAAM,aAAa,GAAI,0DAKpB,kBAAkB,4CA6OpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -22,7 +22,8 @@ const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, })
22
22
  const isCx = useAuthStore((state) => state.isCx);
23
23
  const isCrm = useAuthStore((state) => state.isCrm);
24
24
  const conversationData = useConversationStore((state) => state.conversationData);
25
- const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo);
25
+ const groupID = conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID;
26
+ const currentGroupInfo = useConversationStore((state) => groupID ? state.currentGroupInfo.get(groupID) : undefined);
26
27
  const { mutate: updateSession } = useUpdateSession();
27
28
  const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
28
29
  const { avatar, displayName } = useConversationDisplayData(conversationData);
@@ -144,6 +145,6 @@ const MessageHeader = ({ onClose, currentSession, isJoined, onOpenThreadInfo, })
144
145
  setCurrentSessionStatus(currentSession.status);
145
146
  }
146
147
  }, [currentSession]);
147
- return (_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3 bg-white flex-wrap", children: [shouldShowMemberCount ? (_jsx(GroupCompositeAvatar, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID, faceURL: avatar, ownerUserID: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.ownerUserID, groupName: displayName, size: 40, className: "min-w-10 min-h-10" })) : (_jsx(Avatar, { src: avatar, size: "large", className: "min-w-10 min-h-10", children: ((_a = displayName === null || displayName === void 0 ? void 0 : displayName.charAt) === null || _a === void 0 ? void 0 : _a.call(displayName, 0)) || "A" })), _jsxs("div", { className: "flex flex-col overflow-hidden flex-1", children: [_jsx("p", { className: "text-base truncate", children: displayName || "" }), shouldShowMemberCount && (_jsx("p", { className: "text-xs text-gray-500 truncate", children: t("member_count", { count: (_b = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.memberCount) !== null && _b !== void 0 ? _b : 0 }) }))] }), _jsxs("div", { className: "flex items-center gap-2 justify-end overflow-hidden", children: [isCx && !isRealGroup && (_jsx(SelectSession, { placeholder: t("select_tag"), options: tagOptions, value: currentSessionTag, onChange: (value) => handleUpdateSession(value, "tag", value === currentSessionTag), excludeOptions: [SessionTag.SLOW_PROCESSING, SessionTag.NONE] })), isCx && !isRealGroup && (_jsx(SelectSession, { placeholder: t("select_status"), options: statusOptions, value: currentSessionStatus, onChange: (value) => handleUpdateSession(value, "status", value === currentSessionStatus) })), _jsx(SearchDrawer, {}), canViewMemberList && (_jsx(GroupMembersDrawer, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID, conversationId: conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID, currentSession: currentSession })), _jsx(MediaCollection, {}), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: onOpenThreadInfo, children: _jsx(Icon, { icon: "align-justify-o", size: 22 }) }), !!onClose && (_jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: onClose, children: _jsx(Icon, { icon: "close-b", size: 22 }) }))] })] }));
148
+ return (_jsxs("div", { className: "px-4 py-3 flex items-center border-b gap-3 bg-white flex-wrap", "data-cp-name": "MessageHeader", children: [shouldShowMemberCount ? (_jsx(GroupCompositeAvatar, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID, faceURL: avatar, ownerUserID: currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.ownerUserID, groupName: displayName, size: 40, className: "min-w-10 min-h-10" })) : (_jsx(Avatar, { src: avatar, size: "large", className: "min-w-10 min-h-10", children: ((_a = displayName === null || displayName === void 0 ? void 0 : displayName.charAt) === null || _a === void 0 ? void 0 : _a.call(displayName, 0)) || "A" })), _jsxs("div", { className: "flex flex-col overflow-hidden flex-1", children: [_jsx("p", { className: "text-base truncate", children: displayName || "" }), shouldShowMemberCount && (_jsx("p", { className: "text-xs text-gray-500 truncate", children: t("member_count", { count: (_b = currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.memberCount) !== null && _b !== void 0 ? _b : 0 }) }))] }), _jsxs("div", { className: "flex items-center gap-2 justify-end overflow-hidden", children: [isCx && !isRealGroup && (_jsx(SelectSession, { placeholder: t("select_tag"), options: tagOptions, value: currentSessionTag, onChange: (value) => handleUpdateSession(value, "tag", value === currentSessionTag), excludeOptions: [SessionTag.SLOW_PROCESSING, SessionTag.NONE] })), isCx && !isRealGroup && (_jsx(SelectSession, { placeholder: t("select_status"), options: statusOptions, value: currentSessionStatus, onChange: (value) => handleUpdateSession(value, "status", value === currentSessionStatus) })), _jsx(SearchDrawer, {}), canViewMemberList && (_jsx(GroupMembersDrawer, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID, conversationId: conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID, currentSession: currentSession })), _jsx(MediaCollection, {}), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: onOpenThreadInfo, children: _jsx(Icon, { icon: "align-justify-o", size: 22 }) }), !!onClose && (_jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: onClose, children: _jsx(Icon, { icon: "close-b", size: 22 }) }))] })] }));
148
149
  };
149
150
  export default MessageHeader;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageInfiniteScroll.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageInfiniteScroll.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IACrD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,QAAA,MAAM,qBAAqB,GAAI,6HAU5B,0BAA0B,4CAoC5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"MessageInfiniteScroll.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageInfiniteScroll.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IACrD,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,QAAA,MAAM,qBAAqB,GAAI,6HAU5B,0BAA0B,4CAqC5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -3,5 +3,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Spin } from "antd";
4
4
  import clsx from "clsx";
5
5
  import InfiniteScroll from "react-infinite-scroll-component";
6
- const MessageInfiniteScroll = ({ scrollRef, scrollableTargetId, loadState, moreOldLoading = false, onLoadMoreOld, onScroll, children, empty, containerClassName, }) => (_jsx("div", { id: scrollableTargetId, ref: scrollRef, className: clsx("flex h-full flex-col-reverse overflow-x-hidden overflow-y-auto pb-3", containerClassName), children: empty && loadState.messageList.length === 0 ? (empty) : (_jsx(InfiniteScroll, { dataLength: loadState.messageList.length, next: onLoadMoreOld, className: "flex w-full min-w-0 flex-col-reverse", inverse: true, hasMore: loadState.hasMoreOld, loader: moreOldLoading ? (_jsx("div", { className: "flex w-full items-center justify-center py-2", children: _jsx(Spin, { size: "small" }) })) : (_jsx("span", { className: "sr-only" })), scrollableTarget: scrollableTargetId, onScroll: (e) => onScroll(e), children: children })) }));
6
+ const MessageInfiniteScroll = ({ scrollRef, scrollableTargetId, loadState, moreOldLoading = false, onLoadMoreOld, onScroll, children, empty, containerClassName, }) => (_jsx("div", { id: scrollableTargetId, ref: scrollRef, className: clsx("flex h-full flex-col-reverse overflow-x-hidden overflow-y-auto pb-3", containerClassName), "data-cp-name": "MessageInfiniteScroll", children: empty && loadState.messageList.length === 0 ? (empty) : (_jsx(InfiniteScroll, { dataLength: loadState.messageList.length, next: onLoadMoreOld, className: "flex w-full min-w-0 flex-col-reverse", inverse: true, hasMore: loadState.hasMoreOld, loader: moreOldLoading ? (_jsx("div", { className: "flex w-full items-center justify-center py-2", children: _jsx(Spin, { size: "small" }) })) : (_jsx("span", { className: "sr-only" })), scrollableTarget: scrollableTargetId, onScroll: (e) => onScroll(e), children: children })) }));
7
7
  export default MessageInfiniteScroll;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAgCA,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAgS3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAgCA,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAqT3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -22,7 +22,7 @@ import { usePinMessage } from "../../hooks/message/usePinMessage";
22
22
  import { useConversationSessionState } from "../../hooks/session/useConversationSessionState";
23
23
  import { useJoinGroupFlow } from "../../hooks/session/useJoinGroupFlow";
24
24
  import { useGroupPermission } from "../../hooks/group/useGroupPermission";
25
- import { isGroupSession } from "../../utils/imCommon";
25
+ import { isGroupConversation } from "../../utils/imCommon";
26
26
  import { ConnectStatus, SessionStatus } from "../../types/chat";
27
27
  import PinLimitModal from "../../components/conversation-detail/PinLimitModal";
28
28
  import ConfirmModal from "../../components/common/ConfirmModal";
@@ -33,21 +33,30 @@ const MessageList = (props) => {
33
33
  const { onClose, conversationId, searchClientMsgID, openCreateCannedModal, onOpenThreadInfo, } = props;
34
34
  const conversationData = useConversationStore((state) => state.conversationData);
35
35
  const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
36
- const isGroupChat = isGroupSession(conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType);
37
- const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo);
38
- const currentMemberInGroup = useConversationStore((state) => state.currentMemberInGroup);
39
- // Group/member data refetches async on conversation switch and can briefly
40
- // hold the previous conversation's groupID or a not-yet-loaded roleLevel.
36
+ const isGroupChat = isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined);
37
+ const groupID = conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID;
38
+ const currentGroupInfo = useConversationStore((state) => groupID ? state.currentGroupInfo.get(groupID) : undefined);
39
+ const currentMemberInGroup = useConversationStore((state) => groupID ? state.currentMemberInGroup.get(groupID) : undefined);
40
+ const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
41
+ // "Fresh" now means "we have a cache entry for this groupID" — populated
42
+ // either by a fetch just now or a cache hit from earlier in the session,
43
+ // not necessarily a response that JUST arrived (that's the point of the
44
+ // groupID cache: no spinner on reopening a previously-viewed group).
45
+ const isGroupInfoFresh = currentGroupInfo !== undefined;
41
46
  const isGroupStateFresh = !isGroupChat ||
42
- ((currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.groupID) === (conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID) &&
43
- (currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.groupID) === (conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID) &&
44
- (currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.roleLevel) !== undefined);
47
+ (isGroupInfoFresh &&
48
+ (!currentMemberInGroup || currentMemberInGroup.roleLevel !== undefined));
45
49
  // Group-wide mute (GroupThreadInfo.tsx) restricts Normal members only.
46
50
  const isRestrictedByGroupMute = isGroupChat &&
47
51
  (currentGroupInfo === null || currentGroupInfo === void 0 ? void 0 : currentGroupInfo.status) === GroupStatus.Muted &&
48
52
  (currentMemberInGroup === null || currentMemberInGroup === void 0 ? void 0 : currentMemberInGroup.roleLevel) === GroupMemberRole.Normal;
49
- const canSendMessage = !isGroupChat || (permissions.sendMessage && !isRestrictedByGroupMute);
50
- const canPinMessage = !isGroupChat || permissions.pinMessage;
53
+ // useGroupPermission defaults to Normal-role (sendMessage: true) when
54
+ // currentMemberInGroup is undefined wrong once we know it's absent
55
+ // for good, not just not-loaded-yet.
56
+ const isConfirmedNonMember = isGroupChat && isGroupInfoFresh && !currentMemberInGroup;
57
+ const canSendMessage = !isGroupChat ||
58
+ (!isConfirmedNonMember && permissions.sendMessage && !isRestrictedByGroupMute);
59
+ const canPinMessage = !isGroupChat || (!isConfirmedNonMember && permissions.pinMessage);
51
60
  const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
52
61
  const setSearchClientMsgID = useConversationStore((state) => state.setSearchClientMsgID);
53
62
  const [openMenuId, setOpenMenuId] = useState(null);
@@ -61,6 +70,7 @@ const MessageList = (props) => {
61
70
  const { groupId, latestConversationSession, refetchConversationSessions, } = useConversationSessionState({
62
71
  conversationId,
63
72
  conversationType: conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationType,
73
+ peerType: conversationData === null || conversationData === void 0 ? void 0 : conversationData.peerType,
64
74
  groupId: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID,
65
75
  });
66
76
  const { isJoined, isCheckingMembership, shouldRestrictToLastSession, joinGroup, isJoining, } = useJoinGroupFlow({
@@ -150,6 +160,6 @@ const MessageList = (props) => {
150
160
  if (!conversationData) {
151
161
  return (_jsx("div", { className: "flex flex-1 items-center justify-center h-full", children: connectStatus !== ConnectStatus.Connected ? (_jsx(Spin, {})) : (_jsx(Empty, { description: t("no_conversation_data") })) }));
152
162
  }
153
- return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined, onOpenThreadInfo: onOpenThreadInfo }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: canPinMessage ? handlePinMessage : undefined, onUnpinMessage: canPinMessage ? handleUnpinMessage : undefined }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), isCheckingMembership || !isGroupStateFresh ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: joinGroup, loading: isJoining, children: t("join_group") })] })) : !canSendMessage ? (_jsx("div", { className: "border-t bg-[#f5f5f5] py-3 flex items-center justify-center", children: _jsx("p", { className: "text-sm text-gray-500", children: t(isRestrictedByGroupMute ? "send_message_disabled_group_mute" : "send_message_disabled") }) })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(ConfirmModal, { open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, children: _jsx("p", { children: t("revoke_message_confirm_message") }) }), _jsx(PinLimitModal, { open: pinLimitModalOpen, max: pinnedTotalCount, onClose: () => setPinLimitModalOpen(false) })] }));
163
+ return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, "data-cp-name": "MessageList", children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined, onOpenThreadInfo: onOpenThreadInfo }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage, onPinMessage: canPinMessage ? handlePinMessage : undefined, onUnpinMessage: canPinMessage ? handleUnpinMessage : undefined }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), (isGroupChat && isCheckingMembership) || !isGroupStateFresh ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : isViewOnlyMember ? (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: joinGroup, loading: isJoining, children: t("join_group") })] })) : !canSendMessage ? (_jsx("div", { className: "border-t bg-[#f5f5f5] py-3 flex items-center justify-center", children: _jsx("p", { className: "text-sm text-gray-500", children: t(isRestrictedByGroupMute ? "send_message_disabled_group_mute" : "send_message_disabled") }) })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(ConfirmModal, { open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, children: _jsx("p", { children: t("revoke_message_confirm_message") }) }), _jsx(PinLimitModal, { open: pinLimitModalOpen, max: pinnedTotalCount, onClose: () => setPinLimitModalOpen(false) })] }));
154
164
  };
155
165
  export default MessageList;
@@ -14,7 +14,7 @@ const SelectSession = ({ options, value, onChange, excludeOptions, placeholder,
14
14
  const handleSelect = (val) => {
15
15
  onChange(val);
16
16
  };
17
- return (_jsx("div", { className: "relative shrink-0", children: _jsx(Select, { className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.bgTintColorClassname} custom-select min-w-[100px]`, placement: "bottomLeft", placeholder: placeholder, options: selectOptions, value: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value, onSelect: handleSelect, popupMatchSelectWidth: false, suffixIcon: _jsx(Icon, { icon: "angle-down-o", className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.tintColorClassname} mt-[2px]`, size: 14 }), menuItemSelectedIcon: null, labelRender: () => ["NONE", ""].includes(selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value)
17
+ return (_jsx("div", { className: "relative shrink-0", "data-cp-name": "SelectSession", children: _jsx(Select, { className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.bgTintColorClassname} custom-select min-w-[100px]`, placement: "bottomLeft", placeholder: placeholder, options: selectOptions, value: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value, onSelect: handleSelect, popupMatchSelectWidth: false, suffixIcon: _jsx(Icon, { icon: "angle-down-o", className: `${selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.tintColorClassname} mt-[2px]`, size: 14 }), menuItemSelectedIcon: null, labelRender: () => ["NONE", ""].includes(selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value)
18
18
  ? placeholder
19
19
  : selectedOption
20
20
  ? renderOptionLabel(selectedOption, true)
@@ -1 +1 @@
1
- {"version":3,"file":"UnassignedSessionFooter.d.ts","sourceRoot":"","sources":["../../../src/components/message/UnassignedSessionFooter.tsx"],"names":[],"mappings":"AASA,UAAU,4BAA4B;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,uBAAuB,GAAI,wBAG9B,4BAA4B,mDA2C9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"UnassignedSessionFooter.d.ts","sourceRoot":"","sources":["../../../src/components/message/UnassignedSessionFooter.tsx"],"names":[],"mappings":"AASA,UAAU,4BAA4B;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,uBAAuB,GAAI,wBAG9B,4BAA4B,mDA8C9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -21,6 +21,6 @@ const UnassignedSessionFooter = ({ sessionId, teamId, }) => {
21
21
  antdMessage.error(t("manual_assign_failed"));
22
22
  }
23
23
  };
24
- return (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-amber-500", children: [_jsx(Icon, { icon: "user-del-o", size: 16 }), _jsx("p", { className: "text-sm text-gray-500", children: t("unassigned_thread_notice") })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { type: "primary", onClick: handleAssignToMe, loading: isAssigning, disabled: isAssigning, children: t("assign_to_me") }), _jsx(ManualAssignPopover, { sessionId: sessionId, teamId: teamId, excludeCurrentUser: true, children: _jsx(Button, { disabled: isAssigning, children: t("assign_to_others") }) })] })] }));
24
+ return (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", "data-cp-name": "UnassignedSessionFooter", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-amber-500", children: [_jsx(Icon, { icon: "user-del-o", size: 16 }), _jsx("p", { className: "text-sm text-gray-500", children: t("unassigned_thread_notice") })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { type: "primary", onClick: handleAssignToMe, loading: isAssigning, disabled: isAssigning, children: t("assign_to_me") }), _jsx(ManualAssignPopover, { sessionId: sessionId, teamId: teamId, excludeCurrentUser: true, children: _jsx(Button, { disabled: isAssigning, children: t("assign_to_others") }) })] })] }));
25
25
  };
26
26
  export default UnassignedSessionFooter;
@@ -1 +1 @@
1
- {"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ActionBar.tsx"],"names":[],"mappings":"AAsBA,QAAA,MAAM,SAAS,+CA+Gd,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ActionBar.tsx"],"names":[],"mappings":"AAuBA,QAAA,MAAM,SAAS,+CAiHd,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -11,6 +11,7 @@ import { $isQuoteNode } from "@lexical/rich-text";
11
11
  import { useMessageFooterContext } from ".";
12
12
  import MediaActions from "./MediaActions";
13
13
  import useConversationStore from "../../../store/conversation";
14
+ import { extractMentions } from "./mention/extractMentions";
14
15
  const ActionBar = () => {
15
16
  const [editor] = useLexicalComposerContext();
16
17
  const { onSendMessage, isInternal, listUploadFiles, setListUploadFiles } = useMessageFooterContext();
@@ -30,11 +31,13 @@ const ActionBar = () => {
30
31
  richText = $generateHtmlFromNodes(editor);
31
32
  });
32
33
  if (canSend) {
34
+ const mentions = extractMentions(editor);
33
35
  const sent = onSendMessage({
34
36
  plainText,
35
37
  richText,
36
38
  type: listUploadFiles.length > 0 ? "file" : "text",
37
39
  isInternal,
40
+ mentions,
38
41
  });
39
42
  if (!sent) {
40
43
  return;
@@ -85,6 +88,6 @@ const ActionBar = () => {
85
88
  });
86
89
  });
87
90
  }, [editor]);
88
- return (_jsxs("div", { className: "flex items-center justify-between px-4", children: [_jsx(MediaActions, { listUploadFiles: listUploadFiles, onFilesChange: setListUploadFiles, buttonClassName: "text-gray-500 w-8 h-8 p-0" }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleSend, disabled: !canSend, children: _jsx(Icon, { icon: "send-b", size: 28, className: `${canSend ? "text-blue-500" : "text-gray-400"}` }) })] }));
91
+ return (_jsxs("div", { "data-cp-name": "ActionBar", className: "flex items-center justify-between px-4", children: [_jsx(MediaActions, { listUploadFiles: listUploadFiles, onFilesChange: setListUploadFiles, buttonClassName: "text-gray-500 w-8 h-8 p-0" }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleSend, disabled: !canSend, children: _jsx(Icon, { icon: "send-b", size: 28, className: `${canSend ? "text-blue-500" : "text-gray-400"}` }) })] }));
89
92
  };
90
93
  export default ActionBar;
@@ -8,6 +8,6 @@ const ComposerEditor = ({ isInternal, placeholderText, }) => {
8
8
  const editorClasses = clsx("min-h-[64px] max-h-[140px] overflow-y-auto rounded-md border px-3 py-2 text-sm", isInternal
9
9
  ? "border-orange-300 bg-orange-50"
10
10
  : "border-indigo-500 bg-blue-100");
11
- return (_jsx("div", { className: "px-4", children: _jsx("div", { className: "relative", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: editorClasses }), ErrorBoundary: LexicalErrorBoundary, "aria-placeholder": placeholderText, placeholder: _jsx("div", { className: "absolute left-3 top-2 pointer-events-none", children: _jsx("p", { className: "text-gray-500 text-sm", children: placeholderText }) }) }) }) }));
11
+ return (_jsx("div", { "data-cp-name": "ComposerEditor", className: "px-4", children: _jsx("div", { className: "relative", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: editorClasses }), ErrorBoundary: LexicalErrorBoundary, "aria-placeholder": placeholderText, placeholder: _jsx("div", { className: "absolute left-3 top-2 pointer-events-none", children: _jsx("p", { className: "text-gray-500 text-sm", children: placeholderText }) }) }) }) }));
12
12
  };
13
13
  export default ComposerEditor;
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ComposerTabs.tsx"],"names":[],"mappings":"AAOA,UAAU,iBAAiB;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAeD,QAAA,MAAM,YAAY,GAAI,0EAMnB,iBAAiB,mDAoDnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"ComposerTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ComposerTabs.tsx"],"names":[],"mappings":"AAOA,UAAU,iBAAiB;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAeD,QAAA,MAAM,YAAY,GAAI,0EAMnB,iBAAiB,mDAqDnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -31,7 +31,7 @@ const ComposerTabs = ({ canUseInternal, hintText, isInternal, lockToInternal, se
31
31
  if (!canUseInternal) {
32
32
  return null;
33
33
  }
34
- return (_jsx(Tabs, { activeKey: String(isInternal), items: items, onChange: (value) => {
34
+ return (_jsx(Tabs, { "data-cp-name": "ComposerTabs", activeKey: String(isInternal), items: items, onChange: (value) => {
35
35
  if (lockToInternal && value !== "true") {
36
36
  return;
37
37
  }
@@ -148,7 +148,7 @@ const EmojiPicker = ({ onEmojiSelect, onClose }) => {
148
148
  ],
149
149
  },
150
150
  };
151
- return (_jsx("div", { className: "absolute bottom-full left-0 mb-2 bg-white border border-gray-200 rounded-xl shadow-lg w-96 z-50", children: _jsxs("div", { className: "p-3", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("h3", { className: "font-medium text-gray-900", children: t("choose_emoji") }), _jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-gray-600 text-xl", children: "\u00D7" })] }), _jsx("div", { className: "flex gap-1 mb-3", children: Object.entries(emojiCategories).map(([key, category]) => (_jsx("button", { onClick: () => setActiveCategory(key), className: `px-3 py-1 text-xs rounded-full transition-colors ${activeCategory === key
151
+ return (_jsx("div", { "data-cp-name": "EmojiPicker", className: "absolute bottom-full left-0 mb-2 bg-white border border-gray-200 rounded-xl shadow-lg w-96 z-50", children: _jsxs("div", { className: "p-3", children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsx("h3", { className: "font-medium text-gray-900", children: t("choose_emoji") }), _jsx("button", { onClick: onClose, className: "text-gray-400 hover:text-gray-600 text-xl", children: "\u00D7" })] }), _jsx("div", { className: "flex gap-1 mb-3", children: Object.entries(emojiCategories).map(([key, category]) => (_jsx("button", { onClick: () => setActiveCategory(key), className: `px-3 py-1 text-xs rounded-full transition-colors ${activeCategory === key
152
152
  ? "bg-blue-100 text-blue-600"
153
153
  : "text-gray-500 hover:text-gray-700"}`, children: category.name }, key))) }), _jsx("div", { className: "grid grid-cols-8 gap-1 max-h-48 overflow-y-auto", children: emojiCategories[activeCategory].emojis.map((emoji, index) => (_jsx("button", { onClick: () => onEmojiSelect(emoji), className: "p-2 text-xl hover:bg-gray-100 rounded-lg transition-colors", children: emoji }, index))) })] }) }));
154
154
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EnterHandler.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/EnterHandler.tsx"],"names":[],"mappings":"AAuBA,MAAM,CAAC,OAAO,UAAU,YAAY,SAsInC"}
1
+ {"version":3,"file":"EnterHandler.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/EnterHandler.tsx"],"names":[],"mappings":"AAwBA,MAAM,CAAC,OAAO,UAAU,YAAY,SAgJnC"}
@@ -8,13 +8,19 @@ import { $isQuoteNode } from "@lexical/rich-text";
8
8
  import { useMessageFooterContext } from ".";
9
9
  import useConversationStore from "../../../store/conversation";
10
10
  import emitter, { emit } from "../../../utils/events";
11
+ import { extractMentions } from "./mention/extractMentions";
11
12
  export default function EnterHandler() {
12
13
  const [editor] = useLexicalComposerContext();
13
- const { onSendMessage, isInternal, listUploadFiles, isOpenCanned, activeCannedIndex, } = useMessageFooterContext();
14
+ const { onSendMessage, isInternal, listUploadFiles, isOpenCanned, activeCannedIndex, isMentionMenuOpen, } = useMessageFooterContext();
14
15
  const shiftEnterCount = useRef(0);
15
16
  const quotedMessage = useConversationStore((state) => state.quotedMessage);
16
17
  useEffect(() => {
17
18
  return editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
19
+ // Mention dropdown owns Enter while open (COMMAND_PRIORITY_LOW) —
20
+ // must not preventDefault/consume here or it never gets a turn.
21
+ if (isMentionMenuOpen) {
22
+ return false;
23
+ }
18
24
  // Case 1: Enter (submit, chặn xuống dòng)
19
25
  if (!event.shiftKey) {
20
26
  event.preventDefault();
@@ -35,11 +41,13 @@ export default function EnterHandler() {
35
41
  const hasQuote = !!(quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.clientMsgID);
36
42
  const canSend = hasQuote ? hasText : hasText || hasFiles;
37
43
  if (canSend) {
44
+ const mentions = extractMentions(editor);
38
45
  const sent = onSendMessage({
39
46
  plainText,
40
47
  richText,
41
48
  type: hasFiles ? "file" : "text",
42
49
  isInternal,
50
+ mentions,
43
51
  });
44
52
  if (!sent) {
45
53
  return true;
@@ -97,6 +105,7 @@ export default function EnterHandler() {
97
105
  isInternal,
98
106
  isOpenCanned,
99
107
  activeCannedIndex,
108
+ isMentionMenuOpen,
100
109
  ]);
101
110
  useEffect(() => {
102
111
  const clearEditor = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/FilePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AA6IlC,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,YAAY,GACb,EAAE;IACD,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B,kDAsBA;AAED,QAAA,MAAM,WAAW,+CAQhB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/FilePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AA8IlC,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,YAAY,GACb,EAAE;IACD,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B,kDAsBA;AAED,QAAA,MAAM,WAAW,+CAQhB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -25,7 +25,7 @@ const getFileType = (file) => {
25
25
  return "video";
26
26
  return "image";
27
27
  };
28
- const RemoveButton = ({ file, onRemove }) => (_jsx("button", { type: "button", onClick: () => onRemove(file), className: "absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-gray-900", "aria-label": "X\u00F3a", children: _jsx(Icon, { icon: "close-o", size: 12, className: "text-white" }) }));
28
+ const RemoveButton = ({ file, onRemove }) => (_jsx("button", { type: "button", "data-cp-name": "RemoveButton", onClick: () => onRemove(file), className: "absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-gray-900", "aria-label": "X\u00F3a", children: _jsx(Icon, { icon: "close-o", size: 12, className: "text-white" }) }));
29
29
  const MediaThumb = ({ file, onRemove, onVideoReady }) => {
30
30
  var _a;
31
31
  const [src, setSrc] = useState("");
@@ -48,18 +48,18 @@ const MediaThumb = ({ file, onRemove, onVideoReady }) => {
48
48
  setDuration(event.currentTarget.duration);
49
49
  onVideoReady === null || onVideoReady === void 0 ? void 0 : onVideoReady();
50
50
  };
51
- return (_jsxs("div", { className: "relative h-12 w-12 shrink-0", children: [isVideo ? (_jsx("video", { src: src, className: "h-12 w-12 rounded-lg object-cover", preload: "metadata", muted: true, onLoadedMetadata: handleLoadedMetadata })) : (_jsx("img", { src: src, alt: file.name, className: "h-12 w-12 rounded-lg object-cover" })), isLoading && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center rounded-lg bg-black/60", children: _jsxs("span", { className: "text-xs font-semibold text-white", children: [percent, "%"] }) })), isVideo && duration !== null && (_jsx("div", { className: "absolute bottom-1 left-1/2 flex w-9 -translate-x-1/2 items-center justify-center rounded-xl bg-black/70 px-1 text-center text-[10px] font-normal leading-4 text-white", children: formatDuration(duration) })), _jsx(RemoveButton, { file: file, onRemove: onRemove })] }));
51
+ return (_jsxs("div", { "data-cp-name": "MediaThumb", className: "relative h-12 w-12 shrink-0", children: [isVideo ? (_jsx("video", { src: src, className: "h-12 w-12 rounded-lg object-cover", preload: "metadata", muted: true, onLoadedMetadata: handleLoadedMetadata })) : (_jsx("img", { src: src, alt: file.name, className: "h-12 w-12 rounded-lg object-cover" })), isLoading && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center rounded-lg bg-black/60", children: _jsxs("span", { className: "text-xs font-semibold text-white", children: [percent, "%"] }) })), isVideo && duration !== null && (_jsx("div", { className: "absolute bottom-1 left-1/2 flex w-9 -translate-x-1/2 items-center justify-center rounded-xl bg-black/70 px-1 text-center text-[10px] font-normal leading-4 text-white", children: formatDuration(duration) })), _jsx(RemoveButton, { file: file, onRemove: onRemove })] }));
52
52
  };
53
53
  const DocumentCard = ({ file, onRemove }) => {
54
54
  var _a, _b;
55
55
  const isLoading = file.status === "uploading";
56
56
  const percent = Math.round((_a = file.percent) !== null && _a !== void 0 ? _a : 0);
57
- return (_jsxs("div", { className: "relative flex h-12 w-40 shrink-0 items-center gap-[7px] rounded-lg bg-chat-bubble-neutral/10 py-[4px] pl-2 pr-5", children: [_jsx("div", { className: "flex h-full w-8 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-8 [&>svg]:w-8", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[11px] font-normal leading-[160%] text-gray-900", children: shortenFileName(file.name) }), isLoading ? (_jsxs("span", { className: "text-[10px] leading-[160%] tracking-[0.1px] text-gray-400", children: [percent, "%"] })) : (_jsx("span", { className: "text-[10px] leading-[160%] tracking-[0.1px] text-gray-400", children: formatFileSize((_b = file.size) !== null && _b !== void 0 ? _b : 0) }))] }), _jsx(RemoveButton, { file: file, onRemove: onRemove })] }));
57
+ return (_jsxs("div", { "data-cp-name": "DocumentCard", className: "relative flex h-12 w-40 shrink-0 items-center gap-[7px] rounded-lg bg-chat-bubble-neutral/10 py-[4px] pl-2 pr-5", children: [_jsx("div", { className: "flex h-full w-8 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-8 [&>svg]:w-8", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[11px] font-normal leading-[160%] text-gray-900", children: shortenFileName(file.name) }), isLoading ? (_jsxs("span", { className: "text-[10px] leading-[160%] tracking-[0.1px] text-gray-400", children: [percent, "%"] })) : (_jsx("span", { className: "text-[10px] leading-[160%] tracking-[0.1px] text-gray-400", children: formatFileSize((_b = file.size) !== null && _b !== void 0 ? _b : 0) }))] }), _jsx(RemoveButton, { file: file, onRemove: onRemove })] }));
58
58
  };
59
59
  export function FilePreviewList({ files, onRemove, onVideoReady, }) {
60
60
  if (files.length === 0)
61
61
  return null;
62
- return (_jsx("div", { className: "flex items-center gap-3 self-stretch overflow-x-auto px-2 pb-2 pt-3", children: files.map((file) => {
62
+ return (_jsx("div", { "data-cp-name": "FilePreviewList", className: "flex items-center gap-3 self-stretch overflow-x-auto px-2 pb-2 pt-3", children: files.map((file) => {
63
63
  if (getFileType(file) === "document") {
64
64
  return (_jsx(DocumentCard, { file: file, onRemove: onRemove }, file.uid));
65
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LinkInputPreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/LinkInputPreview.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,mBAAmB,qBAAqB,4CAoEjE,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"LinkInputPreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/LinkInputPreview.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,mBAAmB,qBAAqB,4CAqEjE,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -11,6 +11,6 @@ const LinkInputPreview = ({ url, onRemove }) => {
11
11
  const handleOpen = () => {
12
12
  openLink(url, t);
13
13
  };
14
- return (_jsxs("div", { "data-testid": "link-input-preview", className: "flex w-full shrink-0 items-center gap-2 overflow-hidden bg-blue-25 pr-2", children: [_jsxs("button", { type: "button", onClick: handleOpen, className: "flex min-w-0 flex-1 items-center gap-2 py-0 pl-0 text-left", children: [_jsx("div", { className: "flex h-[51px] w-[51px] shrink-0 items-center justify-center overflow-hidden bg-blue-25", children: isLoading ? (_jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary-400 border-t-transparent" })) : (data === null || data === void 0 ? void 0 : data.image) ? (_jsx("img", { src: data.image, alt: "", className: "h-full w-full object-cover" })) : (_jsx(Icon, { icon: "link-alt-b", size: 24, className: "text-primary-400" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [isLoading ? (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: t("link_preview.loading") })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: (data === null || data === void 0 ? void 0 : data.title) || getHostLabel(url) }), ((data === null || data === void 0 ? void 0 : data.description) || !(data === null || data === void 0 ? void 0 : data.title)) && (_jsx("p", { className: "truncate text-[13px] leading-[1.6] text-gray-400", children: (data === null || data === void 0 ? void 0 : data.description) || getHostLabel(url) }))] })), isError && !isLoading && (_jsx("p", { className: "truncate text-[13px] leading-[1.6] text-gray-400", children: getHostLabel(url) }))] })] }), _jsx("button", { type: "button", onClick: onRemove, "data-testid": "link-input-preview-remove", className: "flex h-4 w-4 shrink-0 items-center justify-center", "aria-label": t("link_preview.remove"), children: _jsx(Icon, { icon: "close-b", size: 16, className: "text-gray-900" }) })] }));
14
+ return (_jsxs("div", { "data-testid": "link-input-preview", "data-cp-name": "LinkInputPreview", className: "flex w-full shrink-0 items-center gap-2 overflow-hidden bg-blue-25 pr-2", children: [_jsxs("button", { type: "button", onClick: handleOpen, className: "flex min-w-0 flex-1 items-center gap-2 py-0 pl-0 text-left", children: [_jsx("div", { className: "flex h-[51px] w-[51px] shrink-0 items-center justify-center overflow-hidden bg-blue-25", children: isLoading ? (_jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary-400 border-t-transparent" })) : (data === null || data === void 0 ? void 0 : data.image) ? (_jsx("img", { src: data.image, alt: "", className: "h-full w-full object-cover" })) : (_jsx(Icon, { icon: "link-alt-b", size: 24, className: "text-primary-400" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [isLoading ? (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: t("link_preview.loading") })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: (data === null || data === void 0 ? void 0 : data.title) || getHostLabel(url) }), ((data === null || data === void 0 ? void 0 : data.description) || !(data === null || data === void 0 ? void 0 : data.title)) && (_jsx("p", { className: "truncate text-[13px] leading-[1.6] text-gray-400", children: (data === null || data === void 0 ? void 0 : data.description) || getHostLabel(url) }))] })), isError && !isLoading && (_jsx("p", { className: "truncate text-[13px] leading-[1.6] text-gray-400", children: getHostLabel(url) }))] })] }), _jsx("button", { type: "button", onClick: onRemove, "data-testid": "link-input-preview-remove", className: "flex h-4 w-4 shrink-0 items-center justify-center", "aria-label": t("link_preview.remove"), children: _jsx(Icon, { icon: "close-b", size: 16, className: "text-gray-900" }) })] }));
15
15
  };
16
16
  export default LinkInputPreview;
@@ -97,5 +97,5 @@ export default function MediaActions({ listUploadFiles, onFilesChange, buttonCla
97
97
  return () => document.removeEventListener("mousedown", handleClickOutside);
98
98
  }, []);
99
99
  const btnClass = buttonClassName !== null && buttonClassName !== void 0 ? buttonClassName : "w-8 h-8 p-0 text-gray-500 hover:text-gray-700 hover:bg-gray-100";
100
- return (_jsxs("div", { className: "flex items-center gap-1 relative", ref: containerRef, children: [isCrm && (_jsx(Button, { type: "text", shape: "default", className: clsx(btnClass, isOpenCanned && "bg-blue-100 text-blue-600"), onClick: onPressCanned, children: _jsx(CannedResponseIcon, { className: clsx("hover:text-gray-700", isOpenCanned && "text-blue-600") }) })), _jsx(Button, { type: "text", shape: "default", className: clsx(btnClass, showEmojiPicker && "bg-blue-100 text-blue-600"), onClick: () => setShowEmojiPicker(!showEmojiPicker), children: EmojiIcon }), showMediaUpload && (_jsxs(_Fragment, { children: [_jsx(Upload, { accept: "image/jpeg, image/png, image/jpg, video/*", beforeUpload: beforeUploadImagesAndVideo, multiple: true, onChange: handleChange, showUploadList: false, fileList: listUploadFiles, children: _jsx(Button, { type: "text", shape: "default", className: btnClass, children: _jsx(Icon, { icon: "image-02-o", size: 22 }) }) }), _jsx(Upload, { accept: ".doc,.docx,.pdf", beforeUpload: beforeUploadFile, onChange: handleChange, showUploadList: false, fileList: listUploadFiles, children: _jsx(Button, { type: "text", shape: "default", className: btnClass, children: AttachIcon }) })] })), showEmojiPicker && (_jsx(EmojiPicker, { onEmojiSelect: handleEmojiSelect, onClose: () => setShowEmojiPicker(false) }))] }));
100
+ return (_jsxs("div", { "data-cp-name": "MediaActions", className: "flex items-center gap-1 relative", ref: containerRef, children: [isCrm && (_jsx(Button, { type: "text", shape: "default", className: clsx(btnClass, isOpenCanned && "bg-blue-100 text-blue-600"), onClick: onPressCanned, children: _jsx(CannedResponseIcon, { className: clsx("hover:text-gray-700", isOpenCanned && "text-blue-600") }) })), _jsx(Button, { type: "text", shape: "default", className: clsx(btnClass, showEmojiPicker && "bg-blue-100 text-blue-600"), onClick: () => setShowEmojiPicker(!showEmojiPicker), children: EmojiIcon }), showMediaUpload && (_jsxs(_Fragment, { children: [_jsx(Upload, { accept: "image/jpeg, image/png, image/jpg, video/*", beforeUpload: beforeUploadImagesAndVideo, multiple: true, onChange: handleChange, showUploadList: false, fileList: listUploadFiles, children: _jsx(Button, { type: "text", shape: "default", className: btnClass, children: _jsx(Icon, { icon: "image-02-o", size: 22 }) }) }), _jsx(Upload, { accept: ".doc,.docx,.pdf", beforeUpload: beforeUploadFile, onChange: handleChange, showUploadList: false, fileList: listUploadFiles, children: _jsx(Button, { type: "text", shape: "default", className: btnClass, children: AttachIcon }) })] })), showEmojiPicker && (_jsx(EmojiPicker, { onEmojiSelect: handleEmojiSelect, onClose: () => setShowEmojiPicker(false) }))] }));
101
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SessionClosedModal.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/SessionClosedModal.tsx"],"names":[],"mappings":"AAKA,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,kBAAkB,GAAI,oDAMzB,uBAAuB,4CAmDzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"SessionClosedModal.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/SessionClosedModal.tsx"],"names":[],"mappings":"AAKA,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,kBAAkB,GAAI,oDAMzB,uBAAuB,4CAoDzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -4,6 +4,6 @@ import { Modal, Button } from "antd";
4
4
  import { useTranslation } from "react-i18next";
5
5
  const SessionClosedModal = ({ open, loading, onReopen, onCreateNew, onClose, }) => {
6
6
  const { t } = useTranslation();
7
- return (_jsx(Modal, { open: open, onCancel: onClose, footer: null, closable: !loading, centered: true, width: 400, maskClosable: !loading, keyboard: !loading, forceRender: true, children: _jsxs("div", { className: "flex flex-col gap-4 pt-2", role: "alertdialog", "aria-label": t("session_closed_modal_title"), children: [_jsx("p", { className: "text-base font-semibold", children: t("session_closed_modal_title") }), _jsx("p", { className: "text-sm text-gray-600", children: t("session_closed_modal_description") }), _jsxs("div", { className: "flex gap-3 w-full", children: [_jsx(Button, { type: "primary", className: "flex-1", size: "large", onClick: onReopen, loading: loading, disabled: loading, children: t("session_closed_modal_reopen") }), _jsx(Button, { type: "primary", className: "flex-1", size: "large", onClick: onCreateNew, loading: loading, disabled: loading, children: t("session_closed_modal_create_new") })] })] }) }));
7
+ return (_jsx(Modal, { "data-cp-name": "SessionClosedModal", open: open, onCancel: onClose, footer: null, closable: !loading, centered: true, width: 400, maskClosable: !loading, keyboard: !loading, forceRender: true, children: _jsxs("div", { className: "flex flex-col gap-4 pt-2", role: "alertdialog", "aria-label": t("session_closed_modal_title"), children: [_jsx("p", { className: "text-base font-semibold", children: t("session_closed_modal_title") }), _jsx("p", { className: "text-sm text-gray-600", children: t("session_closed_modal_description") }), _jsxs("div", { className: "flex gap-3 w-full", children: [_jsx(Button, { type: "primary", className: "flex-1", size: "large", onClick: onReopen, loading: loading, disabled: loading, children: t("session_closed_modal_reopen") }), _jsx(Button, { type: "primary", className: "flex-1", size: "large", onClick: onCreateNew, loading: loading, disabled: loading, children: t("session_closed_modal_create_new") })] })] }) }));
8
8
  };
9
9
  export default SessionClosedModal;
@@ -153,7 +153,7 @@ export const ToolbarPlugin = () => {
153
153
  removeSelectionListener();
154
154
  };
155
155
  }, [editor]);
156
- return (_jsxs("div", { className: "flex items-center gap-2 px-4 pt-1", children: [formatTextButtons.map((button) => {
156
+ return (_jsxs("div", { "data-cp-name": "ToolbarPlugin", className: "flex items-center gap-2 px-4 pt-1", children: [formatTextButtons.map((button) => {
157
157
  const { icon, onPress, key, isActive } = button;
158
158
  return (_jsx(Button, { type: "text", shape: "default", className: getButtonClasses(isActive), onClick: onPress, children: icon }, key));
159
159
  }), insertListButtons.map((button) => {
@@ -1,6 +1,7 @@
1
1
  import { LinkNode } from "@lexical/link";
2
2
  import { HeadingNode, QuoteNode } from "@lexical/rich-text";
3
3
  import { ListItemNode, ListNode } from "@lexical/list";
4
+ import { MentionNode } from "./mention/MentionNode";
4
5
  export declare const editorTheme: {
5
6
  text: {
6
7
  bold: string;
@@ -18,7 +19,7 @@ export declare const editorTheme: {
18
19
  };
19
20
  link: string;
20
21
  };
21
- export declare const editorNodes: (typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
22
+ export declare const editorNodes: (typeof MentionNode | typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
22
23
  export declare const editorOnError: (error: Error) => void;
23
24
  export declare const DOCUMENT_TYPES: string[];
24
25
  //# sourceMappingURL=editorConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editorConfig.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/editorConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CAcvB,CAAC;AAEF,eAAO,MAAM,WAAW,qGAMvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,SAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,UAI1B,CAAC"}
1
+ {"version":3,"file":"editorConfig.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/editorConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CAcvB,CAAC;AAEF,eAAO,MAAM,WAAW,0HAOvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,SAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,UAI1B,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { LinkNode } from "@lexical/link";
2
2
  import { HeadingNode, QuoteNode } from "@lexical/rich-text";
3
3
  import { ListItemNode, ListNode } from "@lexical/list";
4
+ import { MentionNode } from "./mention/MentionNode";
4
5
  export const editorTheme = {
5
6
  text: {
6
7
  bold: "font-bold",
@@ -22,6 +23,7 @@ export const editorNodes = [
22
23
  ListItemNode,
23
24
  QuoteNode,
24
25
  LinkNode,
26
+ MentionNode,
25
27
  ];
26
28
  export const editorOnError = (error) => {
27
29
  console.error(error);
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAEL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAY/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CA4SpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAGL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CAuUpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -27,6 +27,7 @@ import useConversationStore from "../../../store/conversation";
27
27
  import { useCurrentUserAccountType } from "../../../hooks/user/useCurrentUserAccountType";
28
28
  import ComposerTabs from "./ComposerTabs";
29
29
  import ComposerEditor from "./ComposerEditor";
30
+ import MentionMenu from "./mention/MentionMenu";
30
31
  import SessionClosedModal from "./SessionClosedModal";
31
32
  import { useCreateSession, useReopenSession, } from "../../../hooks/session/useReopenOrCreateSession";
32
33
  import { emit } from "../../../utils/events";
@@ -49,10 +50,13 @@ export const MessageFooterContext = createContext({
49
50
  setActiveCannedIndex: () => { },
50
51
  maxActiveCannedIndex: 0,
51
52
  setMaxActiveCannedIndex: () => { },
53
+ isMentionMenuOpen: false,
54
+ setIsMentionMenuOpen: () => { },
52
55
  });
53
56
  export const useMessageFooterContext = () => useContext(MessageFooterContext);
54
57
  const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
55
58
  const { t } = useTranslation();
59
+ const { t: tConversationInbox } = useTranslation("conversation-inbox");
56
60
  const { sendMergeMessage } = useSendMessage();
57
61
  const accountType = useCurrentUserAccountType();
58
62
  const [listUploadFiles, setListUploadFiles] = useState([]);
@@ -64,8 +68,10 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
64
68
  const [activeCannedIndex, setActiveCannedIndex] = useState(0);
65
69
  const [maxActiveCannedIndex, setMaxActiveCannedIndex] = useState(0);
66
70
  const [isInternal, setIsInternal] = useState(false);
71
+ const [isMentionMenuOpen, setIsMentionMenuOpen] = useState(false);
67
72
  const quotedMessage = useConversationStore((state) => state.quotedMessage);
68
73
  const conversationData = useConversationStore((state) => state.conversationData);
74
+ const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
69
75
  // Internal notes are a CX-support concept (team-only remarks not sent to
70
76
  // the customer) — meaningless inside a real member-managed group, where
71
77
  // everyone in the thread already is the "team".
@@ -112,7 +118,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
112
118
  const placeholderText = isInternal
113
119
  ? t("enter_internal_message")
114
120
  : t("enter_message");
115
- const onSendMessage = useCallback(({ plainText, richText, type, isInternal, }) => {
121
+ const onSendMessage = useCallback(({ plainText, richText, type, isInternal, mentions, }) => {
116
122
  if ((currentSession === null || currentSession === void 0 ? void 0 : currentSession.isClosed) && !isInternal) {
117
123
  pendingMessageRef.current = {
118
124
  plainText,
@@ -121,6 +127,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
121
127
  isInternal,
122
128
  files: [...listUploadFiles],
123
129
  urlMetadata: resolveUrlMetadata(),
130
+ mentions,
124
131
  };
125
132
  openSessionClosedModal();
126
133
  return false;
@@ -132,6 +139,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
132
139
  currentSession,
133
140
  isInternal,
134
141
  urlMetadata: resolveUrlMetadata(),
142
+ mentions,
135
143
  });
136
144
  setListUploadFiles([]);
137
145
  return true;
@@ -154,6 +162,7 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
154
162
  currentSession: sessionToUse,
155
163
  isInternal: pending.isInternal,
156
164
  urlMetadata: pending.urlMetadata,
165
+ mentions: pending.mentions,
157
166
  });
158
167
  setListUploadFiles([]);
159
168
  pendingMessageRef.current = null;
@@ -206,6 +215,9 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
206
215
  }
207
216
  closeCanned();
208
217
  };
218
+ if (isViewOnlyMember) {
219
+ return (_jsx("div", { "data-testid": "message-footer-view-only", className: "flex w-full items-center justify-center border-t border-gray-25 bg-white px-4 py-3 text-center text-sm text-gray-500", children: tConversationInbox("thread_detail.view_only_notice") }));
220
+ }
209
221
  return (_jsxs(MessageFooterContext.Provider, { value: {
210
222
  onSendMessage,
211
223
  isInternal,
@@ -218,8 +230,10 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
218
230
  setActiveCannedIndex,
219
231
  maxActiveCannedIndex,
220
232
  setMaxActiveCannedIndex,
233
+ isMentionMenuOpen,
234
+ setIsMentionMenuOpen,
221
235
  }, children: [_jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Popover, { open: isOpenCanned, content: _jsx(CannedResponse, { onClose: closeCanned, openCreateCannedModal: onOpenCreateCannedModal, cannedQuery: cannedQuery }), placement: "topLeft", trigger: "click", arrow: false, classNames: {
222
236
  body: "mx-1 !p-0",
223
- }, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && _jsx(FilePreview, {}), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setIsLinkPreviewDismissed(true) })), _jsx(ToolbarPlugin, {}), _jsxs("div", { children: [_jsx(ComposerTabs, { canUseInternal: canUseInternal, hintText: t("canned_response_hint"), isInternal: isInternal, lockToInternal: lockToInternal, setIsInternal: setIsInternal }), _jsx(ComposerEditor, { isInternal: isInternal, placeholderText: placeholderText })] }), _jsx(ActionBar, {})] }) }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(ComposerTextSyncPlugin, { onChange: setComposerText }), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {}), isCrm && (_jsx(CannedResponseTriggerPlugin, { onClose: closeCanned, onOpen: onOpenCanned }))] }), _jsx(SessionClosedModal, { open: isSessionClosedModalOpen, loading: isSessionActionLoading, onReopen: handleReopenSession, onCreateNew: handleCreateNewSession, onClose: handleCloseSessionModal })] }));
237
+ }, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && _jsx(FilePreview, {}), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setIsLinkPreviewDismissed(true) })), _jsx(ToolbarPlugin, {}), _jsxs("div", { children: [_jsx(ComposerTabs, { canUseInternal: canUseInternal, hintText: t("canned_response_hint"), isInternal: isInternal, lockToInternal: lockToInternal, setIsInternal: setIsInternal }), _jsx(ComposerEditor, { isInternal: isInternal, placeholderText: placeholderText })] }), _jsx(ActionBar, {})] }) }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(ComposerTextSyncPlugin, { onChange: setComposerText }), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {}), isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined) && (_jsx(MentionMenu, { groupID: conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID })), isCrm && (_jsx(CannedResponseTriggerPlugin, { onClose: closeCanned, onOpen: onOpenCanned }))] }), _jsx(SessionClosedModal, { open: isSessionClosedModalOpen, loading: isSessionActionLoading, onReopen: handleReopenSession, onCreateNew: handleCreateNewSession, onClose: handleCloseSessionModal })] }));
224
238
  };
225
239
  export default MessageFooterProvider;