@droppii-org/chat-sdk 0.6.50 → 0.6.52

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 (64) hide show
  1. package/dist/components/message/item/index.d.ts.map +1 -1
  2. package/dist/components/message/item/index.js +3 -2
  3. package/dist/components/search-conversation/SearchAll.d.ts.map +1 -1
  4. package/dist/components/search-conversation/SearchAll.js +7 -9
  5. package/dist/components/search-conversation/SearchConversationAsGroups.d.ts.map +1 -1
  6. package/dist/components/search-conversation/SearchConversationAsGroups.js +3 -0
  7. package/dist/components/search-conversation/SearchConversationAsMessages.d.ts.map +1 -1
  8. package/dist/components/search-conversation/SearchConversationAsMessages.js +4 -1
  9. package/dist/components/search-conversation/SearchConversationAsUsers.d.ts.map +1 -1
  10. package/dist/components/search-conversation/SearchConversationAsUsers.js +4 -6
  11. package/dist/components/search-conversation/SearchScopeContext.d.ts +4 -0
  12. package/dist/components/search-conversation/SearchScopeContext.d.ts.map +1 -0
  13. package/dist/components/search-conversation/SearchScopeContext.js +5 -0
  14. package/dist/components/search-conversation/index.d.ts +5 -2
  15. package/dist/components/search-conversation/index.d.ts.map +1 -1
  16. package/dist/components/search-conversation/index.js +17 -12
  17. package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts.map +1 -1
  18. package/dist/components/search-conversation/item/SearchItemAsGroup.js +9 -0
  19. package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts +2 -0
  20. package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
  21. package/dist/components/search-conversation/item/SearchItemAsMessage.js +28 -6
  22. package/dist/components/search-conversation/item/SearchItemAsUser.d.ts +2 -1
  23. package/dist/components/search-conversation/item/SearchItemAsUser.d.ts.map +1 -1
  24. package/dist/components/search-conversation/item/SearchItemAsUser.js +9 -2
  25. package/dist/constants/index.d.ts +1 -0
  26. package/dist/constants/index.d.ts.map +1 -1
  27. package/dist/constants/index.js +2 -0
  28. package/dist/hooks/message/useMessageListScroll.d.ts.map +1 -1
  29. package/dist/hooks/message/useMessageListScroll.js +11 -5
  30. package/dist/hooks/message/useTypingStatus.d.ts.map +1 -1
  31. package/dist/hooks/message/useTypingStatus.js +1 -9
  32. package/dist/hooks/search/useOpenPdpSearchResult.d.ts +8 -0
  33. package/dist/hooks/search/useOpenPdpSearchResult.d.ts.map +1 -0
  34. package/dist/hooks/search/useOpenPdpSearchResult.js +31 -0
  35. package/dist/hooks/search/useSearchGroups.d.ts +3 -1
  36. package/dist/hooks/search/useSearchGroups.d.ts.map +1 -1
  37. package/dist/hooks/search/useSearchGroups.js +22 -11
  38. package/dist/hooks/search/useSearchMessage.d.ts +2 -0
  39. package/dist/hooks/search/useSearchMessage.d.ts.map +1 -1
  40. package/dist/hooks/search/useSearchMessage.js +10 -4
  41. package/dist/hooks/search/useSearchPdpTeamSessions.d.ts +17 -0
  42. package/dist/hooks/search/useSearchPdpTeamSessions.d.ts.map +1 -0
  43. package/dist/hooks/search/useSearchPdpTeamSessions.js +38 -0
  44. package/dist/hooks/search/useSearchUsers.d.ts +14 -0
  45. package/dist/hooks/search/useSearchUsers.d.ts.map +1 -0
  46. package/dist/hooks/search/useSearchUsers.js +23 -0
  47. package/dist/index.d.ts +3 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +3 -0
  50. package/dist/locales/vi/common.json +1 -0
  51. package/dist/services/query.d.ts +1 -0
  52. package/dist/services/query.d.ts.map +1 -1
  53. package/dist/services/query.js +1 -0
  54. package/dist/services/routes.d.ts +3 -0
  55. package/dist/services/routes.d.ts.map +1 -1
  56. package/dist/services/routes.js +3 -0
  57. package/dist/styles/global.css +1 -1
  58. package/dist/types/search.d.ts +2 -0
  59. package/dist/types/search.d.ts.map +1 -0
  60. package/dist/types/search.js +1 -0
  61. package/dist/utils/conversation.d.ts +2 -1
  62. package/dist/utils/conversation.d.ts.map +1 -1
  63. package/dist/utils/conversation.js +8 -1
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,8BAA8B,CAAC;AA2CtC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAkCD,QAAA,MAAM,WAAW,GAAI,kSAkBlB,gBAAgB,mDAmYlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,8BAA8B,CAAC;AA+CtC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAClD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAkCD,QAAA,MAAM,WAAW,GAAI,kSAkBlB,gBAAgB,mDAyYlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -7,7 +7,7 @@ import { MessageStatus, MessageType, } from "@droppii-org/wasm-client-sdk";
7
7
  import MessageBubble from "./MessageBubble";
8
8
  import { renderBubbleContent } from "./renderMessageContent";
9
9
  import { getImmediateNeighbor, getVisibleNeighbor, isMessageHiddenForViewer, } from "../../../hooks/message/useMessage";
10
- import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../../constants";
10
+ import { MSG_ITEM_BUBBLE_GROUP_PREFIX, MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX, } from "../../../constants";
11
11
  import { formatDividerTimestamp } from "../../../utils/common";
12
12
  import { CustomMessageType } from "../../../types/customMessage";
13
13
  import useAuthStore from "../../../store/auth";
@@ -228,7 +228,8 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
228
228
  const bubbleNode = (_jsx(MessageBubble, { isMine: isMine, isInternal: isInternalMessage, senderName: message === null || message === void 0 ? void 0 : message.senderNickname, showSenderName: showSenderName, showTip: showTip, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, content: renderBubbleContent(message, onPressQuoteMessage), isTransparent: isStickerMessage, timeLabel: dayjs.tz(message.sendTime).format("HH:mm"), timeRevealed: timeRevealed, onToggleTimeReveal: () => onToggleTimeReveal === null || onToggleTimeReveal === void 0 ? void 0 : onToggleTimeReveal(message.clientMsgID) }));
