@droppii-org/chat-sdk 0.6.40 → 0.6.41

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.
@@ -1,3 +1,9 @@
1
- declare const PinnedMessageBar: () => import("react/jsx-runtime").JSX.Element | null;
1
+ interface PinnedMessageBarProps {
2
+ /** CRM spec labels every pin "Tin nhắn từ {name}"; BIZ varies the label by message type. */
3
+ genericSubtitle?: boolean;
4
+ /** Hides unpin in the pinned panel for users the toolbox already denies pinning. */
5
+ canUnpin?: boolean;
6
+ }
7
+ declare const PinnedMessageBar: ({ genericSubtitle, canUnpin, }: PinnedMessageBarProps) => import("react/jsx-runtime").JSX.Element | null;
2
8
  export default PinnedMessageBar;
3
9
  //# sourceMappingURL=PinnedMessageBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PinnedMessageBar.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageBar.tsx"],"names":[],"mappings":"AA6HA,QAAA,MAAM,gBAAgB,sDAgGrB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"PinnedMessageBar.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageBar.tsx"],"names":[],"mappings":"AA6HA,UAAU,qBAAqB;IAC7B,4FAA4F;IAC5F,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,gBAAgB,GAAI,gCAGvB,qBAAqB,mDAkGvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -69,7 +69,7 @@ const PinnedMessageThumbnail = ({ message }) => {
69
69
  }
70
70
  return null;
71
71
  };
72
- const PinnedMessageBar = () => {
72
+ const PinnedMessageBar = ({ genericSubtitle = false, canUnpin = true, }) => {
73
73
  const { t } = useTranslation();
74
74
  const userID = useAuthStore((state) => state.userID);
75
75
  const conversation = useConversationStore((state) => state.conversationData);
@@ -91,7 +91,8 @@ const PinnedMessageBar = () => {
91
91
  ? t("your_self")
92
92
  : latestPinnedMessage.senderNickname || t("message_sender_unnamed");
93
93
  const isRevoked = latestPinnedMessage.contentType === MessageType.RevokeMessage;
94
- const subtitleKey = PINNED_SUBTITLE_KEY_BY_TYPE[latestPinnedMessage.contentType] ||
94
+ const subtitleKey = (!genericSubtitle &&
95
+ PINNED_SUBTITLE_KEY_BY_TYPE[latestPinnedMessage.contentType]) ||
95
96
  "pinned_from_text";
96
97
  const title = isRevoked
97
98
  ? t("revoked")
@@ -104,6 +105,6 @@ const PinnedMessageBar = () => {
104
105
  const hasFlushThumbnail = hasThumbnail &&
105
106
  latestPinnedMessage.contentType !== MessageType.FileMessage;
106
107
  const remainingPinnedCount = pinnedTotalCount - 1;
107
- return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "pinned-message-bar", "data-cp-name": "PinnedMessageBar", role: "button", tabIndex: 0, onClick: () => setIsPanelOpen(true), className: clsx("flex w-full shrink-0 cursor-pointer items-center gap-3 bg-gray-cool-25 pr-3", hasFlushThumbnail ? "py-0 pl-0" : "py-1 pl-3"), children: [hasThumbnail && (_jsx(PinnedMessageThumbnail, { message: latestPinnedMessage })), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center", children: [showTitle && (_jsx("p", { className: "truncate text-sm font-medium leading-[160%] text-gray-900", children: title })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-[var(--dc-color-primary)]" }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: t(subtitleKey, { name: senderName }) })] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [remainingPinnedCount > 0 && (_jsxs("span", { className: "flex min-w-[26px] items-center justify-center rounded-full border-2 border-white bg-gradient-danger-light px-1 text-xs font-bold leading-[160%] text-white", children: ["+", remainingPinnedCount] })), _jsx(Icon, { icon: "angle-down-o", size: 20, className: "text-gray-600" })] })] }), _jsx(PinnedMessagesPanel, { open: isPanelOpen, onClose: () => setIsPanelOpen(false) })] }));
108
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "pinned-message-bar", "data-cp-name": "PinnedMessageBar", role: "button", tabIndex: 0, onClick: () => setIsPanelOpen(true), className: clsx("flex w-full shrink-0 cursor-pointer items-center gap-3 bg-gray-cool-25 pr-3", hasFlushThumbnail ? "py-0 pl-0" : "py-1 pl-3"), children: [hasThumbnail && (_jsx(PinnedMessageThumbnail, { message: latestPinnedMessage })), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center", children: [showTitle && (_jsx("p", { className: "truncate text-sm font-medium leading-[160%] text-gray-900", children: title })), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-[var(--dc-color-primary)]" }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-600", children: t(subtitleKey, { name: senderName }) })] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [remainingPinnedCount > 0 && (_jsxs("span", { className: "flex min-w-[26px] items-center justify-center rounded-full border-2 border-white bg-gradient-danger-light px-1 text-xs font-bold leading-[160%] text-white", children: ["+", remainingPinnedCount] })), _jsx(Icon, { icon: "angle-down-o", size: 20, className: "text-gray-600" })] })] }), _jsx(PinnedMessagesPanel, { open: isPanelOpen, onClose: () => setIsPanelOpen(false), canUnpin: canUnpin })] }));
108
109
  };
