@droppii-org/chat-sdk 0.6.55 → 0.6.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"QuoteMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/QuoteMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAO3D,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,QAAA,MAAM,gBAAgB,GAAI,mCAGvB,qBAAqB,mDAmDvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"QuoteMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/QuoteMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAS3D,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,QAAA,MAAM,gBAAgB,GAAI,mCAGvB,qBAAqB,mDA0EvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -4,6 +4,8 @@ import { useCallback, useMemo } from "react";
4
4
  import useAuthStore from "../../../store/auth";
5
5
  import useConversationStore from "../../../store/conversation";
6
6
  import ReplyQuoteContent from "../../../components/message/reply/ReplyQuoteContent";
7
+ import { useUserUsername } from "../../../hooks/user/useUserUsername";
8
+ import { isSupportSessionAgentView } from "../../../utils/conversation";
7
9
  const QuoteMessageItem = ({ message, onPressQuoteMessage, }) => {
8
10
  var _a, _b;
9
11
  const userID = useAuthStore((state) => state.userID);
@@ -19,7 +21,19 @@ const QuoteMessageItem = ({ message, onPressQuoteMessage, }) => {
19
21
  return false;
20
22
  }
21
23
  }, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex]);
24
+ const quoteMessage = ((_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage) || ((_b = message === null || message === void 0 ? void 0 : message.atTextElem) === null || _b === void 0 ? void 0 : _b.quoteMessage);
25
+ // Outside CRM, an agent identifies quoted senders by username; the session
26
+ // owner keeps seeing the thread's own name.
27
+ const isAgentView = !isCrm && isSupportSessionAgentView(conversationData, userID);
28
+ const quotedUsername = useUserUsername(isAgentView && (quoteMessage === null || quoteMessage === void 0 ? void 0 : quoteMessage.sendID) !== userID
29
+ ? quoteMessage === null || quoteMessage === void 0 ? void 0 : quoteMessage.sendID
30
+ : undefined);
22
31
  const getDisplayName = useCallback(({ name, id }) => {
32
+ if (isAgentView) {
33
+ if (id === userID)
34
+ return t("you");
35
+ return quotedUsername || name || "";
36
+ }
23
37
  if (!name)
24
38
  return "";
25
39
  if (!isCrm && isChatSupport) {
@@ -28,8 +42,15 @@ const QuoteMessageItem = ({ message, onPressQuoteMessage, }) => {
28
42
  if (id === userID)
29
43
  return t("you");
30
44
  return name;
31
- }, [isCrm, isChatSupport, conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName, userID, t]);
32
- const quoteMessage = ((_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage) || ((_b = message === null || message === void 0 ? void 0 : message.atTextElem) === null || _b === void 0 ? void 0 : _b.quoteMessage);
45
+ }, [
46
+ isAgentView,
47
+ quotedUsername,
48
+ isCrm,
49
+ isChatSupport,
50
+ conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName,
51
+ userID,
52
+ t,
53
+ ]);
33
54
  if (!quoteMessage)
34
55
  return null;
35
56
  const title = getDisplayName({
@@ -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;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"}
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,mDAsZlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -135,22 +135,35 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
135
135
  ]);
136
136
  const bubbleWrapperRef = useRef(null);
137
137
  useLongPress(() => onContextMenuOpenChange === null || onContextMenuOpenChange === void 0 ? void 0 : onContextMenuOpenChange(true), enableLongPress ? bubbleWrapperRef : undefined, { delay: 500 });
138
+ // Agents outside CRM (e.g. PDP CS) also need to tell the owner apart from
139
+ // other supporters; only the session owner keeps the anonymous bot view.
140
+ const isSessionAgentView = isSupportSessionAgentView(conversationData, userID);
138
141
  const showSenderInfo = useMemo(() => {
139
142
  var _a, _b, _c;
143
+ if ((message === null || message === void 0 ? void 0 : message.sendID) === userID)
144
+ return false;
145
+ if (isSessionAgentView)
146
+ return true;
140
147
  try {
141
148
  const isChatSupport = (_c = (_b = (_a = JSON.parse((conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex) || "{}")) === null || _a === void 0 ? void 0 : _a.sessionInfo) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.botId;
142
- return Boolean(isChatSupport && isCrm && (message === null || message === void 0 ? void 0 : message.sendID) !== userID);
149
+ return Boolean(isChatSupport && isCrm);
143
150
  }
144
151
  catch (_d) {
145
152
  console.log("Failed to parse conversationData.ex");
146
153
  return false;
147
154
  }
148
- }, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, isCrm, message === null || message === void 0 ? void 0 : message.sendID, userID]);
155
+ }, [
156
+ conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex,
157
+ isCrm,
158
+ isSessionAgentView,
159
+ message === null || message === void 0 ? void 0 : message.sendID,
160
+ userID,
161
+ ]);
149
162
  const isInternalMessage = Boolean(message === null || message === void 0 ? void 0 : message.isInternal);
150
163
  const isSystemLogMessage = isSystemLogMessageType(message === null || message === void 0 ? void 0 : message.contentType);
151
164
  const isGroupNotificationMessage = isGroupNotificationMessageType(message === null || message === void 0 ? void 0 : message.contentType);
152
165
  const isSessionEvent = isSessionEventMessage(message);
153
- const showsSessionEvents = isCrm || isSupportSessionAgentView(conversationData, userID);
166
+ const showsSessionEvents = isCrm || isSessionAgentView;
154
167
  const isStickerMessage = (message === null || message === void 0 ? void 0 : message.contentType) === MessageType.StickerMessage;
155
168
  const hasContextMenu = contextMenuItems.length > 0;
156
169
  const isLatestMine = ((_a = allMessages.find((m) => m.sendID === userID)) === null || _a === void 0 ? void 0 : _a.clientMsgID) ===
