@droppii-org/chat-sdk 0.6.37 → 0.6.39
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/assets/images/stickerInvalid.png +0 -0
- package/dist/components/conversation-detail/ConversationDetailInput.d.ts +3 -1
- package/dist/components/conversation-detail/ConversationDetailInput.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationDetailInput.js +32 -5
- package/dist/components/conversation-detail/TypingIndicatorBar.d.ts +10 -0
- package/dist/components/conversation-detail/TypingIndicatorBar.d.ts.map +1 -0
- package/dist/components/conversation-detail/TypingIndicatorBar.js +24 -0
- package/dist/components/conversation-detail/sticker-picker/StickerCategoryTabs.d.ts +9 -0
- package/dist/components/conversation-detail/sticker-picker/StickerCategoryTabs.d.ts.map +1 -0
- package/dist/components/conversation-detail/sticker-picker/StickerCategoryTabs.js +38 -0
- package/dist/components/conversation-detail/sticker-picker/StickerPicker.d.ts +7 -0
- package/dist/components/conversation-detail/sticker-picker/StickerPicker.d.ts.map +1 -0
- package/dist/components/conversation-detail/sticker-picker/StickerPicker.js +113 -0
- package/dist/components/conversation-detail/sticker-picker/StickerSection.d.ts +12 -0
- package/dist/components/conversation-detail/sticker-picker/StickerSection.d.ts.map +1 -0
- package/dist/components/conversation-detail/sticker-picker/StickerSection.js +46 -0
- package/dist/components/conversation-detail/sticker-picker/constants.d.ts +8 -0
- package/dist/components/conversation-detail/sticker-picker/constants.d.ts.map +1 -0
- package/dist/components/conversation-detail/sticker-picker/constants.js +1 -0
- package/dist/components/message/item/StickerMessage.d.ts.map +1 -1
- package/dist/components/message/item/StickerMessage.js +3 -5
- package/dist/components/message/reply/ReplyPreviewMedia.d.ts.map +1 -1
- package/dist/components/message/reply/ReplyPreviewMedia.js +8 -2
- package/dist/constants/images.d.ts +1 -0
- package/dist/constants/images.d.ts.map +1 -1
- package/dist/constants/images.js +2 -0
- package/dist/context/ChatContext.d.ts.map +1 -1
- package/dist/context/ChatContext.js +1 -1
- package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
- package/dist/hooks/global/useGlobalEvent.js +10 -1
- package/dist/hooks/message/useReportTypingState.d.ts +10 -0
- package/dist/hooks/message/useReportTypingState.d.ts.map +1 -0
- package/dist/hooks/message/useReportTypingState.js +73 -0
- package/dist/hooks/message/useSendMessage.d.ts +7 -1
- package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
- package/dist/hooks/message/useSendMessage.js +45 -2
- package/dist/hooks/message/useTypingStatus.d.ts +11 -0
- package/dist/hooks/message/useTypingStatus.d.ts.map +1 -0
- package/dist/hooks/message/useTypingStatus.js +120 -0
- package/dist/hooks/sticker/useStickers.d.ts +5 -0
- package/dist/hooks/sticker/useStickers.d.ts.map +1 -0
- package/dist/hooks/sticker/useStickers.js +39 -0
- package/dist/hooks/user/useAuth.d.ts.map +1 -1
- package/dist/hooks/user/useAuth.js +2 -0
- package/dist/locales/vi/conversation-inbox.json +11 -0
- package/dist/screens/conversation-detail/index.d.ts.map +1 -1
- package/dist/screens/conversation-detail/index.js +2 -1
- package/dist/screens/conversation-inbox/index.d.ts +2 -0
- package/dist/screens/conversation-inbox/index.d.ts.map +1 -1
- package/dist/screens/conversation-inbox/index.js +2 -2
- package/dist/services/query.d.ts +3 -0
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +3 -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/store/typing.d.ts +13 -0
- package/dist/store/typing.d.ts.map +1 -0
- package/dist/store/typing.js +63 -0
- package/dist/styles/global.css +1 -1
- package/dist/types/chat.d.ts +1 -0
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/types/sticker.d.ts +20 -0
- package/dist/types/sticker.d.ts.map +1 -0
- package/dist/types/sticker.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReportTypingState.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useReportTypingState.ts"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAI,gBAAgB,MAAM;oCAoCvC,MAAM;;CA6BzB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
import { DChatSDK } from "../../constants/sdk";
|
|
3
|
+
// Keep-alive rate while typing; receivers drop a typer after 3s of silence.
|
|
4
|
+
const TYPING_REPORT_INTERVAL_MS = 2000;
|
|
5
|
+
// Business rule: no activity for 3s means the participant stopped typing.
|
|
6
|
+
const TYPING_IDLE_TIMEOUT_MS = 3000;
|
|
7
|
+
// Core forwards one "typing" per window and drops a "stop" once it lapses;
|
|
8
|
+
// assuming 2s is safe with the old 10s core too, it only adds a deduped resend.
|
|
9
|
+
const CORE_SEND_WINDOW_MS = 2000;
|
|
10
|
+
const changeInputState = (conversationId, focus) => {
|
|
11
|
+
var _a;
|
|
12
|
+
return ((_a = DChatSDK === null || DChatSDK === void 0 ? void 0 : DChatSDK.changeInputStates({ conversationID: conversationId, focus })) !== null && _a !== void 0 ? _a : Promise.resolve()).catch((error) => console.error("changeInputStates", error));
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Reports the viewer's own composer activity for `conversationId` so other
|
|
16
|
+
* participants see a typing indicator. `reportActivity` on every edit,
|
|
17
|
+
* `stopTyping` when the composer is cleared, blurred or the message is sent.
|
|
18
|
+
*/
|
|
19
|
+
export const useReportTypingState = (conversationId) => {
|
|
20
|
+
const isTypingRef = useRef(false);
|
|
21
|
+
// When core last actually forwarded "typing" (not deduped by it).
|
|
22
|
+
const coreSentAtRef = useRef(0);
|
|
23
|
+
const lastReportAtRef = useRef(0);
|
|
24
|
+
const idleTimerRef = useRef();
|
|
25
|
+
const conversationIdRef = useRef(conversationId);
|
|
26
|
+
const sendTyping = useCallback((targetId) => {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
if (now - coreSentAtRef.current >= CORE_SEND_WINDOW_MS) {
|
|
29
|
+
coreSentAtRef.current = now;
|
|
30
|
+
}
|
|
31
|
+
lastReportAtRef.current = now;
|
|
32
|
+
void changeInputState(targetId, true);
|
|
33
|
+
}, []);
|
|
34
|
+
const stopTyping = useCallback(() => {
|
|
35
|
+
clearTimeout(idleTimerRef.current);
|
|
36
|
+
if (!isTypingRef.current)
|
|
37
|
+
return;
|
|
38
|
+
isTypingRef.current = false;
|
|
39
|
+
lastReportAtRef.current = 0;
|
|
40
|
+
const targetId = conversationIdRef.current;
|
|
41
|
+
if (!targetId)
|
|
42
|
+
return;
|
|
43
|
+
const windowLapsed = Date.now() - coreSentAtRef.current >= CORE_SEND_WINDOW_MS;
|
|
44
|
+
coreSentAtRef.current = 0;
|
|
45
|
+
// Re-open core's window first so the stop is actually sent.
|
|
46
|
+
const reopen = windowLapsed
|
|
47
|
+
? changeInputState(targetId, true)
|
|
48
|
+
: Promise.resolve();
|
|
49
|
+
void reopen.then(() => changeInputState(targetId, false));
|
|
50
|
+
}, []);
|
|
51
|
+
const reportActivity = useCallback((composerValue) => {
|
|
52
|
+
const targetId = conversationIdRef.current;
|
|
53
|
+
if (!targetId)
|
|
54
|
+
return;
|
|
55
|
+
if (!composerValue.trim()) {
|
|
56
|
+
stopTyping();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!isTypingRef.current ||
|
|
60
|
+
Date.now() - lastReportAtRef.current >= TYPING_REPORT_INTERVAL_MS) {
|
|
61
|
+
isTypingRef.current = true;
|
|
62
|
+
sendTyping(targetId);
|
|
63
|
+
}
|
|
64
|
+
clearTimeout(idleTimerRef.current);
|
|
65
|
+
idleTimerRef.current = setTimeout(stopTyping, TYPING_IDLE_TIMEOUT_MS);
|
|
66
|
+
}, [sendTyping, stopTyping]);
|
|
67
|
+
// Switching threads or unmounting ends typing in the thread being left.
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
conversationIdRef.current = conversationId;
|
|
70
|
+
return stopTyping;
|
|
71
|
+
}, [conversationId, stopTyping]);
|
|
72
|
+
return { reportActivity, stopTyping };
|
|
73
|
+
};
|
|
@@ -3,6 +3,7 @@ import { type CustomMessagePayload } from "../../types/customMessage";
|
|
|
3
3
|
import { BotFlowMeta, ExtendMessageInfo, FileMsgParamsByFile, ImageMsgParamsByFile, MentionOffset, MentionSendPayload, UrlMetadataInfo, VideoMsgParamsByFile } from "../../types/chat";
|
|
4
4
|
import { UploadFile } from "antd";
|
|
5
5
|
import { ISessionResponse } from "../../types/dto";
|
|
6
|
+
import type { StickerItem } from "../../types/sticker";
|
|
6
7
|
export declare const isMediaResendable: (message: {
|
|
7
8
|
clientMsgID: string;
|
|
8
9
|
contentType: number;
|
|
@@ -15,6 +16,7 @@ export declare const createFileMessageByFile: (file: FileMsgParamsByFile) => Pro
|
|
|
15
16
|
export declare const AT_ALL_TAG = "AtAllTag";
|
|
16
17
|
export declare const createAtTextMessage: (params: AtMsgParams) => Promise<MessageItem | null>;
|
|
17
18
|
export declare const createUrlTextMessage: (text: string, urls: string[]) => Promise<MessageItem | null>;
|
|
19
|
+
export declare const createStickerMessage: (stickerUrl: string) => Promise<MessageItem | null>;
|
|
18
20
|
export declare const createCustomMessageByParams: (params: CustomMsgParams) => Promise<MessageItem | null>;
|
|
19
21
|
export declare const createCustomMessage: (payload: CustomMessagePayload) => Promise<MessageItem | null>;
|
|
20
22
|
export declare const createQuoteMessage: (text: string, quotedMessage: MessageItem, urls?: string[]) => Promise<MessageItem | null>;
|
|
@@ -37,13 +39,17 @@ export declare const useSendMessage: (options?: UseSendMessageOptions) => {
|
|
|
37
39
|
sendCustomMessage: (payload: CustomMessagePayload, sendOptions?: {
|
|
38
40
|
currentSession?: ISessionResponse;
|
|
39
41
|
}) => Promise<boolean>;
|
|
42
|
+
sendStickerMessage: (sticker: StickerItem, sendOptions?: {
|
|
43
|
+
currentSession?: ISessionResponse;
|
|
44
|
+
}) => Promise<boolean>;
|
|
40
45
|
resendMessage: (failedMessage: MessageItem) => Promise<void>;
|
|
41
46
|
};
|
|
42
|
-
export declare const generateExtendMessageInfo: ({ richText, urlMetadata, currentSession, flow, mentionOffsets, }: {
|
|
47
|
+
export declare const generateExtendMessageInfo: ({ richText, urlMetadata, currentSession, flow, mentionOffsets, stickerId, }: {
|
|
43
48
|
richText?: string;
|
|
44
49
|
urlMetadata?: UrlMetadataInfo;
|
|
45
50
|
currentSession?: ISessionResponse;
|
|
46
51
|
flow?: BotFlowMeta;
|
|
47
52
|
mentionOffsets?: MentionOffset[];
|
|
53
|
+
stickerId?: string;
|
|
48
54
|
}) => ExtendMessageInfo;
|
|
49
55
|
//# sourceMappingURL=useSendMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,eAAe,EACf,eAAe,EACf,WAAW,EAIZ,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAWtB,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAQlC,OAAO,EAEL,gBAAgB,EAEjB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendMessage.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ import { SessionStatus, SessionTag } from "../../types/chat";
|
|
|
17
17
|
import { updateSession } from "../../hooks/session/useUpdateSession";
|
|
18
18
|
import { invalidateSessionQueries } from "../../utils/queryHelpers";
|
|
19
19
|
import { resolveConversationBotId } from "../../utils/conversation";
|
|
20
|
+
import { QUERY_KEYS } from "../../services/query";
|
|
20
21
|
const messageFileStore = new Map();
|
|
21
22
|
const MEDIA_CONTENT_TYPES = new Set([
|
|
22
23
|
MessageType.PictureMessage,
|
|
@@ -104,6 +105,17 @@ export const createUrlTextMessage = async (text, urls) => {
|
|
|
104
105
|
});
|
|
105
106
|
return textMessage;
|
|
106
107
|
};
|
|
108
|
+
export const createStickerMessage = async (stickerUrl) => {
|
|
109
|
+
const stickerMessage = await DChatSDK.createStickerMessage(stickerUrl, uuidv4())
|
|
110
|
+
.then(({ data }) => {
|
|
111
|
+
return data;
|
|
112
|
+
})
|
|
113
|
+
.catch(({ errCode, errMsg }) => {
|
|
114
|
+
console.error("createStickerMessage", errCode, errMsg);
|
|
115
|
+
return null;
|
|
116
|
+
});
|
|
117
|
+
return stickerMessage;
|
|
118
|
+
};
|
|
107
119
|
export const createCustomMessageByParams = async (params) => {
|
|
108
120
|
const customMessage = await DChatSDK.createCustomMessage(params, new Date().getTime().toString())
|
|
109
121
|
.then(({ data }) => {
|
|
@@ -242,7 +254,7 @@ export const useSendMessage = (options) => {
|
|
|
242
254
|
}
|
|
243
255
|
}, [dispatchMessage, scrollEvent]);
|
|
244
256
|
const resendMessage = useCallback(async (failedMessage) => {
|
|
245
|
-
var _a;
|
|
257
|
+
var _a, _b;
|
|
246
258
|
const storedFiles = messageFileStore.get(failedMessage.clientMsgID);
|
|
247
259
|
if (!storedFiles) {
|
|
248
260
|
let newTextPayload = null;
|
|
@@ -260,6 +272,11 @@ export const useSendMessage = (options) => {
|
|
|
260
272
|
failedMessage.urlTextElem) {
|
|
261
273
|
newTextPayload = await createUrlTextMessage(textContent, failedMessage.urlTextElem.urls);
|
|
262
274
|
}
|
|
275
|
+
else if (failedMessage.contentType === MessageType.StickerMessage) {
|
|
276
|
+
newTextPayload = ((_b = failedMessage.stickerElem) === null || _b === void 0 ? void 0 : _b.content)
|
|
277
|
+
? await createStickerMessage(failedMessage.stickerElem.content)
|
|
278
|
+
: null;
|
|
279
|
+
}
|
|
263
280
|
else {
|
|
264
281
|
newTextPayload = await createTextMessage(textContent);
|
|
265
282
|
}
|
|
@@ -342,6 +359,28 @@ export const useSendMessage = (options) => {
|
|
|
342
359
|
});
|
|
343
360
|
return sendMessage(Object.assign(Object.assign({}, customMessage), { ex: JSON.stringify(extendMessageInfo) || "{}", isInternal: false }), sendOptions === null || sendOptions === void 0 ? void 0 : sendOptions.currentSession);
|
|
344
361
|
}, [conversationData, recvID, groupID, sendMessage]);
|
|
362
|
+
const sendStickerMessage = useCallback(async (sticker, sendOptions) => {
|
|
363
|
+
var _a;
|
|
364
|
+
if (!conversationData || (!recvID && !groupID))
|
|
365
|
+
return false;
|
|
366
|
+
if (!((_a = sticker.file) === null || _a === void 0 ? void 0 : _a.fullUrl))
|
|
367
|
+
return false;
|
|
368
|
+
const stickerMessage = await createStickerMessage(sticker.file.fullUrl);
|
|
369
|
+
if (!stickerMessage)
|
|
370
|
+
return false;
|
|
371
|
+
// BE records "recent stickers" only from ex.stickerId on the saved message.
|
|
372
|
+
const extendMessageInfo = generateExtendMessageInfo({
|
|
373
|
+
currentSession: sendOptions === null || sendOptions === void 0 ? void 0 : sendOptions.currentSession,
|
|
374
|
+
stickerId: sticker.id,
|
|
375
|
+
});
|
|
376
|
+
const isSent = await sendMessage(Object.assign(Object.assign({}, stickerMessage), { ex: JSON.stringify(extendMessageInfo) || "{}", isInternal: false }), sendOptions === null || sendOptions === void 0 ? void 0 : sendOptions.currentSession);
|
|
377
|
+
if (isSent) {
|
|
378
|
+
queryClient.invalidateQueries({
|
|
379
|
+
queryKey: [QUERY_KEYS.GET_STICKER_HISTORY],
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
return isSent;
|
|
383
|
+
}, [conversationData, recvID, groupID, sendMessage, queryClient]);
|
|
345
384
|
const sendMergeMessage = useCallback(async ({ richText, plainText, files = [], currentSession, isInternal, urlMetadata, flow, customMessage, mentions, }) => {
|
|
346
385
|
if (!conversationData || (!recvID && !groupID))
|
|
347
386
|
return false;
|
|
@@ -535,14 +574,18 @@ export const useSendMessage = (options) => {
|
|
|
535
574
|
return {
|
|
536
575
|
sendMergeMessage,
|
|
537
576
|
sendCustomMessage,
|
|
577
|
+
sendStickerMessage,
|
|
538
578
|
resendMessage,
|
|
539
579
|
};
|
|
540
580
|
};
|
|
541
|
-
export const generateExtendMessageInfo = ({ richText, urlMetadata, currentSession, flow, mentionOffsets, }) => {
|
|
581
|
+
export const generateExtendMessageInfo = ({ richText, urlMetadata, currentSession, flow, mentionOffsets, stickerId, }) => {
|
|
542
582
|
const extendMessageInfo = {
|
|
543
583
|
sessionId: (currentSession === null || currentSession === void 0 ? void 0 : currentSession.id) || "",
|
|
544
584
|
applicationType: useAuthStore.getState().applicationType,
|
|
545
585
|
};
|
|
586
|
+
if (stickerId) {
|
|
587
|
+
extendMessageInfo.stickerId = stickerId;
|
|
588
|
+
}
|
|
546
589
|
if (flow) {
|
|
547
590
|
extendMessageInfo.flow = flow;
|
|
548
591
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConversationInputStatus, MessageItem } from "@droppii-org/wasm-client-sdk";
|
|
2
|
+
export declare const handleInputStatusChanged: (payload: ConversationInputStatus | string) => void;
|
|
3
|
+
/** A typer's own message landing ends their typing state right away. */
|
|
4
|
+
export declare const removeTyperOnNewMessage: (message: MessageItem) => void;
|
|
5
|
+
export interface TypingState {
|
|
6
|
+
/** Resolved names of the first typers, only filled when count <= 2. */
|
|
7
|
+
names: string[];
|
|
8
|
+
count: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const useTypingState: (conversationId?: string) => TypingState;
|
|
11
|
+
//# sourceMappingURL=useTypingStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTypingStatus.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useTypingStatus.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,uBAAuB,EACvB,WAAW,EAEZ,MAAM,8BAA8B,CAAC;AAuEtC,eAAO,MAAM,wBAAwB,GACnC,SAAS,uBAAuB,GAAG,MAAM,SA0B1C,CAAC;AAUF,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,GAAI,SAAS,WAAW,SAK3D,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,uEAAuE;IACvE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,cAAc,GAAI,iBAAiB,MAAM,KAAG,WAkBxD,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { useTranslation } from "react-i18next";
|
|
2
|
+
import { useShallow } from "zustand/react/shallow";
|
|
3
|
+
import { SessionType, } from "@droppii-org/wasm-client-sdk";
|
|
4
|
+
import { DChatSDK } from "../../constants/sdk";
|
|
5
|
+
import useAuthStore from "../../store/auth";
|
|
6
|
+
import useConversationStore from "../../store/conversation";
|
|
7
|
+
import useTypingStore from "../../store/typing";
|
|
8
|
+
import { getGroupIdFromConversationId } from "../../utils/conversation";
|
|
9
|
+
// Two names fit the "<A> và <B>" rule; from three on the text drops names.
|
|
10
|
+
const MAX_NAMED_TYPERS = 2;
|
|
11
|
+
const pendingNameLookups = new Map();
|
|
12
|
+
// Typers whose latest event was "start"; a stop during a name lookup wins.
|
|
13
|
+
const activeTypers = new Set();
|
|
14
|
+
// Names are per conversation: group nicknames and 1:1 aliases differ by thread.
|
|
15
|
+
const nameKey = (conversationId, userId) => `${conversationId}:${userId}`;
|
|
16
|
+
const pickNickname = (list) => { var _a, _b; return ((_b = (_a = list === null || list === void 0 ? void 0 : list[0]) === null || _a === void 0 ? void 0 : _a.nickname) === null || _b === void 0 ? void 0 : _b.trim()) || ""; };
|
|
17
|
+
const lookupTyperName = async (key, conversationId, userId) => {
|
|
18
|
+
var _a;
|
|
19
|
+
const conversation = useConversationStore
|
|
20
|
+
.getState()
|
|
21
|
+
.conversationList.find((item) => item.conversationID === conversationId);
|
|
22
|
+
const peerName = (_a = conversation === null || conversation === void 0 ? void 0 : conversation.showName) === null || _a === void 0 ? void 0 : _a.trim();
|
|
23
|
+
const { setName } = useTypingStore.getState();
|
|
24
|
+
if (conversation && !conversation.groupID && peerName) {
|
|
25
|
+
setName(key, peerName);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const groupId = (conversation === null || conversation === void 0 ? void 0 : conversation.groupID) || getGroupIdFromConversationId(conversationId);
|
|
30
|
+
let nickname = "";
|
|
31
|
+
if (groupId) {
|
|
32
|
+
const { data } = await DChatSDK.getSpecifiedGroupMembersInfo({
|
|
33
|
+
groupID: groupId,
|
|
34
|
+
userIDList: [userId],
|
|
35
|
+
});
|
|
36
|
+
nickname = pickNickname(data);
|
|
37
|
+
}
|
|
38
|
+
if (!nickname) {
|
|
39
|
+
const { data } = await DChatSDK.getUsersInfo([userId]);
|
|
40
|
+
nickname = pickNickname(data);
|
|
41
|
+
}
|
|
42
|
+
if (nickname)
|
|
43
|
+
setName(key, nickname);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error("resolveTyperName", error);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
/** Settles once the name is cached or the lookup gave up (never rejects). */
|
|
50
|
+
const resolveTyperName = (conversationId, userId) => {
|
|
51
|
+
const key = nameKey(conversationId, userId);
|
|
52
|
+
if (useTypingStore.getState().names[key])
|
|
53
|
+
return Promise.resolve();
|
|
54
|
+
let pending = pendingNameLookups.get(key);
|
|
55
|
+
if (!pending) {
|
|
56
|
+
pending = lookupTyperName(key, conversationId, userId).finally(() => pendingNameLookups.delete(key));
|
|
57
|
+
pendingNameLookups.set(key, pending);
|
|
58
|
+
}
|
|
59
|
+
return pending;
|
|
60
|
+
};
|
|
61
|
+
export const handleInputStatusChanged = (payload) => {
|
|
62
|
+
var _a;
|
|
63
|
+
let data;
|
|
64
|
+
try {
|
|
65
|
+
data = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error("handleInputStatusChanged", error);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!(data === null || data === void 0 ? void 0 : data.conversationID) || !data.userID)
|
|
72
|
+
return;
|
|
73
|
+
if (data.userID === useAuthStore.getState().userID)
|
|
74
|
+
return;
|
|
75
|
+
const { conversationID, userID } = data;
|
|
76
|
+
const key = nameKey(conversationID, userID);
|
|
77
|
+
if ((_a = data.platformIDs) === null || _a === void 0 ? void 0 : _a.length) {
|
|
78
|
+
activeTypers.add(key);
|
|
79
|
+
// Shown only once named, so a placeholder name never flashes first.
|
|
80
|
+
void resolveTyperName(conversationID, userID).then(() => {
|
|
81
|
+
if (activeTypers.has(key)) {
|
|
82
|
+
useTypingStore.getState().addTyper(conversationID, userID);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
activeTypers.delete(key);
|
|
88
|
+
useTypingStore.getState().removeTyper(conversationID, userID);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
// Mirrors OpenIM's conversationID scheme: si_<sorted user ids> / sg_<groupID>.
|
|
92
|
+
const getConversationIdFromMessage = (message) => {
|
|
93
|
+
if (message.sessionType === SessionType.Single) {
|
|
94
|
+
return `si_${[message.sendID, message.recvID].sort().join("_")}`;
|
|
95
|
+
}
|
|
96
|
+
return message.groupID ? `sg_${message.groupID}` : "";
|
|
97
|
+
};
|
|
98
|
+
/** A typer's own message landing ends their typing state right away. */
|
|
99
|
+
export const removeTyperOnNewMessage = (message) => {
|
|
100
|
+
const conversationId = getConversationIdFromMessage(message);
|
|
101
|
+
if (!conversationId || !message.sendID)
|
|
102
|
+
return;
|
|
103
|
+
activeTypers.delete(nameKey(conversationId, message.sendID));
|
|
104
|
+
useTypingStore.getState().removeTyper(conversationId, message.sendID);
|
|
105
|
+
};
|
|
106
|
+
export const useTypingState = (conversationId) => {
|
|
107
|
+
const { t } = useTranslation("conversation-inbox");
|
|
108
|
+
const count = useTypingStore((state) => { var _a, _b; return conversationId ? ((_b = (_a = state.typers[conversationId]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) : 0; });
|
|
109
|
+
// Only the named typers' entries, so unrelated name lookups don't re-render.
|
|
110
|
+
const resolvedNames = useTypingStore(useShallow((state) => {
|
|
111
|
+
const typers = conversationId ? state.typers[conversationId] : undefined;
|
|
112
|
+
if (!typers || typers.length > MAX_NAMED_TYPERS)
|
|
113
|
+
return [];
|
|
114
|
+
return typers.map((userId) => state.names[nameKey(conversationId, userId)]);
|
|
115
|
+
}));
|
|
116
|
+
return {
|
|
117
|
+
names: resolvedNames.map((name) => name || t("thread_card.fallback_name")),
|
|
118
|
+
count,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { StickerCategory, StickerItem } from "../../types/sticker";
|
|
2
|
+
export declare const useStickerCategories: () => import("@tanstack/react-query").UseQueryResult<StickerCategory[], Error>;
|
|
3
|
+
export declare const useStickersByCategory: (categoryId: string, enabled: boolean) => import("@tanstack/react-query").UseQueryResult<StickerItem[], Error>;
|
|
4
|
+
export declare const useStickerHistory: () => import("@tanstack/react-query").UseQueryResult<StickerItem[], Error>;
|
|
5
|
+
//# sourceMappingURL=useStickers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStickers.d.ts","sourceRoot":"","sources":["../../../src/hooks/sticker/useStickers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA2BpE,eAAO,MAAM,oBAAoB,gFAK7B,CAAC;AAEL,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,EAAE,SAAS,OAAO,yEAMtE,CAAC;AAIL,eAAO,MAAM,iBAAiB,4EAM1B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useQuery } from "@tanstack/react-query";
|
|
2
|
+
import { apiInstance } from "../../services/api";
|
|
3
|
+
import { ENDPOINTS } from "../../services/routes";
|
|
4
|
+
import { QUERY_KEYS } from "../../services/query";
|
|
5
|
+
const STICKER_LIST_STALE_TIME = 5 * 60 * 1000;
|
|
6
|
+
const fetchStickerCategories = async () => {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
const response = await apiInstance.get(ENDPOINTS.chatService.getStickerCategories);
|
|
9
|
+
return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
|
|
10
|
+
};
|
|
11
|
+
const fetchStickersByCategory = async (categoryId) => {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const response = await apiInstance.get(ENDPOINTS.chatService.getStickersByCategory(categoryId));
|
|
14
|
+
return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
|
|
15
|
+
};
|
|
16
|
+
const fetchStickerHistory = async () => {
|
|
17
|
+
var _a, _b;
|
|
18
|
+
const response = await apiInstance.get(ENDPOINTS.chatService.getStickerHistory);
|
|
19
|
+
return (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
|
|
20
|
+
};
|
|
21
|
+
export const useStickerCategories = () => useQuery({
|
|
22
|
+
queryKey: [QUERY_KEYS.GET_STICKER_CATEGORIES],
|
|
23
|
+
queryFn: fetchStickerCategories,
|
|
24
|
+
staleTime: STICKER_LIST_STALE_TIME,
|
|
25
|
+
});
|
|
26
|
+
export const useStickersByCategory = (categoryId, enabled) => useQuery({
|
|
27
|
+
queryKey: [QUERY_KEYS.GET_STICKERS_BY_CATEGORY, categoryId],
|
|
28
|
+
queryFn: () => fetchStickersByCategory(categoryId),
|
|
29
|
+
enabled: enabled && !!categoryId,
|
|
30
|
+
staleTime: STICKER_LIST_STALE_TIME,
|
|
31
|
+
});
|
|
32
|
+
// BE writes history from a message webhook after the send settles, so a
|
|
33
|
+
// cached copy goes stale on every send — always refetch when the picker opens.
|
|
34
|
+
export const useStickerHistory = () => useQuery({
|
|
35
|
+
queryKey: [QUERY_KEYS.GET_STICKER_HISTORY],
|
|
36
|
+
queryFn: fetchStickerHistory,
|
|
37
|
+
staleTime: 0,
|
|
38
|
+
gcTime: 0,
|
|
39
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../../src/hooks/user/useAuth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../../src/hooks/user/useAuth.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY;;CA6BxB,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { DChatSDK } from "../../constants/sdk";
|
|
|
3
3
|
import useAuthStore from "../../store/auth";
|
|
4
4
|
import useConversationStore from "../../store/conversation";
|
|
5
5
|
import useMessageDraftStore from "../../store/messageDraft";
|
|
6
|
+
import useTypingStore from "../../store/typing";
|
|
6
7
|
export const useDChatAuth = () => {
|
|
7
8
|
const initAuthStore = useAuthStore((state) => state.initAuthStore);
|
|
8
9
|
const resetConversationStore = useConversationStore((state) => state.resetConversationStore);
|
|
@@ -12,6 +13,7 @@ export const useDChatAuth = () => {
|
|
|
12
13
|
const applicationType = useAuthStore.getState().applicationType;
|
|
13
14
|
resetConversationStore();
|
|
14
15
|
clearAllDrafts();
|
|
16
|
+
useTypingStore.getState().clearTypers();
|
|
15
17
|
initAuthStore({
|
|
16
18
|
chatToken: "",
|
|
17
19
|
accessToken: "",
|
|
@@ -83,6 +83,12 @@
|
|
|
83
83
|
"product": "Gửi sản phẩm",
|
|
84
84
|
"appointment": "Tạo lịch hẹn"
|
|
85
85
|
},
|
|
86
|
+
"sticker": {
|
|
87
|
+
"toggle": "Nhãn dán",
|
|
88
|
+
"recent": "Gần đây",
|
|
89
|
+
"empty": "Chưa có nhãn dán",
|
|
90
|
+
"load_failed": "Không tải được nhãn dán"
|
|
91
|
+
},
|
|
86
92
|
"bot": {
|
|
87
93
|
"start": "Bắt đầu",
|
|
88
94
|
"restart": "Bắt đầu lại",
|
|
@@ -144,5 +150,10 @@
|
|
|
144
150
|
"public_group_fallback": "Nhóm công khai",
|
|
145
151
|
"group_join": "Tham gia",
|
|
146
152
|
"group_access": "Truy cập"
|
|
153
|
+
},
|
|
154
|
+
"typing": {
|
|
155
|
+
"many_label": "Nhiều người đang nhập",
|
|
156
|
+
"and": "và",
|
|
157
|
+
"suffix": "đang nhập"
|
|
147
158
|
}
|
|
148
159
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/conversation-detail/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/conversation-detail/index.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,kCAAkC,CAAC;AAWrF,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,6CAA6C,CAAC;AAGrD,MAAM,WAAW,4BACf,SAAQ,4BAA4B,EAClC,4BAA4B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB;;;OAGG;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,8IAc9B,4BAA4B,mDAsO9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -24,6 +24,7 @@ import ThreadProfilePanel from "../../components/conversation-detail/ThreadProfi
|
|
|
24
24
|
import MediaResourcePanel from "../../components/media-resources/MediaResourcePanel";
|
|
25
25
|
import { MediaResourceTabKey } from "../../components/media-resources/constants";
|
|
26
26
|
import { ConversationMessageList, ConversationDetailHeader, ConversationDetailInput, PinnedMessageBar, } from "../../components/conversation-detail";
|
|
27
|
+
import TypingIndicatorBar from "../../components/conversation-detail/TypingIndicatorBar";
|
|
27
28
|
import { BotButtonMessage, BotInactiveNotice, BotMenuSheet, BotStartButton, BotSuggest, CsSessionConfirmModal, } from "../../components/conversation-detail/bot";
|
|
28
29
|
import { useBotFlow } from "../../hooks/conversation/useBotFlow";
|
|
29
30
|
import { BOT_TYPE } from "../../constants/botFlow";
|
|
@@ -113,6 +114,6 @@ const DChatConversationDetail = (_a) => {
|
|
|
113
114
|
!botFlow.flowIsEnd &&
|
|
114
115
|
botFlow.shouldShowButtons &&
|
|
115
116
|
botFlow.currentButtonsBlock ? (_jsx(BotButtonMessage, { buttons: botFlow.currentButtonsBlock.data.buttons, disabled: botFlow.isProcessing, onSelect: botFlow.selectButton, onRestart: botFlow.restart })) : null;
|
|
116
|
-
return (_jsxs("div", { "data-testid": "conversation-detail-root", className: clsx("relative flex h-full w-full flex-col overflow-hidden bg-white", className), children: [_jsx(ConversationDetailHeader, { conversation: conversation, onBack: handleBack, onProfileClick: openProfile }), _jsx(PinnedMessageBar, {}),
|
|
117
|
+
return (_jsxs("div", { "data-testid": "conversation-detail-root", className: clsx("relative flex h-full w-full flex-col overflow-hidden bg-white", className), children: [_jsx(ConversationDetailHeader, { conversation: conversation, onBack: handleBack, onProfileClick: openProfile }), _jsx(PinnedMessageBar, {}), _jsxs("div", { className: "relative flex min-h-0 flex-1 flex-col", children: [children !== null && children !== void 0 ? children : (_jsx(ConversationMessageList, { bottomSlot: botButtonsSlot, onCopyMessageLink: onCopyMessageLink, onSearchMessageRevoked: onSearchMessageRevoked })), _jsx(TypingIndicatorBar, { conversationId: conversation.conversationID })] }), footer, isBotThread && (_jsxs(_Fragment, { children: [_jsx(BotMenuSheet, { open: isMenuOpen, items: botFlow.menuItems, disabled: botFlow.isProcessing, onClose: closeMenu, onSelect: botFlow.selectMenuOption }), _jsx(CsSessionConfirmModal, { open: botFlow.isCsConfirmOpen, loading: botFlow.isProcessing, onCancel: botFlow.cancelMenuOption, onConfirm: botFlow.confirmEndCsSession })] })), _jsx(ThreadProfilePanel, { open: isProfileOpen, conversation: conversation, onClose: closeProfile, onSelectResource: setResourceTab }), _jsx(MediaResourcePanel, { open: resourceTab !== null, initialTab: resourceTab !== null && resourceTab !== void 0 ? resourceTab : MediaResourceTabKey.Image, onClose: () => setResourceTab(null) })] }));
|
|
117
118
|
};
|
|
118
119
|
export default DChatConversationDetail;
|
|
@@ -18,6 +18,8 @@ export interface DChatConversationInboxProps {
|
|
|
18
18
|
onCopyMessageLink?: (conversationId: string, clientMsgID: string) => void;
|
|
19
19
|
/** Called instead of the SDK's default toast when a jumped-to message turns out to be revoked. */
|
|
20
20
|
onSearchMessageRevoked?: () => void;
|
|
21
|
+
/** Shows the sticker picker entry in the thread composer. Defaults to true. */
|
|
22
|
+
showSticker?: boolean;
|
|
21
23
|
}
|
|
22
24
|
declare const DChatConversationInbox: (props: DChatConversationInboxProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
25
|
export default DChatConversationInbox;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/conversation-inbox/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAM/D,MAAM,WAAW,2BAA2B;IAC1C,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,6FAA6F;IAC7F,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,yEAAyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC;;;;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;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/screens/conversation-inbox/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAM/D,MAAM,WAAW,2BAA2B;IAC1C,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC,6FAA6F;IAC7F,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,yEAAyE;IACzE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC;;;;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;IACpC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAsOD,QAAA,MAAM,sBAAsB,GAAI,OAAO,2BAA2B,4CAQjE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -77,7 +77,7 @@ const useInboxConversationList = (chatCategory) => {
|
|
|
77
77
|
const isApplicationTypeValid = Object.values(DChatApplicationType).includes(applicationType);
|
|
78
78
|
return Object.assign(Object.assign({}, useConversationList({ enabled: isApplicationTypeValid, chatCategory })), { isApplicationTypeValid });
|
|
79
79
|
};
|
|
80
|
-
const DChatConversationInboxBody = ({ onSelectThread, className, moreOptions, showSearch = true, headerTitle, headerRightSlot, onCopyMessageLink, onSearchMessageRevoked, target, conversationList, }) => {
|
|
80
|
+
const DChatConversationInboxBody = ({ onSelectThread, className, moreOptions, showSearch = true, headerTitle, headerRightSlot, onCopyMessageLink, onSearchMessageRevoked, showSticker, target, conversationList, }) => {
|
|
81
81
|
const { t } = useTranslation("conversation-inbox");
|
|
82
82
|
const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
|
|
83
83
|
const removedFromGroupModalOpen = useConversationStore((state) => state.removedFromGroupModalOpen);
|
|
@@ -99,7 +99,7 @@ const DChatConversationInboxBody = ({ onSelectThread, className, moreOptions, sh
|
|
|
99
99
|
groupId ||
|
|
100
100
|
botId);
|
|
101
101
|
if (hasConversationTarget) {
|
|
102
|
-
return (_jsx(DChatConversationDetail, { className: className, moreOptions: moreOptions, conversationId: threadId !== null && threadId !== void 0 ? threadId : undefined, userId: userId, groupId: groupId, botId: botId, onCopyMessageLink: onCopyMessageLink, onSearchMessageRevoked: onSearchMessageRevoked, messageId: messageId }));
|
|
102
|
+
return (_jsx(DChatConversationDetail, { className: className, moreOptions: moreOptions, conversationId: threadId !== null && threadId !== void 0 ? threadId : undefined, userId: userId, groupId: groupId, botId: botId, onCopyMessageLink: onCopyMessageLink, onSearchMessageRevoked: onSearchMessageRevoked, messageId: messageId, showSticker: showSticker }));
|
|
103
103
|
}
|
|
104
104
|
return (_jsxs("div", { "data-testid": "conversation-inbox-root", className: clsx(
|
|
105
105
|
// `relative` + `overflow-hidden` keep ContactSearchPanel's Drawer
|
package/dist/services/query.d.ts
CHANGED
|
@@ -46,5 +46,8 @@ export declare const QUERY_KEYS: {
|
|
|
46
46
|
DELETE_CONVERSATION: string;
|
|
47
47
|
GET_JOIN_LINK: string;
|
|
48
48
|
GET_JOIN_LINK_INFO: string;
|
|
49
|
+
GET_STICKER_CATEGORIES: string;
|
|
50
|
+
GET_STICKERS_BY_CATEGORY: string;
|
|
51
|
+
GET_STICKER_HISTORY: string;
|
|
49
52
|
};
|
|
50
53
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/services/query.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/services/query.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDtB,CAAC"}
|
package/dist/services/query.js
CHANGED
|
@@ -46,4 +46,7 @@ export const QUERY_KEYS = {
|
|
|
46
46
|
DELETE_CONVERSATION: "DELETE_CONVERSATION",
|
|
47
47
|
GET_JOIN_LINK: "GET_JOIN_LINK",
|
|
48
48
|
GET_JOIN_LINK_INFO: "GET_JOIN_LINK_INFO",
|
|
49
|
+
GET_STICKER_CATEGORIES: "GET_STICKER_CATEGORIES",
|
|
50
|
+
GET_STICKERS_BY_CATEGORY: "GET_STICKERS_BY_CATEGORY",
|
|
51
|
+
GET_STICKER_HISTORY: "GET_STICKER_HISTORY",
|
|
49
52
|
};
|
|
@@ -43,6 +43,9 @@ export declare const ENDPOINTS: {
|
|
|
43
43
|
getUrlMetadata: string;
|
|
44
44
|
getMessageResources: string;
|
|
45
45
|
searchContacts: string;
|
|
46
|
+
getStickerCategories: string;
|
|
47
|
+
getStickersByCategory: (categoryId: string) => string;
|
|
48
|
+
getStickerHistory: string;
|
|
46
49
|
};
|
|
47
50
|
identityService: {
|
|
48
51
|
getToken: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/services/routes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;mCAMS,MAAM;;0CAGC,MAAM,UAAU,MAAM;6BAEnC,MAAM;;oDAEiB,MAAM;uCAEnB,MAAM;kCAEX,MAAM;;oCAGJ,MAAM;mCAEP,MAAM;uCAEF,MAAM;;;;;;;;;iCAUZ,MAAM;4CAEK,MAAM;mCAEf,MAAM;yCAEA,MAAM;gCAEf,MAAM;;;;;gDAOU,MAAM;qCAEjB,MAAM;uCAEJ,MAAM;0CAEH,MAAM;yCAEP,MAAM;8BAEjB,MAAM;wCACI,MAAM
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/services/routes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;mCAMS,MAAM;;0CAGC,MAAM,UAAU,MAAM;6BAEnC,MAAM;;oDAEiB,MAAM;uCAEnB,MAAM;kCAEX,MAAM;;oCAGJ,MAAM;mCAEP,MAAM;uCAEF,MAAM;;;;;;;;;iCAUZ,MAAM;4CAEK,MAAM;mCAEf,MAAM;yCAEA,MAAM;gCAEf,MAAM;;;;;gDAOU,MAAM;qCAEjB,MAAM;uCAEJ,MAAM;0CAEH,MAAM;yCAEP,MAAM;8BAEjB,MAAM;wCACI,MAAM;;;;;4CAMF,MAAM;;;;;;;;;;;;CAa7C,CAAC"}
|
package/dist/services/routes.js
CHANGED
|
@@ -43,6 +43,9 @@ export const ENDPOINTS = {
|
|
|
43
43
|
getUrlMetadata: "/chat-service/v1/utils/url-metadata",
|
|
44
44
|
getMessageResources: "/chat-service/v1/app/messages/resources",
|
|
45
45
|
searchContacts: "/chat-service/v1/app/contacts/search",
|
|
46
|
+
getStickerCategories: "/chat-service/v1/app/sticker-categories",
|
|
47
|
+
getStickersByCategory: (categoryId) => `/chat-service/v1/app/sticker-categories/${categoryId}/stickers`,
|
|
48
|
+
getStickerHistory: "/chat-service/v1/app/stickers/history",
|
|
46
49
|
},
|
|
47
50
|
identityService: {
|
|
48
51
|
getToken: "/identity-service/v1/identity/get-token",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface TypingStore {
|
|
2
|
+
/** conversationID -> userIDs currently typing, in the order they started. */
|
|
3
|
+
typers: Record<string, string[]>;
|
|
4
|
+
/** "<conversationID>:<userID>" -> display name, resolved once and reused. */
|
|
5
|
+
names: Record<string, string>;
|
|
6
|
+
addTyper: (conversationId: string, userId: string) => void;
|
|
7
|
+
removeTyper: (conversationId: string, userId: string) => void;
|
|
8
|
+
setName: (key: string, name: string) => void;
|
|
9
|
+
clearTypers: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare const useTypingStore: import("zustand").UseBoundStore<import("zustand").StoreApi<TypingStore>>;
|
|
12
|
+
export default useTypingStore;
|
|
13
|
+
//# sourceMappingURL=typing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typing.d.ts","sourceRoot":"","sources":["../../src/store/typing.ts"],"names":[],"mappings":"AAeA,UAAU,WAAW;IACnB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACjC,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,WAAW,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,QAAA,MAAM,cAAc,0EA4CjB,CAAC;AAEJ,eAAe,cAAc,CAAC"}
|