109
110
  export default PinnedMessageBar;
@@ -5,7 +5,8 @@ interface PinnedMessageItemProps {
5
5
  onContextMenuOpenChange: (open: boolean) => void;
6
6
  onUnpin: (message: MessageItemType) => void;
7
7
  onJump: (message: MessageItemType) => void;
8
+ canUnpin?: boolean;
8
9
  }
9
- declare const PinnedMessageItem: ({ message, contextMenuOpen, onContextMenuOpenChange, onUnpin, onJump, }: PinnedMessageItemProps) => import("react/jsx-runtime").JSX.Element;
10
+ declare const PinnedMessageItem: ({ message, contextMenuOpen, onContextMenuOpenChange, onUnpin, onJump, canUnpin, }: PinnedMessageItemProps) => import("react/jsx-runtime").JSX.Element;
10
11
  export default PinnedMessageItem;
11
12
  //# sourceMappingURL=PinnedMessageItem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PinnedMessageItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageItem.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAY9E,UAAU,sBAAsB;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,uBAAuB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;CAC5C;AAED,QAAA,MAAM,iBAAiB,GAAI,yEAMxB,sBAAsB,4CAsFxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"PinnedMessageItem.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessageItem.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAY9E,UAAU,sBAAsB;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,uBAAuB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C,MAAM,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,iBAAiB,GAAI,mFAOxB,sBAAsB,4CAqFxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -8,17 +8,18 @@ import MessageBubble from "../../components/message/item/MessageBubble";
8
8
  import { renderBubbleContent } from "../../components/message/item/renderMessageContent";
9
9
  import { buildMessageToolboxMenuItems, MessageToolboxActionKey, MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, } from "../../components/message/toolbox";
10
10
  import useAuthStore from "../../store/auth";
11
- const PinnedMessageItem = ({ message, contextMenuOpen, onContextMenuOpenChange, onUnpin, onJump, }) => {
11
+ const PinnedMessageItem = ({ message, contextMenuOpen, onContextMenuOpenChange, onUnpin, onJump, canUnpin = true, }) => {
12
12
  const { t } = useTranslation();
13
13
  const userID = useAuthStore((state) => state.userID);
14
14
  const isMine = (message === null || message === void 0 ? void 0 : message.sendID) === userID;
15
+ const unpinAction = {
16
+ key: MessageToolboxActionKey.UNPIN,
17
+ label: t("context_menu_unpin"),
18
+ icon: "thumbtack-off-o",
19
+ onClick: () => onUnpin(message),
20
+ };
15
21
  const contextMenuItems = buildMessageToolboxMenuItems([
16
- {
17
- key: MessageToolboxActionKey.UNPIN,
18
- label: t("context_menu_unpin"),
19
- icon: "thumbtack-off-o",
20
- onClick: () => onUnpin(message),
21
- },
22
+ ...(canUnpin ? [unpinAction] : []),
22
23
  {
23
24
  key: MessageToolboxActionKey.VIEW_ORIGINAL,
24
25
  label: t("context_menu_view_original"),
@@ -32,6 +33,6 @@ const PinnedMessageItem = ({ message, contextMenuOpen, onContextMenuOpenChange,
32
33
  event.stopPropagation();
33
34
  onUnpin(message);
34
35
  }, className: "flex h-7 w-7 shrink-0 items-center justify-center self-center rounded-full bg-gray-25 text-gray-600", children: _jsx(Icon, { icon: "thumbtack-off-o", size: 16 }) }));
35
- return (_jsxs("div", { "data-cp-name": "PinnedMessageItem", className: clsx("flex items-end gap-2 px-3 pb-4", isMine ? "justify-end" : "justify-start"), children: [isMine && unpinButton, _jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsxs("div", { className: "relative min-w-0 cursor-pointer", onClick: () => onJump(message), children: [_jsx("div", { className: "pointer-events-none", children: bubbleNode }), pinnedBadgeNode] }) }), !isMine && unpinButton] }));
36
+ return (_jsxs("div", { "data-cp-name": "PinnedMessageItem", className: clsx("flex items-end gap-2 px-3 pb-4", isMine ? "justify-end" : "justify-start"), children: [isMine && canUnpin && unpinButton, _jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsxs("div", { className: "relative min-w-0 cursor-pointer", onClick: () => onJump(message), children: [_jsx("div", { className: "pointer-events-none", children: bubbleNode }), pinnedBadgeNode] }) }), !isMine && canUnpin && unpinButton] }));
36
37
  };