229
229
  const showPinnedBadge = Boolean(message === null || message === void 0 ? void 0 : message.isPinned);
230
230
  const pinnedBadgeNode = showPinnedBadge ? (_jsx("span", { "data-testid": "message-pinned-badge", className: clsx("absolute -top-2.5 z-[1] flex h-[22px] w-[26px] items-center justify-center rounded-full border border-white bg-gray-25", isMine ? "left-0" : "right-0"), children: _jsx(Icon, { icon: "thumbtack-b", size: 12, className: "text-[var(--dc-color-primary)]" }) })) : null;
231
- const wrappedBubble = hasContextMenu ? (_jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsxs("div", { ref: bubbleWrapperRef, className: "relative min-w-0 max-w-full", children: [bubbleNode, pinnedBadgeNode] }) })) : (_jsxs("div", { className: "relative min-w-0 max-w-full", children: [bubbleNode, pinnedBadgeNode] }));
231
+ const bubbleGroupId = `${MSG_ITEM_BUBBLE_GROUP_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`;
232
+ const wrappedBubble = hasContextMenu ? (_jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsxs("div", { ref: bubbleWrapperRef, id: bubbleGroupId, className: "relative min-w-0 max-w-full", children: [bubbleNode, pinnedBadgeNode] }) })) : (_jsxs("div", { id: bubbleGroupId, className: "relative min-w-0 max-w-full", children: [bubbleNode, pinnedBadgeNode] }));
232
233
  return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID, "data-cp-name": "MessageItem" }),
233
234
  unreadDividerNode,
234
235
  timeBreakNode,
@@ -1 +1 @@
1
- {"version":3,"file":"SearchAll.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchAll.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAG,CAAC;AAG7C,UAAU,0BAA0B;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,GAAG,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACvD;AACD,QAAA,MAAM,qBAAqB,GAAI,+BAG5B,0BAA0B,4CA2J5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"SearchAll.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchAll.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAG,CAAC;AAI7C,UAAU,0BAA0B;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,GAAG,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACvD;AACD,QAAA,MAAM,qBAAqB,GAAI,+BAG5B,0BAA0B,4CAyJ5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -6,30 +6,28 @@ import { useSearchMessage } from "../../hooks/search/useSearchMessage";
6
6
  import { MessageType } from "@droppii-org/wasm-client-sdk";
7
7
  import { Icon } from "../../components/icon";
8
8
  import SearchItemAsMessage from "./item/SearchItemAsMessage";
9
- import { useGetSession } from "../../hooks/session/useGetSession";
10
9
  import SearchItemAsUser from "./item/SearchItemAsUser";
11
10
  import SearchItemAsGroup from "./item/SearchItemAsGroup";
12
11
  import { useSearchGroups } from "../../hooks/search/useSearchGroups";
12
+ import { useSearchUsers } from "../../hooks/search/useSearchUsers";
13
13
  import { SearchConversationTabKey } from ".";
14
+ import { useSearchScope } from "./SearchScopeContext";
14
15
  import { PAGE_SIZE } from "../../constants";
15
16
  const SearchConversationAll = ({ searchTerm = "", setActiveKey, }) => {
16
17
  const { t } = useTranslation();
18
+ const scope = useSearchScope();
17
19
  const { dataFlatten: messages, isLoading: isLoadingMessage, hasNextPage: hasNextPageMessage, } = useSearchMessage({
18
20
  payload: {
19
21
  searchTerm: searchTerm.trim(),
20
22
  contentType: MessageType.TextMessage,
21
23
  },
22
- options: { pageSize: PAGE_SIZE.xs },
23
- });
24
- const { dataFlatten: sessions, isLoading: isLoadingSession, hasNextPage: hasNextPageSession, } = useGetSession({
25
- filter: {
26
- searchTerm: searchTerm.trim(),
27
- },
28
- options: { pageSize: PAGE_SIZE.xs },
24
+ options: { pageSize: PAGE_SIZE.xs, scope },
29
25
  });
26
+ const { dataFlatten: sessions, isLoading: isLoadingSession, hasNextPage: hasNextPageSession, } = useSearchUsers({ searchTerm, scope, pageSize: PAGE_SIZE.xs });
30
27
  const { groups, isLoading: isLoadingGroup, hasNextPage: hasNextPageGroup, } = useSearchGroups({
31
28
  searchTerm: searchTerm.trim(),
32
29
  pageSize: PAGE_SIZE.xs,
30
+ scope,
33
31
  });
34
32
  if (searchTerm.trim() === "" ||
35
33
  (messages.length === 0 && sessions.length === 0 && groups.length === 0)) {
@@ -38,6 +36,6 @@ const SearchConversationAll = ({ searchTerm = "", setActiveKey, }) => {
38
36
  if (isLoadingMessage || isLoadingSession || isLoadingGroup) {
39
37
  return (_jsx("div", { className: "h-full overflow-auto flex items-center justify-center", children: _jsx(Spin, {}) }));
40
38
  }
41
- return (_jsxs("div", { className: "h-full overflow-auto", "data-cp-name": "SearchConversationAll", children: [sessions.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("users") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageSession && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Users), children: t("see_more") })] }), _jsx("div", { children: sessions.map((session) => (_jsx(SearchItemAsUser, { session: session, searchTerm: searchTerm }, session.conversationId))) })] })), messages.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("messages") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageMessage && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Messages), children: t("see_more") })] }), _jsx("div", { children: messages.map((message) => (_jsx(SearchItemAsMessage, { message: message.chatLog, searchTerm: searchTerm, displayTag: message.displayTag }, message.chatLog.clientMsgID))) })] })), groups.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("groups") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageGroup && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Groups), children: t("see_more") })] }), _jsx("div", { children: groups.map((group) => (_jsx(SearchItemAsGroup, { group: group, searchTerm: searchTerm }, group.conversationId))) })] }))] }));
39
+ return (_jsxs("div", { className: "h-full overflow-auto", "data-cp-name": "SearchConversationAll", children: [sessions.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("users") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageSession && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Users), children: t("see_more") })] }), _jsx("div", { children: sessions.map((session) => (_jsx(SearchItemAsUser, { session: session, searchTerm: searchTerm }, session.conversationId))) })] })), messages.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("messages") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageMessage && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Messages), children: t("see_more") })] }), _jsx("div", { children: messages.map((message) => (_jsx(SearchItemAsMessage, { message: message.chatLog, searchTerm: searchTerm, displayTag: message.displayTag, tag: message.tag }, message.chatLog.clientMsgID))) })] })), groups.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between px-3 min-h-[32px]", children: [_jsx("span", { className: "text-xs font-medium uppercase flex-1 text-gray-600", children: t("groups") }), _jsx(Button, { type: "link", icon: _jsx(Icon, { icon: "angle-right-o", size: 18, className: "!align-[-4px]" }), iconPosition: "end", className: clsx("p-0 gap-1", !hasNextPageGroup && "invisible"), onClick: () => setActiveKey === null || setActiveKey === void 0 ? void 0 : setActiveKey(SearchConversationTabKey.Groups), children: t("see_more") })] }), _jsx("div", { children: groups.map((group) => (_jsx(SearchItemAsGroup, { group: group, searchTerm: searchTerm }, group.conversationId))) })] }))] }));
42
40
  };
