@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.
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +3 -2
- package/dist/components/search-conversation/SearchAll.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchAll.js +7 -9
- package/dist/components/search-conversation/SearchConversationAsGroups.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchConversationAsGroups.js +3 -0
- package/dist/components/search-conversation/SearchConversationAsMessages.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchConversationAsMessages.js +4 -1
- package/dist/components/search-conversation/SearchConversationAsUsers.d.ts.map +1 -1
- package/dist/components/search-conversation/SearchConversationAsUsers.js +4 -6
- package/dist/components/search-conversation/SearchScopeContext.d.ts +4 -0
- package/dist/components/search-conversation/SearchScopeContext.d.ts.map +1 -0
- package/dist/components/search-conversation/SearchScopeContext.js +5 -0
- package/dist/components/search-conversation/index.d.ts +5 -2
- package/dist/components/search-conversation/index.d.ts.map +1 -1
- package/dist/components/search-conversation/index.js +17 -12
- package/dist/components/search-conversation/item/SearchItemAsGroup.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsGroup.js +9 -0
- package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts +2 -0
- package/dist/components/search-conversation/item/SearchItemAsMessage.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsMessage.js +28 -6
- package/dist/components/search-conversation/item/SearchItemAsUser.d.ts +2 -1
- package/dist/components/search-conversation/item/SearchItemAsUser.d.ts.map +1 -1
- package/dist/components/search-conversation/item/SearchItemAsUser.js +9 -2
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +2 -0
- package/dist/hooks/message/useMessageListScroll.d.ts.map +1 -1
- package/dist/hooks/message/useMessageListScroll.js +11 -5
- package/dist/hooks/message/useTypingStatus.d.ts.map +1 -1
- package/dist/hooks/message/useTypingStatus.js +1 -9
- package/dist/hooks/search/useOpenPdpSearchResult.d.ts +8 -0
- package/dist/hooks/search/useOpenPdpSearchResult.d.ts.map +1 -0
- package/dist/hooks/search/useOpenPdpSearchResult.js +31 -0
- package/dist/hooks/search/useSearchGroups.d.ts +3 -1
- package/dist/hooks/search/useSearchGroups.d.ts.map +1 -1
- package/dist/hooks/search/useSearchGroups.js +22 -11
- package/dist/hooks/search/useSearchMessage.d.ts +2 -0
- package/dist/hooks/search/useSearchMessage.d.ts.map +1 -1
- package/dist/hooks/search/useSearchMessage.js +10 -4
- package/dist/hooks/search/useSearchPdpTeamSessions.d.ts +17 -0
- package/dist/hooks/search/useSearchPdpTeamSessions.d.ts.map +1 -0
- package/dist/hooks/search/useSearchPdpTeamSessions.js +38 -0
- package/dist/hooks/search/useSearchUsers.d.ts +14 -0
- package/dist/hooks/search/useSearchUsers.d.ts.map +1 -0
- package/dist/hooks/search/useSearchUsers.js +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/locales/vi/common.json +1 -0
- package/dist/services/query.d.ts +1 -0
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +1 -0
- package/dist/services/routes.d.ts +3 -0
- package/dist/services/routes.d.ts.map +1 -1
- package/dist/services/routes.js +3 -0
- package/dist/styles/global.css +1 -1
- package/dist/types/search.d.ts +2 -0
- package/dist/types/search.d.ts.map +1 -0
- package/dist/types/search.js +1 -0
- package/dist/utils/conversation.d.ts +2 -1
- package/dist/utils/conversation.d.ts.map +1 -1
- package/dist/utils/conversation.js +8 -1
- 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;
|
|
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
|
|
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;
|
|
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":"
|
|
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":"
|
|
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":"
|
|
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 {
|
|
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
|
|
11
|
-
|
|
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 @@
|
|
|
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"}
|
|
@@ -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":"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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;
|
|
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;
|
|
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
|
-
|
|
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
|
-
} }),
|
|
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;
|
|
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;
|
|
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"}
|
package/dist/constants/index.js
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
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("
|
|
111
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
+
};
|