37
38
  export default PinnedMessageItem;
@@ -1,7 +1,8 @@
1
1
  interface PinnedMessagesPanelProps {
2
2
  open: boolean;
3
3
  onClose: () => void;
4
+ canUnpin?: boolean;
4
5
  }
5
- declare const PinnedMessagesPanel: ({ open, onClose }: PinnedMessagesPanelProps) => import("react/jsx-runtime").JSX.Element;
6
+ declare const PinnedMessagesPanel: ({ open, onClose, canUnpin, }: PinnedMessagesPanelProps) => import("react/jsx-runtime").JSX.Element;
6
7
  export default PinnedMessagesPanel;
7
8
  //# sourceMappingURL=PinnedMessagesPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PinnedMessagesPanel.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessagesPanel.tsx"],"names":[],"mappings":"AAYA,UAAU,wBAAwB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,mBAAmB,GAAI,mBAAmB,wBAAwB,4CAoGvE,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"PinnedMessagesPanel.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/PinnedMessagesPanel.tsx"],"names":[],"mappings":"AAYA,UAAU,wBAAwB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,mBAAmB,GAAI,8BAI1B,wBAAwB,4CAqG1B,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -8,7 +8,7 @@ import useConversationStore from "../../store/conversation";
8
8
  import { usePinMessage } from "../../hooks/message/usePinMessage";
9
9
  import { emit } from "../../utils/events";
10
10
  import PinnedMessageItem from "./PinnedMessageItem";
11
- const PinnedMessagesPanel = ({ open, onClose }) => {
11
+ const PinnedMessagesPanel = ({ open, onClose, canUnpin = true, }) => {
12
12
  const { t } = useTranslation();
13
13
  const conversation = useConversationStore((state) => state.conversationData);
14
14
  const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
@@ -46,6 +46,6 @@ const PinnedMessagesPanel = ({ open, onClose }) => {
46
46
  borderTopRightRadius: 16,
47
47
  overflow: "hidden",
48
48
  },
49
- }, getContainer: false, forceRender: true, children: _jsxs("div", { className: "flex h-full flex-col bg-white", children: [_jsxs("div", { className: "flex items-center gap-4 border-b border-gray-25 px-3 py-4", children: [_jsx("span", { className: "flex-1 text-lg font-bold text-gray-900", children: t("pinned_panel_title") }), _jsx(Button, { type: "text", shape: "default", className: "h-6 w-6 p-0 text-gray-900", onClick: onClose, "aria-label": t("pinned_panel_title"), children: _jsx(Icon, { icon: "close-b", size: 24 }) })] }), _jsxs("div", { className: "flex flex-1 flex-col gap-3 overflow-y-auto py-3", children: [_jsx("p", { className: "px-3 text-sm leading-[160%] text-gray-600", children: t("pinned_panel_hint") }), pinnedMessageList.map((message) => (_jsx(PinnedMessageItem, { message: message, contextMenuOpen: openContextMenuId === message.clientMsgID, onContextMenuOpenChange: (isOpen) => setOpenContextMenuId(isOpen ? message.clientMsgID : null), onUnpin: handleUnpin, onJump: handleJump }, message.clientMsgID)))] })] }) }));
49
+ }, getContainer: false, forceRender: true, children: _jsxs("div", { className: "flex h-full flex-col bg-white", children: [_jsxs("div", { className: "flex items-center gap-4 border-b border-gray-25 px-3 py-4", children: [_jsx("span", { className: "flex-1 text-lg font-bold text-gray-900", children: t("pinned_panel_title") }), _jsx(Button, { type: "text", shape: "default", className: "h-6 w-6 p-0 text-gray-900", onClick: onClose, "aria-label": t("pinned_panel_title"), children: _jsx(Icon, { icon: "close-b", size: 24 }) })] }), _jsxs("div", { className: "flex flex-1 flex-col gap-3 overflow-y-auto py-3", children: [_jsx("p", { className: "px-3 text-sm leading-[160%] text-gray-600", children: t("pinned_panel_hint") }), pinnedMessageList.map((message) => (_jsx(PinnedMessageItem, { message: message, contextMenuOpen: openContextMenuId === message.clientMsgID, onContextMenuOpenChange: (isOpen) => setOpenContextMenuId(isOpen ? message.clientMsgID : null), onUnpin: handleUnpin, onJump: handleJump, canUnpin: canUnpin }, message.clientMsgID)))] })] }) }));
50
50
  };