43
41
  export default SearchConversationAll;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchConversationAsGroups.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsGroups.tsx"],"names":[],"mappings":"AAQA,UAAU,+BAA+B;IACvC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,0BAA0B,GAAI,OAAO,+BAA+B,4CA0CzE,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
1
+ {"version":3,"file":"SearchConversationAsGroups.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsGroups.tsx"],"names":[],"mappings":"AASA,UAAU,+BAA+B;IACvC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,0BAA0B,GAAI,OAAO,+BAA+B,4CA4CzE,CAAC;AAEF,eAAe,0BAA0B,CAAC"}
@@ -5,11 +5,14 @@ import { useTranslation } from "react-i18next";
5
5
  import InfiniteScroll from "react-infinite-scroll-component";
6
6
  import SearchItemAsGroup from "./item/SearchItemAsGroup";
7
7
  import { useSearchGroups } from "../../hooks/search/useSearchGroups";
8
+ import { useSearchScope } from "./SearchScopeContext";
8
9
  const SearchConversationAsGroups = (props) => {
9
10
  const { searchTerm = "" } = props;
10
11
  const { t } = useTranslation();
12
+ const scope = useSearchScope();
11
13
  const { groups, hasNextPage, fetchNextPage, isLoading } = useSearchGroups({
12
14
  searchTerm,
15
+ scope,
13
16
  });
14
17
  if ((groups.length === 0 && !isLoading) || searchTerm.trim() === "")
15
18
  return _jsx(Empty, { description: t("no_conversation") });
@@ -1 +1 @@
1
- {"version":3,"file":"SearchConversationAsMessages.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsMessages.tsx"],"names":[],"mappings":"AAOA,UAAU,iCAAiC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,4BAA4B,GAChC,OAAO,iCAAiC,4CAgDzC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
1
+ {"version":3,"file":"SearchConversationAsMessages.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsMessages.tsx"],"names":[],"mappings":"AAQA,UAAU,iCAAiC;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,4BAA4B,GAChC,OAAO,iCAAiC,4CAmDzC,CAAC;AAEF,eAAe,4BAA4B,CAAC"}
@@ -5,19 +5,22 @@ import { useSearchMessage } from "../../hooks/search/useSearchMessage";
5
5
  import { MessageType } from "@droppii-org/wasm-client-sdk";
6
6
  import InfiniteScroll from "react-infinite-scroll-component";
7
7
  import SearchItemAsMessage from "./item/SearchItemAsMessage";
