@droppii-org/chat-sdk 0.6.35 → 0.6.36
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/conversation-inbox/ConversationInboxItem.js +7 -7
- package/dist/components/message/item/index.js +10 -10
- package/dist/hooks/conversation/useResolveConversation.d.ts.map +1 -1
- package/dist/hooks/conversation/useResolveConversation.js +13 -2
- package/dist/utils/conversation.d.ts +11 -0
- package/dist/utils/conversation.d.ts.map +1 -1
- package/dist/utils/conversation.js +27 -0
- package/dist/utils/messageLog.d.ts.map +1 -1
- package/dist/utils/messageLog.js +3 -0
- package/package.json +1 -1
|
@@ -29,14 +29,14 @@ const ConversationInboxItem = ({ item, onClick }) => {
|
|
|
29
29
|
const { t } = useTranslation("conversation-inbox");
|
|
30
30
|
const { t: tCommon } = useTranslation("common");
|
|
31
31
|
const currentUserId = useAuthStore((state) => state.userID);
|
|
32
|
+
const isCrm = useAuthStore((state) => state.isCrm);
|
|
32
33
|
const displayName = resolveConversationDisplayName(item, t);
|
|
33
34
|
const avatarUrl = useConversationAvatarUrl(item);
|
|
34
35
|
const badgeLabel = resolvePeerBadgeLabel(item.peerType, t);
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!item.latestMsg)
|
|
36
|
+
// The START divider is hidden inside consumer-app threads, so letting it
|
|
37
|
+
// become the card preview would advertise a message the user cannot find.
|
|
38
|
+
const hidesSessionStart = useMemo(() => {
|
|
39
|
+
if (isCrm || !item.latestMsg)
|
|
40
40
|
return false;
|
|
41
41
|
try {
|
|
42
42
|
return isSessionEventMessage(JSON.parse(item.latestMsg));
|
|
@@ -44,8 +44,8 @@ const ConversationInboxItem = ({ item, onClick }) => {
|
|
|
44
44
|
catch (_a) {
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
|
-
}, [item.latestMsg]);
|
|
48
|
-
const latestMessagePreview =
|
|
47
|
+
}, [isCrm, item.latestMsg]);
|
|
48
|
+
const latestMessagePreview = hidesSessionStart
|
|
49
49
|
? ""
|
|
50
50
|
: parseLatestMessage(item.latestMsg, currentUserId, tCommon, {
|
|
51
51
|
peerType: item.peerType,
|
|
@@ -161,16 +161,13 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
161
161
|
// the nearest ordinary one.
|
|
162
162
|
const immediatePrev = getImmediateNeighbor(allMessages, message, "prev");
|
|
163
163
|
const immediateNext = getImmediateNeighbor(allMessages, message, "next");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
isGroupNotificationMessageType(immediateNext.contentType) ||
|
|
172
|
-
isSessionEventMessage(immediateNext)
|
|
173
|
-
: false;
|
|
164
|
+
// A neighbour that renders nothing must not break the group, or consumer
|
|
165
|
+
// apps get an unexplained gap where the hidden session divider used to be.
|
|
166
|
+
const breaksGroup = (neighbour) => isSystemLogMessageType(neighbour.contentType) ||
|
|
167
|
+
isGroupNotificationMessageType(neighbour.contentType) ||
|
|
168
|
+
(isSessionEventMessage(neighbour) && isCrm);
|
|
169
|
+
const prevBreaksGroup = immediatePrev ? breaksGroup(immediatePrev) : false;
|
|
170
|
+
const nextBreaksGroup = immediateNext ? breaksGroup(immediateNext) : false;
|
|
174
171
|
const prevSameUser = !isOrder &&
|
|
175
172
|
!prevBreaksGroup &&
|
|
176
173
|
!!previousMessage &&
|
|
@@ -211,6 +208,9 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
211
208
|
_jsx(GroupNotificationMessageItem, { message: message })));
|
|
212
209
|
}
|
|
213
210
|
if (isSessionEvent) {
|
|
211
|
+
// Consumer apps hide session dividers — see isSessionEventMessage.
|
|
212
|
+
if (!isCrm)
|
|
213
|
+
return null;
|
|
214
214
|
return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
|
|
215
215
|
timeBreakNode,
|
|
216
216
|
_jsx(SessionEventMessageItem, { message: message })));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResolveConversation.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useResolveConversation.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAIjB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"useResolveConversation.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useResolveConversation.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gBAAgB,EAIjB,MAAM,8BAA8B,CAAC;AAgBtC,MAAM,WAAW,4BAA4B;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsDD,eAAO,MAAM,wBAAwB,GACnC,OAAO,MAAM,KACZ,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAWjC,CAAC;AA+DF,eAAO,MAAM,sBAAsB,GAAI,wDAMpC,4BAA4B;;;CA8J9B,CAAC"}
|
|
@@ -7,7 +7,9 @@ import { ENDPOINTS } from "../../services/routes";
|
|
|
7
7
|
import { ConnectStatus, SyncStatus } from "../../types/chat";
|
|
8
8
|
import { useChatContext } from "../../context/ChatContext";
|
|
9
9
|
import useConversationStore from "../../store/conversation";
|
|
10
|
-
import { getGroupIdFromConversationId, resolveConversationBotId, } from "../../utils/conversation";
|
|
10
|
+
import { getGroupIdFromConversationId, getPeerUserIdFromConversationId, resolveConversationBotId, } from "../../utils/conversation";
|
|
11
|
+
import useAuthStore from "../../store/auth";
|
|
12
|
+
import useUserStore from "../../store/user";
|
|
11
13
|
const MISSING_BOT_GROUP_ERROR = "Missing groupId from get-or-create bot conversation response";
|
|
12
14
|
const CONVERSATION_NOT_FOUND_ERROR = "Conversation not found";
|
|
13
15
|
const RESOLVE_FAILED_ERROR = "Failed to resolve conversation";
|
|
@@ -59,6 +61,7 @@ export const fetchConversationByBotId = async (botId) => {
|
|
|
59
61
|
return fetchBySource(resolvedGroupId, SessionType.Group);
|
|
60
62
|
};
|
|
61
63
|
const fetchConversationByTarget = ({ conversationId, userId, groupId, botId, }) => {
|
|
64
|
+
var _a;
|
|
62
65
|
const targetGroupId = groupId || getGroupIdFromConversationId(conversationId);
|
|
63
66
|
// groupId before userId: a group-message notification link carries both
|
|
64
67
|
// (the group, plus the sender's userId as secondary info) — resolving
|
|
@@ -66,8 +69,16 @@ const fetchConversationByTarget = ({ conversationId, userId, groupId, botId, })
|
|
|
66
69
|
// of the group.
|
|
67
70
|
if (targetGroupId)
|
|
68
71
|
return fetchBySource(targetGroupId, SessionType.Group);
|
|
69
|
-
if (conversationId)
|
|
72
|
+
if (conversationId) {
|
|
73
|
+
// getMultipleConversation only reads the local cache, so a 1:1 deep link
|
|
74
|
+
// to a thread this device has never synced resolves to nothing. The peer
|
|
75
|
+
// encoded in the id lets getOneConversation fetch it instead.
|
|
76
|
+
const selfUserId = useAuthStore.getState().userID || ((_a = useUserStore.getState().selfInfo) === null || _a === void 0 ? void 0 : _a.id);
|
|
77
|
+
const peerUserId = getPeerUserIdFromConversationId(conversationId, selfUserId);
|
|
78
|
+
if (peerUserId)
|
|
79
|
+
return fetchBySource(peerUserId, SessionType.Single);
|
|
70
80
|
return fetchByConversationId(conversationId);
|
|
81
|
+
}
|
|
71
82
|
if (botId)
|
|
72
83
|
return fetchConversationByBotId(botId);
|
|
73
84
|
if (userId)
|
|
@@ -21,4 +21,15 @@ export declare const resolvePeerBadgeColor: (peerType: PeerType) => "" | "bg-[va
|
|
|
21
21
|
* "group unknown".
|
|
22
22
|
*/
|
|
23
23
|
export declare const getGroupIdFromConversationId: (conversationId?: string) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Pulls the OTHER participant out of a 1:1 conversation id
|
|
26
|
+
* ("si_<userA>_<userB>"), which is what getOneConversation wants as its
|
|
27
|
+
* sourceID — passing the viewer's own id would resolve a thread with
|
|
28
|
+
* themselves. The id does not record which side is which, so the peer is
|
|
29
|
+
* whichever half is not selfUserId.
|
|
30
|
+
*
|
|
31
|
+
* Returns "" when the id is not a 1:1 id, is malformed, or when neither half
|
|
32
|
+
* matches selfUserId — guessing a peer there would open the wrong thread.
|
|
33
|
+
*/
|
|
34
|
+
export declare const getPeerUserIdFromConversationId: (conversationId?: string, selfUserId?: string) => string;
|
|
24
35
|
//# sourceMappingURL=conversation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/utils/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAW9B,eAAO,MAAM,sBAAsB,GACjC,IAAI,MAAM,GAAG,SAAS,KACrB,iBAcF,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,MAAM,gBAAgB,KACrB,YAA4D,CAAC;AAEhE,eAAO,MAAM,wBAAwB,GAAI,MAAM,gBAAgB,KAAG,MAOjE,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,gBAAgB,YAChB,CAAC;AAEjC,eAAO,MAAM,cAAc,GAAI,MAAM,gBAAgB,YAChB,CAAC;AAEtC,eAAO,MAAM,WAAW,GAAI,MAAM,gBAAgB,YAChB,CAAC;AAEnC,eAAO,MAAM,8BAA8B,GACzC,MAAM,gBAAgB,EACtB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,KACzB,MAKF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,MAAM,gBAAgB,KACrB,MAAM,GAAG,IAGX,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,QAAQ,EAClB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,KACzB,MAIF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,UAAU,QAAQ,8EAIvD,CAAC;
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/utils/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAW9B,eAAO,MAAM,sBAAsB,GACjC,IAAI,MAAM,GAAG,SAAS,KACrB,iBAcF,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,MAAM,gBAAgB,KACrB,YAA4D,CAAC;AAEhE,eAAO,MAAM,wBAAwB,GAAI,MAAM,gBAAgB,KAAG,MAOjE,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,MAAM,gBAAgB,YAChB,CAAC;AAEjC,eAAO,MAAM,cAAc,GAAI,MAAM,gBAAgB,YAChB,CAAC;AAEtC,eAAO,MAAM,WAAW,GAAI,MAAM,gBAAgB,YAChB,CAAC;AAEnC,eAAO,MAAM,8BAA8B,GACzC,MAAM,gBAAgB,EACtB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,KACzB,MAKF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GACvC,MAAM,gBAAgB,KACrB,MAAM,GAAG,IAGX,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,UAAU,QAAQ,EAClB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,KACzB,MAIF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,UAAU,QAAQ,8EAIvD,CAAC;AAKF;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,GAAI,iBAAiB,MAAM,WAG5D,CAAC;AAET;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B,GAC1C,iBAAiB,MAAM,EACvB,aAAa,MAAM,KAClB,MAYF,CAAC"}
|
|
@@ -62,6 +62,7 @@ export const resolvePeerBadgeColor = (peerType) => {
|
|
|
62
62
|
return "";
|
|
63
63
|
};
|
|
64
64
|
const GROUP_CONVERSATION_ID_PREFIX = "sg_";
|
|
65
|
+
const SINGLE_CONVERSATION_ID_PREFIX = "si_";
|
|
65
66
|
/**
|
|
66
67
|
* Group conversationIds are formatted as "sg_<groupID>" — derive the groupID
|
|
67
68
|
* straight from the id when a full ConversationItem isn't available yet (e.g.
|
|
@@ -75,3 +76,29 @@ const GROUP_CONVERSATION_ID_PREFIX = "sg_";
|
|
|
75
76
|
export const getGroupIdFromConversationId = (conversationId) => (conversationId === null || conversationId === void 0 ? void 0 : conversationId.startsWith(GROUP_CONVERSATION_ID_PREFIX))
|
|
76
77
|
? conversationId.slice(GROUP_CONVERSATION_ID_PREFIX.length)
|
|
77
78
|
: "";
|
|
79
|
+
/**
|
|
80
|
+
* Pulls the OTHER participant out of a 1:1 conversation id
|
|
81
|
+
* ("si_<userA>_<userB>"), which is what getOneConversation wants as its
|
|
82
|
+
* sourceID — passing the viewer's own id would resolve a thread with
|
|
83
|
+
* themselves. The id does not record which side is which, so the peer is
|
|
84
|
+
* whichever half is not selfUserId.
|
|
85
|
+
*
|
|
86
|
+
* Returns "" when the id is not a 1:1 id, is malformed, or when neither half
|
|
87
|
+
* matches selfUserId — guessing a peer there would open the wrong thread.
|
|
88
|
+
*/
|
|
89
|
+
export const getPeerUserIdFromConversationId = (conversationId, selfUserId) => {
|
|
90
|
+
if (!(conversationId === null || conversationId === void 0 ? void 0 : conversationId.startsWith(SINGLE_CONVERSATION_ID_PREFIX)))
|
|
91
|
+
return "";
|
|
92
|
+
if (!selfUserId)
|
|
93
|
+
return "";
|
|
94
|
+
const [first, second] = conversationId
|
|
95
|
+
.slice(SINGLE_CONVERSATION_ID_PREFIX.length)
|
|
96
|
+
.split("_");
|
|
97
|
+
if (!first || !second)
|
|
98
|
+
return "";
|
|
99
|
+
if (first === selfUserId)
|
|
100
|
+
return second;
|
|
101
|
+
if (second === selfUserId)
|
|
102
|
+
return first;
|
|
103
|
+
return "";
|
|
104
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messageLog.d.ts","sourceRoot":"","sources":["../../src/utils/messageLog.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,WAAW,EACZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,eAAO,MAAM,wBAAwB,uCAAwC,CAAC;AAI9E,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"messageLog.d.ts","sourceRoot":"","sources":["../../src/utils/messageLog.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,WAAW,EACZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,eAAO,MAAM,wBAAwB,uCAAwC,CAAC;AAI9E,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AACvD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAKnD,eAAO,MAAM,qBAAqB,GAAI,UAAU,OAAO,CAAC,WAAW,CAAC,YAGf,CAAC;AAEtD,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,CAAC,WAAW,CAAC,EAC7B,IAAI,SAAS,KACZ,MAQF,CAAC;AAEF,eAAO,MAAM,gCAAgC,6dAmBnC,CAAC;AAEX,eAAO,MAAM,8BAA8B,GAAI,cAAc,MAAM,YAGhE,CAAC;AAoDJ,eAAO,MAAM,wBAAwB,GACnC,aAAa,MAAM,GAAG,SAAS,EAC/B,YAAY,MAAM,GAAG,SAAS,EAC9B,IAAI,SAAS,EACb,iBAAiB,MAAM,KACtB,MAmJF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,cAAc,MAAM,8CACf,CAAC;AAE7C,eAAO,MAAM,uBAAuB,GAAI,SAAS,OAAO,CAAC,WAAW,CAAC,WAyBpE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,SAAS,OAAO,CAAC,WAAW,CAAC,WA2BpE,CAAC"}
|
package/dist/utils/messageLog.js
CHANGED
|
@@ -4,6 +4,9 @@ export const SYSTEM_LOG_MESSAGE_TYPES = [MessageType.LogTextMessage];
|
|
|
4
4
|
// (unlike Order/Product), so they're identified by this exact `data` string.
|
|
5
5
|
export const SESSION_START_MARKER = "#SESSION - START";
|
|
6
6
|
export const SESSION_END_MARKER = "#SESSION - END";
|
|
7
|
+
// Session boundaries are internal bookkeeping: the customer never asked for a
|
|
8
|
+
// session, so announcing either end of one is noise in a consumer app (BIZ,
|
|
9
|
+
// Mall). CRM keeps them — agents work the session boundaries.
|
|
7
10
|
export const isSessionEventMessage = (message) => {
|
|
8
11
|
var _a, _b;
|
|
9
12
|
return (message === null || message === void 0 ? void 0 : message.contentType) === MessageType.CustomMessage &&
|