51
51
  export default PinnedMessagesPanel;
@@ -8,6 +8,8 @@ interface MessageListProps {
8
8
  onCopyMessageLink?: (conversationId: string, clientMsgID: string) => void;
9
9
  /** Called instead of the SDK's default toast when a jumped-to message turns out to be revoked. */
10
10
  onSearchMessageRevoked?: () => void;
11
+ /** Renders the pinned-message bar under the header (CRM desk only). */
12
+ showPinnedMessageBar?: boolean;
11
13
  }
12
14
  declare const MessageList: (props: MessageListProps) => import("react/jsx-runtime").JSX.Element;
13
15
  export default MessageList;
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAiCA,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;IAC9B,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACrC;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAmX3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAkCA,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;IAC9B,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAuX3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -26,12 +26,13 @@ import { isGroupConversation } from "../../utils/imCommon";
26
26
  import { ConnectStatus, SessionStatus } from "../../types/chat";
27
27
  import { PeerType } from "../../types/conversation";
28
28
  import PinLimitModal from "../../components/conversation-detail/PinLimitModal";
29
+ import PinnedMessageBar from "../../components/conversation-detail/PinnedMessageBar";
29
30
  import ConfirmModal from "../../components/common/ConfirmModal";
30
31
  dayjs.extend(isToday);
31
32
  const MessageList = (props) => {
32
33
  const { t } = useTranslation();
33
34
  const { user, connectStatus, allowPinMessageWithoutPermission } = useChatContext();
34
- const { onClose, conversationId, searchClientMsgID, openCreateCannedModal, onOpenThreadInfo, onCopyMessageLink, onSearchMessageRevoked, } = props;
35
+ const { onClose, conversationId, searchClientMsgID, openCreateCannedModal, onOpenThreadInfo, onCopyMessageLink, onSearchMessageRevoked, showPinnedMessageBar = false, } = props;
35
36
  const conversationData = useConversationStore((state) => state.conversationData);
36
37
  const permissions = useGroupPermission(conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID);
37
38
  const isGroupChat = isGroupConversation(conversationData !== null && conversationData !== void 0 ? conversationData : undefined);
@@ -192,7 +193,7 @@ const MessageList = (props) => {
192
193
  if (!conversationData) {
193
194
  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") })) }));
194
195
  }
195
- return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 overflow-hidden bg-white", "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, isGroupChat: isGroupChat, 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, timeRevealed: revealedTimeMsgId === message.clientMsgID, onToggleTimeReveal: handleToggleTimeReveal, onCopyMessageLink: handleCopyMessageLink }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), (Boolean(rawGroupId) && 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 })) : !isConfirmedGroup && shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", "data-cp-name": "JoinGroupRequired", 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") })] })) : isViewOnlyMember ? (
196
+ return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 overflow-hidden bg-white", "data-cp-name": "MessageList", children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined, onOpenThreadInfo: onOpenThreadInfo }), showPinnedMessageBar && (_jsx(PinnedMessageBar, { genericSubtitle: true, canUnpin: canPinMessage })), _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, isGroupChat: isGroupChat, 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, timeRevealed: revealedTimeMsgId === message.clientMsgID, onToggleTimeReveal: handleToggleTimeReveal, onCopyMessageLink: handleCopyMessageLink }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), (Boolean(rawGroupId) && 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 })) : !isConfirmedGroup && shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", "data-cp-name": "JoinGroupRequired", 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") })] })) : isViewOnlyMember ? (
196
197
  // Brief fallback while isJoined catches up after the kick event.
197
198
  _jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })) : !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
198
199
  ? "send_message_disabled_group_mute"