8
+ import { useSearchScope } from "./SearchScopeContext";
8
9
  const SearchConversationAsMessages = (props) => {
9
10
  const { searchTerm = "" } = props;
10
11
  const { t } = useTranslation();
12
+ const scope = useSearchScope();
11
13
  const { dataFlatten, hasNextPage, fetchNextPage, isLoading } = useSearchMessage({
12
14
  payload: {
13
15
  searchTerm: searchTerm.trim(),
14
16
  contentType: MessageType.TextMessage,
15
17
  },
18
+ options: { scope },
16
19
  });
17
20
  if ((dataFlatten.length === 0 && !isLoading) || searchTerm.trim() === "")
18
21
  return _jsx(Empty, { description: t("no_conversation") });
19
22
  if (isLoading)
20
23
  return (_jsx("div", { className: "flex items-center justify-center", children: _jsx(Spin, {}) }));
21
- return (_jsx("div", { id: "scrollableSearchMessagesTab", className: "h-full overflow-auto", "data-cp-name": "SearchConversationAsMessages", children: _jsx(InfiniteScroll, { dataLength: dataFlatten.length, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableSearchMessagesTab", children: dataFlatten.map((item) => (_jsx(SearchItemAsMessage, { message: item.chatLog, searchTerm: searchTerm, displayTag: item.displayTag }, item.chatLog.clientMsgID))) }) }));
24
+ return (_jsx("div", { id: "scrollableSearchMessagesTab", className: "h-full overflow-auto", "data-cp-name": "SearchConversationAsMessages", children: _jsx(InfiniteScroll, { dataLength: dataFlatten.length, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableSearchMessagesTab", children: dataFlatten.map((item) => (_jsx(SearchItemAsMessage, { message: item.chatLog, searchTerm: searchTerm, displayTag: item.displayTag, tag: item.tag }, item.chatLog.clientMsgID))) }) }));
22
25
  };
23
26
  export default SearchConversationAsMessages;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchConversationAsUsers.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsUsers.tsx"],"names":[],"mappings":"AAMA,UAAU,8BAA8B;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,yBAAyB,GAAI,OAAO,8BAA8B,4CA4CvE,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
1
+ {"version":3,"file":"SearchConversationAsUsers.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchConversationAsUsers.tsx"],"names":[],"mappings":"AAOA,UAAU,8BAA8B;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,yBAAyB,GAAI,OAAO,8BAA8B,4CA0CvE,CAAC;AAEF,eAAe,yBAAyB,CAAC"}
@@ -3,15 +3,13 @@ import { Empty, Spin } from "antd";
3
3
  import { useTranslation } from "react-i18next";
4
4
  import InfiniteScroll from "react-infinite-scroll-component";
5
5
  import SearchItemAsUser from "./item/SearchItemAsUser";
6
- import { useGetSession } from "../../hooks/session/useGetSession";
6
+ import { useSearchUsers } from "../../hooks/search/useSearchUsers";
7
+ import { useSearchScope } from "./SearchScopeContext";
7
8
  const SearchConversationAsUsers = (props) => {
8
9
  const { searchTerm = "" } = props;
9
10
  const { t } = useTranslation();
10
- const { dataFlatten, hasNextPage, fetchNextPage, isLoading } = useGetSession({
11
- filter: {
12
- searchTerm: searchTerm.trim(),
13
- },
14
- });
11
+ const scope = useSearchScope();
12
+ const { dataFlatten, hasNextPage, fetchNextPage, isLoading } = useSearchUsers({ searchTerm, scope });
15
13
  if ((dataFlatten.length === 0 && !isLoading) || searchTerm.trim() === "")
16
14
  return _jsx(Empty, { description: t("no_conversation") });
17
15
  if (isLoading)
@@ -0,0 +1,4 @@
1
+ import type { SearchScope } from "../../types/search";
2
+ export declare const SearchScopeProvider: import("react").Provider<SearchScope>;
3
+ export declare const useSearchScope: () => SearchScope;
4
+ //# sourceMappingURL=SearchScopeContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchScopeContext.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/SearchScopeContext.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,eAAO,MAAM,mBAAmB,uCAA8B,CAAC;AAE/D,eAAO,MAAM,cAAc,mBAAuC,CAAC"}
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ import { createContext, useContext } from "react";
3
+ const SearchScopeContext = createContext("crm");
4
+ export const SearchScopeProvider = SearchScopeContext.Provider;
5
+ export const useSearchScope = () => useContext(SearchScopeContext);
@@ -1,3 +1,4 @@
1
+ import type { SearchScope } from "../../types/search";
1
2
  export declare enum SearchConversationTabKey {
2
3
  All = "all",
3
4
  MyInbox = "myInbox",
@@ -5,9 +6,11 @@ export declare enum SearchConversationTabKey {
5
6
  Messages = "messages",
6
7
  Groups = "groups"
7
8
  }
8
- interface SearchConversationProps {
9
+ export interface SearchConversationProps {
9
10
  searchTerm: string;
11
+ /** Data sources + result navigation. Defaults to the CRM desk behavior. */
12
+ scope?: SearchScope;
10
13
  }
11
- declare const SearchConversation: ({ searchTerm }: SearchConversationProps) => import("react/jsx-runtime").JSX.Element;
14
+ declare const SearchConversation: ({ searchTerm, scope, }: SearchConversationProps) => import("react/jsx-runtime").JSX.Element;
12
15
  export default SearchConversation;
13
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/index.tsx"],"names":[],"mappings":"AAWA,oBAAY,wBAAwB;IAClC,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,UAAU,uBAAuB;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,QAAA,MAAM,kBAAkB,GAAI,gBAAgB,uBAAuB,4CA4ElE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-conversation/index.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,oBAAY,wBAAwB;IAClC,GAAG,QAAQ;IACX,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AACD,QAAA,MAAM,kBAAkB,GAAI,wBAGzB,uBAAuB,4CAkFzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -8,6 +8,7 @@ import SearchConversationMyInbox from "./SearchConversationMyInbox";
8
8
  import SearchConversationAsUsers from "./SearchConversationAsUsers";
9
9
  import SearchConversationAsMessages from "./SearchConversationAsMessages";
10
10
  import SearchConversationAsGroups from "./SearchConversationAsGroups";
11
+ import { SearchScopeProvider } from "./SearchScopeContext";
11
12
  export var SearchConversationTabKey;
12
13
  (function (SearchConversationTabKey) {
13
14
  SearchConversationTabKey["All"] = "all";
@@ -16,11 +17,11 @@ export var SearchConversationTabKey;
16
17
  SearchConversationTabKey["Messages"] = "messages";
17
18
  SearchConversationTabKey["Groups"] = "groups";
18
19
  })(SearchConversationTabKey || (SearchConversationTabKey = {}));
19
- const SearchConversation = ({ searchTerm }) => {
20
+ const SearchConversation = ({ searchTerm, scope = "crm", }) => {
20
21
  const { t } = useTranslation();
21
22
  const [activeKey, setActiveKey] = useState(SearchConversationTabKey.All);
22
23
  const items = useMemo(() => {
23
- return [
24
+ const allItems = [
24
25
  {
25
26
  key: SearchConversationTabKey.All,
26
27
  label: t("all"),
@@ -47,7 +48,11 @@ const SearchConversation = ({ searchTerm }) => {
47
48
  children: _jsx(SearchConversationAsGroups, { searchTerm: searchTerm }),
48
49
  },
49
50
  ];
50
- }, [t, searchTerm]);
51
+ // PDP spec: the source inbox is never a search category.
52
+ return scope === "pdp-portal"
53
+ ? allItems.filter((item) => item.key !== SearchConversationTabKey.MyInbox)
54
+ : allItems;
55
+ }, [t, searchTerm, scope]);
51
56
  // Clicking a result row while on "All" switches activeKey without any
52
57
  // click/focus on the tab header itself — antd's own scroll-into-view for
53
58
  // that path relies on measuring .ant-tabs-nav against its scroll parent,
@@ -58,14 +63,14 @@ const SearchConversation = ({ searchTerm }) => {
58
63
  (_a = document
59
64
  .querySelector('[data-cp-name="SearchConversation"] .ant-tabs-tab-active')) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ inline: "nearest", block: "nearest" });
60
65
  }, [activeKey]);
61
- return (_jsx("div", { className: "h-full", "data-cp-name": "SearchConversation", children: _jsx(Tabs, { defaultActiveKey: SearchConversationTabKey.All, items: items, className: "h-full", activeKey: activeKey, onChange: (key) => setActiveKey(key), destroyOnHidden: true,
62
- // Ant's built-in tab-overflow ("...") dropdown never recovers from
63
- // its initial off-screen measurement inside this Drawer (rendered
64
- // with getContainer={false} for unrelated scroll-position reasons —
65
- // see DeskConversationList) — the last tab (Nhóm) becomes
66
- // permanently unreachable. A plain horizontally-scrollable strip
67
- // sidesteps that positioning bug entirely: every tab stays a real,
68
- // always-clickable element: no hidden dropdown involved.
69
- renderTabBar: (tabBarProps, DefaultTabBar) => (_jsx("div", { className: "overflow-x-auto", children: _jsx(DefaultTabBar, Object.assign({}, tabBarProps, { className: "!w-max" })) })) }) }));
66
+ return (_jsx(SearchScopeProvider, { value: scope, children: _jsx("div", { className: "h-full", "data-cp-name": "SearchConversation", children: _jsx(Tabs, { defaultActiveKey: SearchConversationTabKey.All, items: items, className: "h-full", activeKey: activeKey, onChange: (key) => setActiveKey(key), destroyOnHidden: true,
67
+ // Ant's built-in tab-overflow ("...") dropdown never recovers from
68
+ // its initial off-screen measurement inside this Drawer (rendered
69
+ // with getContainer={false} for unrelated scroll-position reasons —
70
+ // see DeskConversationList) — the last tab (Nhóm) becomes
71
+ // permanently unreachable. A plain horizontally-scrollable strip
72
+ // sidesteps that positioning bug entirely: every tab stays a real,
73
+ // always-clickable element: no hidden dropdown involved.
74
+ renderTabBar: (tabBarProps, DefaultTabBar) => (_jsx("div", { className: "overflow-x-auto", children: _jsx(DefaultTabBar, Object.assign({}, tabBarProps, { className: "!w-max" })) })) }) }) }));
70
75
  };
71
76
  export default SearchConversation;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchItemAsGroup.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsGroup.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAOxF,UAAU,sBAAsB;IAC9B,KAAK,EAAE,4BAA4B,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,iBAAiB,GAAI,OAAO,sBAAsB,4CAiEvD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"SearchItemAsGroup.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsGroup.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AASxF,UAAU,sBAAsB;IAC9B,KAAK,EAAE,4BAA4B,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,iBAAiB,GAAI,OAAO,sBAAsB,4CAwEvD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -7,15 +7,24 @@ import { useChatNavigate } from "../../../hooks/conversation/useChatNavigate";
7
7
  import { highlightSearch, sanitizeHtml } from "../../../utils/common";
8
8
  import { Icon } from "../../../components/icon";
9
9
  import GroupCompositeAvatar from "../../../components/group/GroupCompositeAvatar";
10
+ import { useOpenPdpSearchResult } from "../../../hooks/search/useOpenPdpSearchResult";
11
+ import { useSearchScope } from "../SearchScopeContext";
10
12
  const SearchItemAsGroup = (props) => {
11
13
  const { group, searchTerm = "" } = props;
12
14
  const { t } = useTranslation();
13
15
  const onNavigate = useChatNavigate();
16
+ const scope = useSearchScope();
17
+ const openPdpResult = useOpenPdpSearchResult();
14
18
  const setConversationData = useConversationStore((state) => state.setConversationData);
15
19
  const setSelectedConversationId = useConversationStore((state) => state.setSelectedConversationId);
16
20
  const { conversation } = group;
17
21
  const isPublic = group.visibility === GroupVisibility.Public;
18
22
  const onPressItem = () => {
23
+ // PDP's inbox opens real groups by ?groupId, same as its group list.
24
+ if (scope === "pdp-portal") {
25
+ openPdpResult({ groupId: group.groupId });
26
+ return;
27
+ }
19
28
  // Result can go stale before the click — force a fresh membership check.
20
29
  setConversationData(conversation, undefined, { forceRevalidate: true });
21
30
  setSelectedConversationId(conversation.conversationID);
@@ -5,6 +5,8 @@ interface SearchItemAsMessageProps {
5
5
  };
6
6
  searchTerm: string;
7
7
  displayTag?: string;
8
+ /** BE source tag (MY_INBOX | CS_TEAM); only PDP Portal renders from it. */
9
+ tag?: string;
8
10
  onClick?: () => void;
9
11
  }
10
12
  declare const SearchItemAsMessage: (props: SearchItemAsMessageProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchItemAsMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsMessage.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA4B,MAAM,8BAA8B,CAAC;AAerF,UAAU,wBAAwB;IAChC,OAAO,EAAE,WAAW,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,mBAAmB,GAAI,OAAO,wBAAwB,4CA2G3D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"SearchItemAsMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsMessage.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA4B,MAAM,8BAA8B,CAAC;AAwBrF,UAAU,wBAAwB;IAChC,OAAO,EAAE,WAAW,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,mBAAmB,GAAI,OAAO,wBAAwB,4CAyH3D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -10,19 +10,41 @@ import { useTranslation } from "react-i18next";
10
10
  import useConversationStore from "../../../store/conversation";
11
11
  import { useMemo } from "react";
12
12
  import useAuthStore from "../../../store/auth";
13
+ import { getConversationIdFromMessage } from "../../../utils/conversation";
14
+ import { useOpenPdpSearchResult } from "../../../hooks/search/useOpenPdpSearchResult";
15
+ import { useSearchScope } from "../SearchScopeContext";
16
+ // PDP labels the source by its inbox tab; BE's displayTag carries the CS team name.
17
+ const PDP_TAG_LABEL_KEYS = {
18
+ MY_INBOX: "my_messages",
19
+ CS_TEAM: "pdp_team_inbox_tag",
20
+ };
13
21
  const SearchItemAsMessage = (props) => {
14
- var _a;
22
+ var _a, _b;
15
23
  const { t } = useTranslation();
16
- const { message, searchTerm = "", displayTag, onClick } = props;
24
+ const { message, searchTerm = "", displayTag, tag, onClick } = props;
17
25
  const { user } = useChatContext();
18
26
  const isCrm = useAuthStore((state) => state.isCrm);
27
+ const scope = useSearchScope();
28
+ const isPdpPortal = scope === "pdp-portal";
29
+ const openPdpResult = useOpenPdpSearchResult();
19
30
  const conversationData = useConversationStore((state) => state.conversationData);
20
31
  const useConversationDisplay = useMemo(() => {
21
- if (isCrm)
32
+ // PDP results span many threads, so show the sender like CRM does.
33
+ if (isCrm || isPdpPortal)
22
34
  return true;
23
35
  return (user === null || user === void 0 ? void 0 : user.userID) === (message === null || message === void 0 ? void 0 : message.sendID);
24
- }, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, message === null || message === void 0 ? void 0 : message.sendID, isCrm]);
36
+ }, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, message === null || message === void 0 ? void 0 : message.sendID, isCrm, isPdpPortal]);
37
+ const tagLabel = isPdpPortal
38
+ ? tag && PDP_TAG_LABEL_KEYS[tag] && t(PDP_TAG_LABEL_KEYS[tag])
39
+ : displayTag;
25
40
  const onPressItem = async () => {
41
+ if (isPdpPortal) {
42
+ openPdpResult({
43
+ threadId: getConversationIdFromMessage(message),
44
+ messageId: message.clientMsgID,
45
+ });
46
+ return;
47
+ }
26
48
  const { data } = await DChatSDK.getOneConversation({
27
49
  sourceID: message.sessionType === SessionType.Group
28
50
  ? message.groupID
@@ -63,13 +85,13 @@ const SearchItemAsMessage = (props) => {
63
85
  : conversationData === null || conversationData === void 0 ? void 0 : conversationData.faceURL, alt: useConversationDisplay
64
86
  ? message.senderNickname
65
87
  : conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName, children: useConversationDisplay
66
- ? message.senderNickname.charAt(0).toUpperCase()
88
+ ? (_b = message.senderNickname) === null || _b === void 0 ? void 0 : _b.charAt(0).toUpperCase()
67
89
  : conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName.charAt(0).toUpperCase() }) }), _jsxs("div", { className: "flex flex-col flex-1 min-w-0 gap-1", children: [_jsxs("div", { className: "flex flex-1 items-center justify-between", children: [_jsx("span", { className: "text-sm flex-1 font-semibold truncate", children: useConversationDisplay
68
90
  ? message.senderNickname
69
91
  : conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName }), _jsx("span", { className: "text-xs text-gray-500", children: formatTimestamp(message.sendTime, {
70
92
  hasTime: true,
71
93
  }) })] }), _jsxs("div", { className: "flex flex-col flex-1 min-w-0 gap-1", children: [_jsx("span", { className: "text-xs flex-1 text-gray-500 truncate", dangerouslySetInnerHTML: {
72
94
  __html: sanitizeHtml(highlightSearch(msgContent, searchTerm)),
73
- } }), displayTag && (_jsx("span", { className: "text-[10px] text-[var(--dc-color-primary)] bg-[var(--dc-color-primary-light)] px-1.5 py-0.5 rounded w-fit truncate", children: displayTag }))] })] })] }, message.clientMsgID));
95
+ } }), tagLabel && (_jsx("span", { className: "text-[10px] text-[var(--dc-color-primary)] bg-[var(--dc-color-primary-light)] px-1.5 py-0.5 rounded w-fit truncate", children: tagLabel }))] })] })] }, message.clientMsgID));
74
96
  };