@@ -1 +1 @@
1
- {"version":3,"file":"ReplyPreviewBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyPreviewBar.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,eAAe,sDAwC3B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ReplyPreviewBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyPreviewBar.tsx"],"names":[],"mappings":"AAQA,eAAO,MAAM,eAAe,sDAmD3B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -3,21 +3,28 @@ import { useTranslation } from "react-i18next";
3
3
  import { Icon } from "../../../components/icon";
4
4
  import useAuthStore from "../../../store/auth";
5
5
  import useConversationStore from "../../../store/conversation";
6
+ import { useUserUsername } from "../../../hooks/user/useUserUsername";
7
+ import { isSupportSessionAgentView } from "../../../utils/conversation";
6
8
  import { ReplyQuoteContent } from "./ReplyQuoteContent";
7
9
  export const ReplyPreviewBar = () => {
8
10
  const { t } = useTranslation();
9
11
  const quotedMessage = useConversationStore((state) => state.quotedMessage);
10
12
  const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
13
+ const conversationData = useConversationStore((state) => state.conversationData);
11
14
  const userID = useAuthStore((state) => state.userID);
15
+ const isCrm = useAuthStore((state) => state.isCrm);
16
+ const isMe = (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.sendID) === userID;
17
+ // Matches the sent quote's title, which shows agents outside CRM the username.
18
+ const isAgentView = !isCrm && isSupportSessionAgentView(conversationData, userID);
19
+ const quotedUsername = useUserUsername(isAgentView && !isMe ? quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.sendID : undefined);
12
20
  const handleClearQuotedMessage = () => {
13
21
  setQuotedMessage(null);
14
22
  };
15
23
  if (!quotedMessage)
16
24
  return null;
17
- const isMe = quotedMessage.sendID === userID;
18
25
  const senderName = isMe
19
26
  ? t("your_self")
20
- : quotedMessage.senderNickname || "";
27
+ : quotedUsername || quotedMessage.senderNickname || "";
21
28
  return (_jsxs("div", { "data-testid": "reply-preview-bar", "data-cp-name": "ReplyPreviewBar", className: "flex h-[59px] w-full shrink-0 items-center bg-gray-200/10 px-2 py-1", children: [_jsx(ReplyQuoteContent, { message: quotedMessage, title: t("reply_to", { name: senderName }) }), _jsx("button", { type: "button", onClick: handleClearQuotedMessage, "aria-label": t("cancel"), "data-testid": "reply-preview-bar-close", className: "flex h-4 w-4 shrink-0 items-center justify-center", children: _jsx(Icon, { icon: "close-o", size: 16, className: "text-gray-600" }) })] }));
22
29
  };
23
30
  export default ReplyPreviewBar;
@@ -0,0 +1,3 @@
1
+ /** Username from the user's public info `ex`; undefined until known. */
2
+ export declare const useUserUsername: (userId?: string) => string | undefined;
3
+ //# sourceMappingURL=useUserUsername.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUserUsername.d.ts","sourceRoot":"","sources":["../../../src/hooks/user/useUserUsername.ts"],"names":[],"mappings":"AA+BA,wEAAwE;AACxE,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,SAoB1D,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { DChatSDK } from "../../constants/sdk";
4
+ import { useChatContext } from "../../context/ChatContext";
5
+ import useUsersInfoStore from "../../store/usersInfo";
6
+ import { ConnectStatus } from "../../types/chat";
7
+ // Backoff for a failed/empty lookup, same as the header's owner lookup.
8
+ const RETRY_DELAYS_MS = [2000, 5000, 10000];
9
+ // Quotes of one sender mount together; only one lookup runs per user at a time.
10
+ const pendingUserIds = new Set();
11
+ const loadUserInfo = (userId, attempt = 0) => {
12
+ DChatSDK.getUsersInfo([userId])
13
+ .then(({ data }) => {
14
+ if (!(data === null || data === void 0 ? void 0 : data.length))
15
+ throw new Error("user not found");
16
+ useUsersInfoStore.getState().upsertUsers(data);
17
+ pendingUserIds.delete(userId);
18
+ })
19
+ .catch((error) => {
20
+ const delay = RETRY_DELAYS_MS[attempt];
21
+ if (delay === undefined) {
22
+ pendingUserIds.delete(userId);
23
+ console.error("Error fetching user info:", error);
24
+ return;
25
+ }
26
+ setTimeout(() => loadUserInfo(userId, attempt + 1), delay);
27
+ });
28
+ };
29
+ /** Username from the user's public info `ex`; undefined until known. */
30
+ export const useUserUsername = (userId) => {
31
+ var _a, _b, _c;
32
+ const { connectStatus } = useChatContext();
33
+ const user = useUsersInfoStore((state) => userId ? state.usersInfo[userId] : undefined);
34
+ useEffect(() => {
35
+ if (!userId || user || pendingUserIds.has(userId))
36
+ return;
37
+ if (connectStatus !== ConnectStatus.Connected)
38
+ return;
39
+ pendingUserIds.add(userId);
40
+ loadUserInfo(userId);
41
+ }, [userId, user, connectStatus]);
42
+ try {
43
+ const ex = JSON.parse((user === null || user === void 0 ? void 0 : user.ex) || "{}");
44
+ return ((_c = (_b = (_a = ex === null || ex === void 0 ? void 0 : ex.userInfo) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.username) === null || _c === void 0 ? void 0 : _c.trim()) || undefined;
45
+ }
46
+ catch (_d) {
47
+ return undefined;
48
+ }
49
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-sdk",
3
- "version": "0.6.55",
3
+ "version": "0.6.56",
4
4
  "description": "Droppii React Chat SDK",
5
5
  "repository": {
6
6
  "type": "git",