@@ -1 +1 @@
1
- {"version":3,"file":"usePinnedMessages.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/usePinnedMessages.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,GAAU,gBAAgB,MAAM,kBAoB/D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,MAAM;;;;CAqBvD,CAAC"}
1
+ {"version":3,"file":"usePinnedMessages.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/usePinnedMessages.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,GAAU,gBAAgB,MAAM,kBA2B/D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,gBAAgB,MAAM;;;;CAqBvD,CAAC"}
@@ -11,6 +11,12 @@ export const fetchPinnedMessages = async (conversationID) => {
11
11
  offset: 0,
12
12
  pageSize: PAGE_SIZE.small,
13
13
  });
14
+ // The store holds one thread's pins; a reply that lands after the user
15
+ // switched threads would paint the old thread's pins into the new one.
16
+ const { selectedConversationId, conversationData } = useConversationStore.getState();
17
+ const activeConversationId = selectedConversationId || (conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID);
18
+ if (activeConversationId !== conversationID)
19
+ return;
14
20
  const sortedMessageList = [...(data.messageList || [])].sort((first, second) => (second.pinnedTime || 0) - (first.pinnedTime || 0));
15
21
  setPinnedMessageData(sortedMessageList, data.totalCount || 0, (_a = data.remainingPinCount) !== null && _a !== void 0 ? _a : 0, (_b = data.isEnd) !== null && _b !== void 0 ? _b : true);
16
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,UAAU,qBAAqB;IAC7B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACrC;AAED,QAAA,MAAM,gBAAgB,GAAI,8FAKvB,qBAAqB,4CA0CvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/desk-message/index.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,UAAU,qBAAqB;IAC7B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACrC;AAED,QAAA,MAAM,gBAAgB,GAAI,8FAKvB,qBAAqB,4CA2CvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -14,6 +14,6 @@ const DChatDeskMessage = ({ openCreateCannedModal, groupThreadInfoConfig, onCopy
14
14
  const searchClientMsgID = useConversationStore((state) => state.searchClientMsgID);
15
15
  const [isThreadInfoOpen, { toggle: toggleThreadInfo, setFalse: closeThreadInfo },] = useBoolean(false);
16
16
  const { connectStatus } = useChatContext();
17
- return (_jsx(_Fragment, { children: connectStatus === ConnectStatus.Connected ? (_jsxs("div", { className: "flex flex-1 flex-row h-screen bg-[#f5f5f5]", children: [_jsx(DeskAssignedSession, {}), _jsx(DeskConversationList, {}), _jsx(MessageList, { conversationId: selectedConversationId, searchClientMsgID: searchClientMsgID, openCreateCannedModal: openCreateCannedModal, onOpenThreadInfo: toggleThreadInfo, onCopyMessageLink: onCopyMessageLink, onSearchMessageRevoked: onSearchMessageRevoked }), _jsx(ThreadInfo, { isOpen: isThreadInfoOpen, onClose: closeThreadInfo, groupConfig: groupThreadInfoConfig })] })) : (_jsx("div", { className: "flex flex-1 flex-row h-screen bg-[#f5f5f5]", children: connectStatus === ConnectStatus.Connecting && _jsx(Spin, { fullscreen: true }) })) }));
17
+ return (_jsx(_Fragment, { children: connectStatus === ConnectStatus.Connected ? (_jsxs("div", { className: "flex flex-1 flex-row h-screen bg-[#f5f5f5]", children: [_jsx(DeskAssignedSession, {}), _jsx(DeskConversationList, {}), _jsx(MessageList, { conversationId: selectedConversationId, searchClientMsgID: searchClientMsgID, openCreateCannedModal: openCreateCannedModal, onOpenThreadInfo: toggleThreadInfo, onCopyMessageLink: onCopyMessageLink, onSearchMessageRevoked: onSearchMessageRevoked, showPinnedMessageBar: true }), _jsx(ThreadInfo, { isOpen: isThreadInfoOpen, onClose: closeThreadInfo, groupConfig: groupThreadInfoConfig })] })) : (_jsx("div", { className: "flex flex-1 flex-row h-screen bg-[#f5f5f5]", children: connectStatus === ConnectStatus.Connecting && _jsx(Spin, { fullscreen: true }) })) }));
18
18
  };
19
19
  export default DChatDeskMessage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-sdk",
3
- "version": "0.6.40",
3
+ "version": "0.6.41",
4
4
  "description": "Droppii React Chat SDK",
5
5
  "repository": {
6
6
  "type": "git",