75
97
  export default SearchItemAsMessage;
@@ -1,6 +1,7 @@
1
1
  import { ISessionByStatus } from "../../../store/type";
2
+ import type { PdpTeamSessionItem } from "../../../hooks/search/useSearchPdpTeamSessions";
2
3
  interface SearchItemAsUserProps {
3
- session: ISessionByStatus;
4
+ session: PdpTeamSessionItem & Partial<Pick<ISessionByStatus, "conversation">>;
4
5
  searchTerm: string;
5
6
  }
6
7
  declare const SearchItemAsUser: (props: SearchItemAsUserProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchItemAsUser.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsUser.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKhD,UAAU,qBAAqB;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CA0CrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"SearchItemAsUser.d.ts","sourceRoot":"","sources":["../../../../src/components/search-conversation/item/SearchItemAsUser.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIhD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAIlF,UAAU,qBAAqB;IAE7B,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC,CAAC;IAC9E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CA+CrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -4,12 +4,19 @@ import { Avatar, message } from "antd";
4
4
  import { highlightSearch, sanitizeHtml } from "../../../utils/common";
5
5
  import useConversationStore from "../../../store/conversation";
6
6
  import { useTranslation } from "react-i18next";
7
+ import { useOpenPdpSearchResult } from "../../../hooks/search/useOpenPdpSearchResult";
8
+ import { useSearchScope } from "../SearchScopeContext";
7
9
  const SearchItemAsUser = (props) => {
8
- var _a, _b, _c, _d, _e, _f;
10
+ var _a, _b, _c, _d, _e, _f, _g;
9
11
  const { session, searchTerm = "" } = props;
10
12
  const { t } = useTranslation();
13
+ const scope = useSearchScope();
14
+ const openPdpResult = useOpenPdpSearchResult();
11
15
  const ownerName = `${(_a = session.owner) === null || _a === void 0 ? void 0 : _a.fullName}${((_b = session.owner) === null || _b === void 0 ? void 0 : _b.username) ? ` (${(_c = session.owner) === null || _c === void 0 ? void 0 : _c.username})` : ""}`;
12
16
  const onPressItem = async () => {
17
+ if (scope === "pdp-portal") {
18
+ return openPdpResult({ threadId: session.conversationId });
19
+ }
13
20
  if (!(session === null || session === void 0 ? void 0 : session.conversation)) {
14
21
  return message.error(t("err_get_conversation"));
15
22
  }
@@ -18,7 +25,7 @@ const SearchItemAsUser = (props) => {
18
25
  .getState()
19
26
  .setSelectedConversationId(session.conversationId);
20
27
  };
21
- return (_jsxs("div", { className: "py-3 px-2 flex items-center gap-3 hover:bg-gray-100 hover:rounded-sm cursor-pointer border-b mx-1", onClick: onPressItem, "data-cp-name": "SearchItemAsUser", children: [_jsx(Avatar, { size: "large", src: (_d = session.owner) === null || _d === void 0 ? void 0 : _d.avatar, alt: (_e = session.owner) === null || _e === void 0 ? void 0 : _e.username, children: (_f = session.owner) === null || _f === void 0 ? void 0 : _f.fullName.charAt(0).toUpperCase() }), _jsx("div", { className: "flex flex-col flex-1 min-w-0", children: _jsx("p", { className: "text-sm font-semibold truncate", dangerouslySetInnerHTML: {
28
+ return (_jsxs("div", { className: "py-3 px-2 flex items-center gap-3 hover:bg-gray-100 hover:rounded-sm cursor-pointer border-b mx-1", onClick: onPressItem, "data-cp-name": "SearchItemAsUser", children: [_jsx(Avatar, { size: "large", src: (_d = session.owner) === null || _d === void 0 ? void 0 : _d.avatar, alt: (_e = session.owner) === null || _e === void 0 ? void 0 : _e.username, children: (_g = (_f = session.owner) === null || _f === void 0 ? void 0 : _f.fullName) === null || _g === void 0 ? void 0 : _g.charAt(0).toUpperCase() }), _jsx("div", { className: "flex flex-col flex-1 min-w-0", children: _jsx("p", { className: "text-sm font-semibold truncate", dangerouslySetInnerHTML: {
22
29
  __html: sanitizeHtml(highlightSearch(ownerName, searchTerm)),
23
30
  } }) })] }, session.id));
24
31
  };
@@ -7,5 +7,6 @@ export declare const PAGE_SIZE: {
7
7
  };
8
8
  export declare const MSG_ITEM_PREFIX = "msg-item-";
9
9
  export declare const MSG_ITEM_CONTENT_PREFIX = "msg-item-content-";
10
+ export declare const MSG_ITEM_BUBBLE_GROUP_PREFIX = "msg-item-bubble-group-";
10
11
  export declare const ANTD_PRIMARY_COLOR_VAR = "var(--dc-color-primary)";
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,qFAC2D,CAAC;AAErF,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC;AAEX,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAM3D,eAAO,MAAM,sBAAsB,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,qFAC2D,CAAC;AAErF,eAAO,MAAM,SAAS;;;;;CAKZ,CAAC;AAEX,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAE3D,eAAO,MAAM,4BAA4B,2BAA2B,CAAC;AAMrE,eAAO,MAAM,sBAAsB,4BAA4B,CAAC"}
@@ -7,6 +7,8 @@ export const PAGE_SIZE = {
7
7
  };
8
8
  export const MSG_ITEM_PREFIX = "msg-item-";
9
9
  export const MSG_ITEM_CONTENT_PREFIX = "msg-item-content-";
10
+ // Bubble plus its pin badge, so the jump-to-message pulse moves both together.
11
+ export const MSG_ITEM_BUBBLE_GROUP_PREFIX = "msg-item-bubble-group-";
10
12
  // antd components read colorPrimary from antd's own theme token, not from
11
13
  // the --dc-color-primary CSS var this SDK themes everything else with.
12
14
  // Wrap any antd component that needs brand color in
@@ -1 +1 @@
1
- {"version":3,"file":"useMessageListScroll.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessageListScroll.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAkC,MAAM,OAAO,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAM3D,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,WAAW,EAAE,CAAC;CAC5B;AAED,UAAU,0BAA0B;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;IAChC,eAAe,EAAE,SAAS,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACxD,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,kBAAkB,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,oBAAoB,GAAI,iKAWlC,0BAA0B;;;;8BAqErB,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC;;;mCA0Ce,MAAM;CA6CzD,CAAC"}
1
+ {"version":3,"file":"useMessageListScroll.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessageListScroll.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAkC,MAAM,OAAO,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAU3D,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,WAAW,EAAE,CAAC;CAC5B;AAED,UAAU,0BAA0B;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,oBAAoB,CAAC;IAChC,eAAe,EAAE,SAAS,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACxD,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,kBAAkB,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,oBAAoB,GAAI,iKAWlC,0BAA0B;;;;8BAqErB,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC;;;mCA0Ce,MAAM;CA6CzD,CAAC"}
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useRef } from "react";
3
3
  import { useDebounceFn } from "ahooks";
4
4
  import { isNumber } from "lodash";
5
5
  import { markConversationMessageAsRead } from "../../hooks/conversation/useConversation";
6
- import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../constants";
6
+ import { MSG_ITEM_BUBBLE_GROUP_PREFIX, MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX, } from "../../constants";
7
7
  export const MESSAGE_LIST_BOTTOM_THRESHOLD = -5;
8
8
  export const useMessageListScroll = ({ conversationId, userId, isGroupChat, loadState, latestLoadState, moreOldLoading, moreNewLoading, getMoreOldMessages, getMoreNewMessages, markAsReadBlocked = false, }) => {
9
9
  const scrollRef = useRef(null);
@@ -104,13 +104,19 @@ export const useMessageListScroll = ({ conversationId, userId, isGroupChat, load
104
104
  block: "center",
105
105
  });
106
106
  setTimeout(() => {
107
+ var _a;
107
108
  const targetContentElement = document.getElementById(`${MSG_ITEM_CONTENT_PREFIX}${clientMsgID}`);
108
- targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.classList.add("zoom-in-out-element", "border-blue-500", "border");
109
+ // The border hugs the bubble; the pulse runs on the wrapper that also
110
+ // holds the pin badge, or the badge stays put while the bubble scales.
111
+ const pulseElement = (_a = document.getElementById(`${MSG_ITEM_BUBBLE_GROUP_PREFIX}${clientMsgID}`)) !== null && _a !== void 0 ? _a : targetContentElement;
112
+ targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.classList.add("border-blue-500", "border");
113
+ pulseElement === null || pulseElement === void 0 ? void 0 : pulseElement.classList.add("zoom-in-out-element");
109
114
  const onEnd = () => {
110
- targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.classList.remove("zoom-in-out-element", "border-blue-500", "border");
111
- targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.removeEventListener("animationend", onEnd);
115
+ targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.classList.remove("border-blue-500", "border");
116
+ pulseElement === null || pulseElement === void 0 ? void 0 : pulseElement.classList.remove("zoom-in-out-element");
117
+ pulseElement === null || pulseElement === void 0 ? void 0 : pulseElement.removeEventListener("animationend", onEnd);
112
118
  };
113
- targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.addEventListener("animationend", onEnd, {
119
+ pulseElement === null || pulseElement === void 0 ? void 0 : pulseElement.addEventListener("animationend", onEnd, {
114
120
  once: true,
115
121
  });
116
122
  }, 500);
@@ -1 +1 @@
1
- {"version":3,"file":"useTypingStatus.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useTypingStatus.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,WAAW,EAEZ,MAAM,8BAA8B,CAAC;AAuBtC,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,WAK7C,CAAC;AAqDF,eAAO,MAAM,wBAAwB,GACnC,SAAS,uBAAuB,GAAG,MAAM,SA0B1C,CAAC;AAUF,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,GAAI,SAAS,WAAW,SAK3D,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,mFAAmF;IACnF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,cAAc,GAAI,iBAAiB,MAAM,KAAG,WAoBxD,CAAC"}
1
+ {"version":3,"file":"useTypingStatus.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useTypingStatus.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,WAAW,EACZ,MAAM,8BAA8B,CAAC;AA0BtC,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,WAK7C,CAAC;AAqDF,eAAO,MAAM,wBAAwB,GACnC,SAAS,uBAAuB,GAAG,MAAM,SA0B1C,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,GAAI,SAAS,WAAW,SAK3D,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,mFAAmF;IACnF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,cAAc,GAAI,iBAAiB,MAAM,KAAG,WAoBxD,CAAC"}
@@ -1,11 +1,10 @@
1
1
  import { useTranslation } from "react-i18next";
2
2
  import { useShallow } from "zustand/react/shallow";
3
- import { SessionType, } from "@droppii-org/wasm-client-sdk";
4
3
  import { DChatSDK } from "../../constants/sdk";
5
4
  import useAuthStore from "../../store/auth";
6
5
  import useConversationStore from "../../store/conversation";
7
6
  import useTypingStore from "../../store/typing";
8
- import { getGroupIdFromConversationId } from "../../utils/conversation";
7
+ import { getConversationIdFromMessage, getGroupIdFromConversationId, } from "../../utils/conversation";
9
8
  // One typer is named; from two on the text drops names ("Nhiều người đang nhập").
10
9
  const MAX_NAMED_TYPERS = 1;
11
10
  // Longer names are cut to this many characters and end with "...".
@@ -97,13 +96,6 @@ export const handleInputStatusChanged = (payload) => {
97
96
  useTypingStore.getState().removeTyper(conversationID, userID);
98
97
  }
99
98
  };
100
- // Mirrors OpenIM's conversationID scheme: si_<sorted user ids> / sg_<groupID>.
101
- const getConversationIdFromMessage = (message) => {
102
- if (message.sessionType === SessionType.Single) {
103
- return `si_${[message.sendID, message.recvID].sort().join("_")}`;
104
- }
105
- return message.groupID ? `sg_${message.groupID}` : "";
106
- };
107
99
  /** A typer's own message landing ends their typing state right away. */
108
100
  export const removeTyperOnNewMessage = (message) => {
109
101
  const conversationId = getConversationIdFromMessage(message);
@@ -0,0 +1,8 @@
1
+ export interface PdpSearchResultTarget {
2
+ threadId?: string;
3
+ groupId?: string;
4
+ messageId?: string;
5
+ }
6
+ export declare const buildPdpSearchResultUrl: (pathname: string, search: string, target: PdpSearchResultTarget) => string;
7
+ export declare const useOpenPdpSearchResult: () => (target: PdpSearchResultTarget) => void;
8
+ //# sourceMappingURL=useOpenPdpSearchResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOpenPdpSearchResult.d.ts","sourceRoot":"","sources":["../../../src/hooks/search/useOpenPdpSearchResult.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,eAAO,MAAM,uBAAuB,GAClC,UAAU,MAAM,EAChB,QAAQ,MAAM,EACd,QAAQ,qBAAqB,WAQ9B,CAAC;AAIF,eAAO,MAAM,sBAAsB,iBAItB,qBAAqB,SAuBjC,CAAC"}
@@ -0,0 +1,31 @@
1
+ "use client";
2
+ import { useCallback } from "react";
3
+ import { useChatNavigate } from "../../hooks/conversation/useChatNavigate";
4
+ import useConversationStore from "../../store/conversation";
5
+ const TARGET_PARAMS = ["threadId", "groupId", "userId", "botId", "messageId"];
6
+ export const buildPdpSearchResultUrl = (pathname, search, target) => {
7
+ const params = new URLSearchParams(search);
8
+ TARGET_PARAMS.forEach((key) => params.delete(key));
9
+ Object.entries(target).forEach(([key, value]) => {
10
+ if (value)
11
+ params.set(key, value);
12
+ });
13
+ return `${pathname}?${params.toString()}`;
14
+ };
15
+ // PDP opens results through its URL: DChatConversationDetail re-resolves the target
16
+ // with forceRevalidate, which is the access check before showing any content.
17
+ export const useOpenPdpSearchResult = () => {
18
+ const onNavigate = useChatNavigate();
19
+ return useCallback((target) => {
20
+ onNavigate(buildPdpSearchResultUrl(window.location.pathname, window.location.search, target));
21
+ // The resolver skips an already-open thread, so hand it the jump target directly.
22
+ const { conversationData, setConversationData } = useConversationStore.getState();
23
+ if (target.messageId &&
24
+ conversationData &&
25
+ conversationData.conversationID === target.threadId) {
26
+ setConversationData(conversationData, target.messageId, {
27
+ forceRevalidate: true,
28
+ });
29
+ }
30
+ }, [onNavigate]);
31
+ };