@droppii-org/chat-sdk 0.6.53 → 0.6.55
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-detail/ConversationMessageList.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationMessageList.js +8 -0
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +6 -0
- 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/conversation/useViewOnlyGroupRefresh.d.ts +11 -0
- package/dist/hooks/conversation/useViewOnlyGroupRefresh.d.ts.map +1 -0
- package/dist/hooks/conversation/useViewOnlyGroupRefresh.js +43 -0
- package/dist/hooks/message/useMessage.d.ts +2 -0
- package/dist/hooks/message/useMessage.d.ts.map +1 -1
- package/dist/hooks/message/useMessage.js +84 -0
- package/dist/hooks/search/useSearchGroups.d.ts +1 -0
- package/dist/hooks/search/useSearchGroups.d.ts.map +1 -1
- package/dist/hooks/search/useSearchGroups.js +11 -1
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +73 -0
- package/dist/store/type.d.ts +1 -0
- package/dist/store/type.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationMessageList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ConversationMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationMessageList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA0BzE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACrC;AAED,QAAA,MAAM,uBAAuB,GAAI,4DAI9B,4BAA4B,4CA8Q9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -12,7 +12,9 @@ import { useUnreadMessageIndicator } from "../../hooks/message/useUnreadMessageI
|
|
|
12
12
|
import { usePinMessage } from "../../hooks/message/usePinMessage";
|
|
13
13
|
import { useRevokeMessage } from "../../hooks/message/useRevokeMessage";
|
|
14
14
|
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
15
|
+
import { useViewOnlyGroupRefresh } from "../../hooks/conversation/useViewOnlyGroupRefresh";
|
|
15
16
|
import useConversationStore from "../../store/conversation";
|
|
17
|
+
import { PeerType } from "../../types/conversation";
|
|
16
18
|
import useAuthStore from "../../store/auth";
|
|
17
19
|
import { isGroupChat as resolveIsGroupChat, isSupportSessionAgentView, } from "../../utils/conversation";
|
|
18
20
|
import emitter from "../../utils/events";
|
|
@@ -28,6 +30,7 @@ const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessag
|
|
|
28
30
|
const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
|
|
29
31
|
const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
|
|
30
32
|
const searchClientMsgID = useConversationStore((state) => state.searchClientMsgID);
|
|
33
|
+
const isViewOnlyMember = useConversationStore((state) => state.isViewOnlyMember);
|
|
31
34
|
const setSearchClientMsgID = useConversationStore((state) => state.setSearchClientMsgID);
|
|
32
35
|
const conversationId = selectedConversationId || (conversation === null || conversation === void 0 ? void 0 : conversation.conversationID) || "";
|
|
33
36
|
const isGroupChat = conversation ? resolveIsGroupChat(conversation) : false;
|
|
@@ -40,6 +43,11 @@ const ConversationMessageList = ({ bottomSlot, onCopyMessageLink, onSearchMessag
|
|
|
40
43
|
// agent handling someone else's session needs — load the full history.
|
|
41
44
|
const useAppHistory = !isSupportSessionAgentView(Object.assign(Object.assign({}, conversation), { conversationID: conversationId }), viewerUserID);
|
|
42
45
|
const messageController = useMessage(conversationId, searchClientMsgID, true, useAppHistory, onSearchMessageRevoked);
|
|
46
|
+
useViewOnlyGroupRefresh({
|
|
47
|
+
enabled: isViewOnlyMember && (conversation === null || conversation === void 0 ? void 0 : conversation.peerType) === PeerType.GROUP,
|
|
48
|
+
groupId: conversation === null || conversation === void 0 ? void 0 : conversation.groupID,
|
|
49
|
+
refreshMessages: messageController.refreshLatestMessages,
|
|
50
|
+
});
|
|
43
51
|
const { isResolved: isUnreadLookupResolved, firstUnreadMessageId, unreadDividerMessageId, showJumpButton, markDividerSeen, } = useUnreadMessageIndicator({
|
|
44
52
|
conversationId,
|
|
45
53
|
searchClientMsgID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAqCA,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CA2Z3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -24,6 +24,7 @@ import { usePinMessage } from "../../hooks/message/usePinMessage";
|
|
|
24
24
|
import { useConversationSessionState } from "../../hooks/session/useConversationSessionState";
|
|
25
25
|
import { useJoinGroupFlow } from "../../hooks/session/useJoinGroupFlow";
|
|
26
26
|
import { useGroupPermission } from "../../hooks/group/useGroupPermission";
|
|
27
|
+
import { useViewOnlyGroupRefresh } from "../../hooks/conversation/useViewOnlyGroupRefresh";
|
|
27
28
|
import { isGroupConversation } from "../../utils/imCommon";
|
|
28
29
|
import { ConnectStatus, SessionStatus } from "../../types/chat";
|
|
29
30
|
import { PeerType } from "../../types/conversation";
|
|
@@ -108,6 +109,11 @@ const MessageList = (props) => {
|
|
|
108
109
|
}
|
|
109
110
|
}, [isConfirmedGroup, isJoined, isViewOnlyMember, setIsViewOnlyMember]);
|
|
110
111
|
const messageController = useMessage(conversationId, searchClientMsgID, true, false, onSearchMessageRevoked);
|
|
112
|
+
useViewOnlyGroupRefresh({
|
|
113
|
+
enabled: isViewOnlyMember && isConfirmedGroup,
|
|
114
|
+
groupId: groupID,
|
|
115
|
+
refreshMessages: messageController.refreshLatestMessages,
|
|
116
|
+
});
|
|
111
117
|
const { loadState, moreOldLoading, moreNewLoading } = messageController;
|
|
112
118
|
const { isResolved: isUnreadLookupResolved, firstUnreadMessageId, unreadDividerMessageId, showJumpButton, markDividerSeen, } = useUnreadMessageIndicator({
|
|
113
119
|
conversationId,
|
|
@@ -5,6 +5,7 @@ export declare const PAGE_SIZE: {
|
|
|
5
5
|
readonly medium: 20;
|
|
6
6
|
readonly large: 50;
|
|
7
7
|
};
|
|
8
|
+
export declare const VIEW_ONLY_REFRESH_INTERVAL_MS = 10000;
|
|
8
9
|
export declare const MSG_ITEM_PREFIX = "msg-item-";
|
|
9
10
|
export declare const MSG_ITEM_CONTENT_PREFIX = "msg-item-content-";
|
|
10
11
|
export declare const MSG_ITEM_BUBBLE_GROUP_PREFIX = "msg-item-bubble-group-";
|
|
@@ -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;
|
|
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;AAGX,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAEpD,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
|
@@ -5,6 +5,8 @@ export const PAGE_SIZE = {
|
|
|
5
5
|
medium: 20,
|
|
6
6
|
large: 50,
|
|
7
7
|
};
|
|
8
|
+
// A non-member viewing a public group gets no pushes, so the view polls at this pace.
|
|
9
|
+
export const VIEW_ONLY_REFRESH_INTERVAL_MS = 10000;
|
|
8
10
|
export const MSG_ITEM_PREFIX = "msg-item-";
|
|
9
11
|
export const MSG_ITEM_CONTENT_PREFIX = "msg-item-content-";
|
|
10
12
|
// Bubble plus its pin badge, so the jump-to-message pulse moves both together.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface UseViewOnlyGroupRefreshOptions {
|
|
2
|
+
/** True only while the viewer reads a public group they are not a member of. */
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
groupId?: string;
|
|
5
|
+
refreshMessages: () => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
/** OpenIM only pushes to group members, so refresh a read-only viewer's messages and
|
|
8
|
+
* group info on open, then poll while visible and again when the tab returns. */
|
|
9
|
+
export declare const useViewOnlyGroupRefresh: ({ enabled, groupId, refreshMessages, }: UseViewOnlyGroupRefreshOptions) => void;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=useViewOnlyGroupRefresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useViewOnlyGroupRefresh.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useViewOnlyGroupRefresh.ts"],"names":[],"mappings":"AAKA,UAAU,8BAA8B;IACtC,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED;iFACiF;AACjF,eAAO,MAAM,uBAAuB,GAAI,wCAIrC,8BAA8B,SAkChC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useLatest } from "ahooks";
|
|
3
|
+
import { VIEW_ONLY_REFRESH_INTERVAL_MS } from "../../constants";
|
|
4
|
+
import useConversationStore from "../../store/conversation";
|
|
5
|
+
/** OpenIM only pushes to group members, so refresh a read-only viewer's messages and
|
|
6
|
+
* group info on open, then poll while visible and again when the tab returns. */
|
|
7
|
+
export const useViewOnlyGroupRefresh = ({ enabled, groupId, refreshMessages, }) => {
|
|
8
|
+
const refreshMessagesRef = useLatest(refreshMessages);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!enabled || !groupId)
|
|
11
|
+
return;
|
|
12
|
+
let inFlight = false;
|
|
13
|
+
const refresh = async () => {
|
|
14
|
+
var _a;
|
|
15
|
+
if (inFlight || document.visibilityState === "hidden")
|
|
16
|
+
return;
|
|
17
|
+
inFlight = true;
|
|
18
|
+
try {
|
|
19
|
+
await Promise.allSettled([
|
|
20
|
+
(_a = refreshMessagesRef.current) === null || _a === void 0 ? void 0 : _a.call(refreshMessagesRef),
|
|
21
|
+
useConversationStore.getState().refreshViewOnlyGroup(groupId),
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
inFlight = false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const onVisibilityChange = () => {
|
|
29
|
+
if (document.visibilityState === "visible")
|
|
30
|
+
void refresh();
|
|
31
|
+
};
|
|
32
|
+
const timer = window.setInterval(() => {
|
|
33
|
+
void refresh();
|
|
34
|
+
}, VIEW_ONLY_REFRESH_INTERVAL_MS);
|
|
35
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
36
|
+
// Reopening a group shows its cached name/avatar; don't wait a full interval.
|
|
37
|
+
void refresh();
|
|
38
|
+
return () => {
|
|
39
|
+
window.clearInterval(timer);
|
|
40
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
41
|
+
};
|
|
42
|
+
}, [enabled, groupId, refreshMessagesRef]);
|
|
43
|
+
};
|
|
@@ -22,10 +22,12 @@ export declare const useMessage: (conversationId?: string, searchClientMsgID?: s
|
|
|
22
22
|
getMoreOldMessages: (loadMore?: any) => Promise<void>;
|
|
23
23
|
moreNewLoading: boolean;
|
|
24
24
|
getMoreNewMessages: (loadMore?: any) => Promise<void>;
|
|
25
|
+
refreshLatestMessages: () => Promise<void>;
|
|
25
26
|
};
|
|
26
27
|
export declare const pushNewMessage: (message: MessageItem) => void;
|
|
27
28
|
export declare const updateOneMessage: (message: MessageItem) => void;
|
|
28
29
|
export declare const removeOneMessage: (clientMsgID: string) => void;
|
|
29
30
|
export declare const getVisibleNeighbor: (allMessages: MessageItem[], current: MessageItem, direction: "prev" | "next") => MessageItem | undefined;
|
|
30
31
|
export declare const getImmediateNeighbor: (allMessages: MessageItem[], current: MessageItem, direction: "prev" | "next") => MessageItem | undefined;
|
|
32
|
+
export declare const mergeLatestMessages: (current: MessageItem[], fetched: MessageItem[]) => MessageItem[];
|
|
31
33
|
//# sourceMappingURL=useMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,WAAW,EACX,WAAW,EAEZ,MAAM,8BAA8B,CAAC;AAgBtC,eAAO,MAAM,kBAAkB,eAkB9B,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,SAAS,WAAW,EACpB,OAAO,OAAO,EACd,eAAe;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5E,eAAe,MAAM,KACpB,OA0BF,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,iBAAiB,MAAM,EACvB,oBAAoB,MAAM,EAC1B,iBAAc,EACd,uBAAqB,EAGrB,yBAAyB,MAAM,IAAI;;;;;qBAgBd,WAAW,EAAE;;;;;;qBAAb,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,WAAW,EACX,WAAW,EAEZ,MAAM,8BAA8B,CAAC;AAgBtC,eAAO,MAAM,kBAAkB,eAkB9B,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,SAAS,WAAW,EACpB,OAAO,OAAO,EACd,eAAe;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5E,eAAe,MAAM,KACpB,OA0BF,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,iBAAiB,MAAM,EACvB,oBAAoB,MAAM,EAC1B,iBAAc,EACd,uBAAqB,EAGrB,yBAAyB,MAAM,IAAI;;;;;qBAgBd,WAAW,EAAE;;;;;;qBAAb,WAAW,EAAE;;;;;;;CAoZnC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,SACpB,CAAC;AAChC,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,SACpB,CAAC;AAClC,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,SACf,CAAC;AAEtC,eAAO,MAAM,kBAAkB,GAC7B,aAAa,WAAW,EAAE,EAC1B,SAAS,WAAW,EACpB,WAAW,MAAM,GAAG,MAAM,KACzB,WAAW,GAAG,SAkBhB,CAAC;AAMF,eAAO,MAAM,oBAAoB,GAC/B,aAAa,WAAW,EAAE,EAC1B,SAAS,WAAW,EACpB,WAAW,MAAM,GAAG,MAAM,KACzB,WAAW,GAAG,SAQhB,CAAC;AAmBF,eAAO,MAAM,mBAAmB,GAC9B,SAAS,WAAW,EAAE,EACtB,SAAS,WAAW,EAAE,kBAgBvB,CAAC"}
|
|
@@ -242,6 +242,67 @@ onSearchMessageRevoked) => {
|
|
|
242
242
|
}, {
|
|
243
243
|
manual: true,
|
|
244
244
|
});
|
|
245
|
+
// For a viewer who gets no pushes (non-member of a public group): re-read the
|
|
246
|
+
// newest page(s), walking back until they overlap the shown list so a burst of
|
|
247
|
+
// new messages never leaves a gap.
|
|
248
|
+
const pageLoadingRef = useLatest(moreOldLoading || moreNewLoading);
|
|
249
|
+
const refreshLatestMessages = async () => {
|
|
250
|
+
const state = latestLoadState.current;
|
|
251
|
+
// A jumped-to window (hasMoreNew) hides the newest messages on purpose; a
|
|
252
|
+
// page load in flight would race the merge below, so wait for the next poll.
|
|
253
|
+
if (!state ||
|
|
254
|
+
!canLoadRef.current ||
|
|
255
|
+
state.initLoading ||
|
|
256
|
+
state.hasMoreNew ||
|
|
257
|
+
pageLoadingRef.current) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const reqConversationID = conversationId;
|
|
261
|
+
const reqUseAppHistory = useAppHistory;
|
|
262
|
+
if (!reqConversationID)
|
|
263
|
+
return;
|
|
264
|
+
const shown = new Set(state.messageList.map((msg) => msg.clientMsgID));
|
|
265
|
+
const fetched = [];
|
|
266
|
+
let bridged = shown.size === 0;
|
|
267
|
+
let startClientMsgID = "";
|
|
268
|
+
for (let page = 0; page < MAX_REFRESH_PAGES; page++) {
|
|
269
|
+
const params = {
|
|
270
|
+
count: PAGE_SIZE.large,
|
|
271
|
+
startClientMsgID,
|
|
272
|
+
conversationID: reqConversationID,
|
|
273
|
+
viewType: ViewType.History,
|
|
274
|
+
};
|
|
275
|
+
const { data } = reqUseAppHistory
|
|
276
|
+
? await DChatSDK.getAdvancedHistoryMessageListApp(params)
|
|
277
|
+
: await DChatSDK.getAdvancedHistoryMessageList(params);
|
|
278
|
+
if (isStaleResponse(reqConversationID, reqUseAppHistory))
|
|
279
|
+
return;
|
|
280
|
+
const newestFirst = data.messageList.toReversed();
|
|
281
|
+
fetched.push(...newestFirst);
|
|
282
|
+
if (newestFirst.some((msg) => shown.has(msg.clientMsgID))) {
|
|
283
|
+
bridged = true;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
if (data.isEnd || newestFirst.length === 0) {
|
|
287
|
+
bridged = true;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
startClientMsgID = newestFirst[newestFirst.length - 1].clientMsgID;
|
|
291
|
+
}
|
|
292
|
+
setLoadState((preState) => {
|
|
293
|
+
// More new messages than we walked back: show the fresh pages alone
|
|
294
|
+
// rather than a list with a hole in it; older ones load on scroll.
|
|
295
|
+
if (!bridged) {
|
|
296
|
+
if (pageLoadingRef.current)
|
|
297
|
+
return preState;
|
|
298
|
+
return Object.assign(Object.assign({}, preState), { hasMoreOld: true, messageList: fetched });
|
|
299
|
+
}
|
|
300
|
+
const messageList = mergeLatestMessages(preState.messageList, fetched);
|
|
301
|
+
return messageList === preState.messageList
|
|
302
|
+
? preState
|
|
303
|
+
: Object.assign(Object.assign({}, preState), { messageList });
|
|
304
|
+
});
|
|
305
|
+
};
|
|
245
306
|
useEffect(() => {
|
|
246
307
|
const pushNewMessage = (message) => {
|
|
247
308
|
var _a, _b;
|
|
@@ -335,6 +396,7 @@ onSearchMessageRevoked) => {
|
|
|
335
396
|
getMoreOldMessages,
|
|
336
397
|
moreNewLoading,
|
|
337
398
|
getMoreNewMessages,
|
|
399
|
+
refreshLatestMessages,
|
|
338
400
|
};
|
|
339
401
|
};
|
|
340
402
|
export const pushNewMessage = (message) => emit("PUSH_NEW_MSG", message);
|
|
@@ -376,6 +438,28 @@ const removeDuplicateMessages = (messages) => {
|
|
|
376
438
|
return true;
|
|
377
439
|
});
|
|
378
440
|
};
|
|
441
|
+
// How far refreshLatestMessages walks back to meet the shown list.
|
|
442
|
+
const MAX_REFRESH_PAGES = 3;
|
|
443
|
+
// Server copies replace shown ones whose type changed (a revoke becomes its
|
|
444
|
+
// placeholder); new ones are placed by sendTime like pushNewMessage does.
|
|
445
|
+
// Returns `current` itself when nothing changed, so React can skip the render.
|
|
446
|
+
export const mergeLatestMessages = (current, fetched) => {
|
|
447
|
+
const unseen = new Map(fetched.map((msg) => [msg.clientMsgID, msg]));
|
|
448
|
+
let changed = false;
|
|
449
|
+
const kept = current.map((msg) => {
|
|
450
|
+
const fresh = unseen.get(msg.clientMsgID);
|
|
451
|
+
if (!fresh)
|
|
452
|
+
return msg;
|
|
453
|
+
unseen.delete(msg.clientMsgID);
|
|
454
|
+
if (fresh.contentType === msg.contentType)
|
|
455
|
+
return msg;
|
|
456
|
+
changed = true;
|
|
457
|
+
return Object.assign(Object.assign({}, msg), fresh);
|
|
458
|
+
});
|
|
459
|
+
if (unseen.size === 0 && !changed)
|
|
460
|
+
return current;
|
|
461
|
+
return [...unseen.values(), ...kept].sort((a, b) => (b.sendTime || 0) - (a.sendTime || 0));
|
|
462
|
+
};
|
|
379
463
|
// Merges `base` with `incoming`, keeping each message at the position of its
|
|
380
464
|
// first occurrence but letting `incoming` (the later/authoritative source,
|
|
381
465
|
// e.g. a fresh server fetch) overwrite the content of any duplicate.
|
|
@@ -7,6 +7,7 @@ interface UseSearchGroupsParams {
|
|
|
7
7
|
pageSize?: number;
|
|
8
8
|
scope?: SearchScope;
|
|
9
9
|
}
|
|
10
|
+
export declare const buildSearchedGroupConversation: (group: IConversationGroupItem) => import("@droppii-org/wasm-client-sdk").ConversationItem;
|
|
10
11
|
export declare const useSearchGroups: ({ searchTerm, enabled, pageSize, scope, }: UseSearchGroupsParams) => {
|
|
11
12
|
groups: ConversationGroupDisplayItem[];
|
|
12
13
|
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<import("@tanstack/react-query").InfiniteData<BaseResponse<IConversationGroupItem[]>, unknown>, Error>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSearchGroups.d.ts","sourceRoot":"","sources":["../../../src/hooks/search/useSearchGroups.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGnE,OAAO,EAGL,KAAK,4BAA4B,EAClC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"useSearchGroups.d.ts","sourceRoot":"","sources":["../../../src/hooks/search/useSearchGroups.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAGnE,OAAO,EAGL,KAAK,4BAA4B,EAClC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,UAAU,qBAAqB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAID,eAAO,MAAM,8BAA8B,GAAI,OAAO,sBAAsB,4DAQ3E,CAAC;AA4BF,eAAO,MAAM,eAAe,GAAI,2CAK7B,qBAAqB;;;;;;CAmEvB,CAAC"}
|
|
@@ -8,6 +8,16 @@ import { PAGE_SIZE } from "../../constants";
|
|
|
8
8
|
import useAuthStore from "../../store/auth";
|
|
9
9
|
import useConversationStore from "../../store/conversation";
|
|
10
10
|
import { buildFallbackConversation, syncGroupConversationsToStore, } from "../../hooks/group/useConversationGroups";
|
|
11
|
+
import { PeerType } from "../../types/conversation";
|
|
12
|
+
// A searched group the viewer isn't in never syncs, so this is all it gets. Real
|
|
13
|
+
// groups carry visibility; mark them so the view-only/block checks run on open.
|
|
14
|
+
export const buildSearchedGroupConversation = (group) => {
|
|
15
|
+
const conversation = buildFallbackConversation(group);
|
|
16
|
+
const isRealGroup = group.visibility !== undefined &&
|
|
17
|
+
!group.conversationId.startsWith("sg_bot_");
|
|
18
|
+
return isRealGroup
|
|
19
|
+
? Object.assign(Object.assign({}, conversation), { peerType: PeerType.GROUP }) : conversation;
|
|
20
|
+
};
|
|
11
21
|
const fetchGroupsPage = (scope, page, pageSize, searchTerm) => {
|
|
12
22
|
if (scope === "pdp-portal") {
|
|
13
23
|
// Joined groups only, already limited to the PDP account by BE.
|
|
@@ -60,7 +70,7 @@ export const useSearchGroups = ({ searchTerm, enabled = true, pageSize = PAGE_SI
|
|
|
60
70
|
return {
|
|
61
71
|
groupId: group.groupId,
|
|
62
72
|
conversationId: group.conversationId,
|
|
63
|
-
conversation: syncedConversation !== null && syncedConversation !== void 0 ? syncedConversation :
|
|
73
|
+
conversation: syncedConversation !== null && syncedConversation !== void 0 ? syncedConversation : buildSearchedGroupConversation(group),
|
|
64
74
|
visibility: group.visibility,
|
|
65
75
|
memberCount: group.memberCount,
|
|
66
76
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/store/conversation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/store/conversation.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAY3C,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,SAElD,CAAC;AAUF,eAAO,MAAM,cAAc,GAAI,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,SAEhE,CAAC;AAEF,QAAA,MAAM,oBAAoB,gFAuhBvB,CAAC;AAEJ,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { GroupStatus, GroupVisibility, SessionType, } from "@droppii-org/wasm-client-sdk";
|
|
2
2
|
import { create } from "zustand";
|
|
3
|
+
import isEqual from "lodash/isEqual";
|
|
3
4
|
import { DChatSDK } from "../constants/sdk";
|
|
4
5
|
import { conversationSort } from "../utils/imCommon";
|
|
5
6
|
import { PeerType } from "../types/conversation";
|
|
@@ -411,6 +412,78 @@ const useConversationStore = create((set, get) => ({
|
|
|
411
412
|
setSelfLeftGroupID: (groupID) => set({ selfLeftGroupID: groupID }),
|
|
412
413
|
isViewOnlyMember: false,
|
|
413
414
|
setIsViewOnlyMember: (value) => set({ isViewOnlyMember: value }),
|
|
415
|
+
refreshViewOnlyGroup: async (groupID) => {
|
|
416
|
+
var _a;
|
|
417
|
+
let group;
|
|
418
|
+
let isJoined = false;
|
|
419
|
+
try {
|
|
420
|
+
const [{ data }, joined] = await Promise.all([
|
|
421
|
+
DChatSDK.getSpecifiedGroupsInfo([groupID]),
|
|
422
|
+
DChatSDK.isJoinGroup(groupID)
|
|
423
|
+
.then((result) => Boolean(result.data))
|
|
424
|
+
.catch(() => false),
|
|
425
|
+
]);
|
|
426
|
+
group = data === null || data === void 0 ? void 0 : data[0];
|
|
427
|
+
isJoined = joined;
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
// A failed poll proves nothing about the group; keep the last data.
|
|
431
|
+
console.error("refreshViewOnlyGroup", error);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const { conversationData, isViewOnlyMember } = get();
|
|
435
|
+
// Joined, switched thread or closed while the request was in flight.
|
|
436
|
+
if (!isViewOnlyMember || (conversationData === null || conversationData === void 0 ? void 0 : conversationData.groupID) !== groupID)
|
|
437
|
+
return;
|
|
438
|
+
if (!group || group.status === GroupStatus.Dismissed) {
|
|
439
|
+
get().clearSelectedConversation();
|
|
440
|
+
get().showRemovedFromGroupModal();
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
// Being added by an admin can sync as a group update instead of
|
|
444
|
+
// OnJoinedGroupAdded (the row was cached while viewing), so catch it here.
|
|
445
|
+
// Member mode waits for the member record; until then the next poll retries.
|
|
446
|
+
if (isJoined) {
|
|
447
|
+
set({ nonMemberGroupID: null });
|
|
448
|
+
await get().getCurrentMemberInGroupByReq(groupID);
|
|
449
|
+
const latestState = get();
|
|
450
|
+
if (!latestState.isViewOnlyMember ||
|
|
451
|
+
((_a = latestState.conversationData) === null || _a === void 0 ? void 0 : _a.groupID) !== groupID) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (!latestState.currentMemberInGroup.has(groupID)) {
|
|
455
|
+
// Not a member yet after all: put the kick-guard back.
|
|
456
|
+
set({ nonMemberGroupID: groupID });
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
set({ isViewOnlyMember: false });
|
|
460
|
+
// Not awaited: the self-permission call can stall right after a join.
|
|
461
|
+
void get().getSelfGroupPermissionByReq(groupID);
|
|
462
|
+
void get().getCurrentGroupInfoByReq(groupID);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
if (group.visibility !== GroupVisibility.Public) {
|
|
466
|
+
get().clearSelectedConversation();
|
|
467
|
+
get().showRemovedFromGroupModal();
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const latest = group;
|
|
471
|
+
set((state) => {
|
|
472
|
+
const isSameInfo = isEqual(state.currentGroupInfo.get(groupID), latest);
|
|
473
|
+
const isSameHeader = conversationData.showName === latest.groupName &&
|
|
474
|
+
conversationData.faceURL === latest.faceURL;
|
|
475
|
+
if (isSameInfo && isSameHeader)
|
|
476
|
+
return state;
|
|
477
|
+
return Object.assign({
|
|
478
|
+
// Set directly: getCurrentGroupInfoByReq's kick-guard skips groups the
|
|
479
|
+
// viewer has left, which is exactly who reaches this view.
|
|
480
|
+
currentGroupInfo: new Map(state.currentGroupInfo).set(groupID, Object.assign({}, latest)) }, (isSameHeader
|
|
481
|
+
? {}
|
|
482
|
+
: {
|
|
483
|
+
conversationData: Object.assign(Object.assign({}, conversationData), { showName: latest.groupName, faceURL: latest.faceURL }),
|
|
484
|
+
}));
|
|
485
|
+
});
|
|
486
|
+
},
|
|
414
487
|
nonMemberGroupID: null,
|
|
415
488
|
setNonMemberGroupID: (groupID) => set({ nonMemberGroupID: groupID }),
|
|
416
489
|
disbandedGroupID: null,
|
package/dist/store/type.d.ts
CHANGED
|
@@ -96,6 +96,7 @@ export interface ConversationStore {
|
|
|
96
96
|
setSelfLeftGroupID: (groupID: string | null) => void;
|
|
97
97
|
isViewOnlyMember: boolean;
|
|
98
98
|
setIsViewOnlyMember: (value: boolean) => void;
|
|
99
|
+
refreshViewOnlyGroup: (groupID: string) => Promise<void>;
|
|
99
100
|
nonMemberGroupID: string | null;
|
|
100
101
|
setNonMemberGroupID: (groupID: string | null) => void;
|
|
101
102
|
disbandedGroupID: string | null;
|
package/dist/store/type.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../src/store/type.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../src/store/type.ts"],"names":[],"mappings":"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"}
|