@droppii-org/chat-sdk 0.1.57 → 0.1.59
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/ConversationDetailHeader.js +3 -2
- package/dist/components/conversation-detail/ConversationDetailInput.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationDetailInput.js +2 -1
- package/dist/components/conversation-detail/ConversationMessageList.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationMessageList.js +18 -4
- package/dist/components/conversation-detail/ConversationMoreOptionItem.js +1 -1
- package/dist/components/conversation-detail/bot/BotInactiveNotice.d.ts +3 -0
- package/dist/components/conversation-detail/bot/BotInactiveNotice.d.ts.map +1 -0
- package/dist/components/conversation-detail/bot/BotInactiveNotice.js +10 -0
- package/dist/components/conversation-detail/bot/index.d.ts +1 -0
- package/dist/components/conversation-detail/bot/index.d.ts.map +1 -1
- package/dist/components/conversation-detail/bot/index.js +1 -0
- package/dist/components/conversation-inbox/ConversationInboxItem.js +3 -2
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +1 -23
- package/dist/components/message/footer/index.js +2 -2
- package/dist/components/message/item/QuoteMessage.d.ts +1 -2
- package/dist/components/message/item/QuoteMessage.d.ts.map +1 -1
- package/dist/components/message/item/QuoteMessage.js +13 -49
- package/dist/components/message/item/TextMessage.d.ts.map +1 -1
- package/dist/components/message/item/TextMessage.js +2 -2
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +12 -3
- package/dist/components/message/reply/ReplyPreviewBar.d.ts +3 -0
- package/dist/components/message/reply/ReplyPreviewBar.d.ts.map +1 -0
- package/dist/components/message/reply/ReplyPreviewBar.js +23 -0
- package/dist/components/message/reply/ReplyPreviewMedia.d.ts +7 -0
- package/dist/components/message/reply/ReplyPreviewMedia.d.ts.map +1 -0
- package/dist/components/message/reply/ReplyPreviewMedia.js +41 -0
- package/dist/components/message/reply/ReplyQuoteContent.d.ts +9 -0
- package/dist/components/message/reply/ReplyQuoteContent.d.ts.map +1 -0
- package/dist/components/message/reply/ReplyQuoteContent.js +17 -0
- package/dist/hooks/conversation/useBotConversationDetail.js +2 -2
- package/dist/hooks/conversation/useBotDetail.d.ts +3 -0
- package/dist/hooks/conversation/useBotDetail.d.ts.map +1 -0
- package/dist/hooks/conversation/useBotDetail.js +18 -0
- package/dist/hooks/conversation/useBotFlow.d.ts +1 -0
- package/dist/hooks/conversation/useBotFlow.d.ts.map +1 -1
- package/dist/hooks/conversation/useBotFlow.js +13 -3
- package/dist/hooks/conversation/useConversationAvatarUrl.d.ts +3 -0
- package/dist/hooks/conversation/useConversationAvatarUrl.d.ts.map +1 -0
- package/dist/hooks/conversation/useConversationAvatarUrl.js +11 -0
- package/dist/hooks/conversation/useCreateConversation.js +2 -2
- package/dist/hooks/message/useMessageListScroll.d.ts +1 -0
- package/dist/hooks/message/useMessageListScroll.d.ts.map +1 -1
- package/dist/hooks/message/useMessageListScroll.js +22 -0
- package/dist/locales/vi/common.json +5 -4
- package/dist/locales/vi/conversation-inbox.json +2 -1
- package/dist/screens/conversation-detail/index.d.ts.map +1 -1
- package/dist/screens/conversation-detail/index.js +4 -2
- package/dist/services/query.d.ts +3 -2
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +3 -2
- package/dist/services/routes.d.ts +3 -2
- package/dist/services/routes.d.ts.map +1 -1
- package/dist/services/routes.js +3 -2
- package/dist/styles/global.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/conversation.d.ts +20 -0
- package/dist/types/conversation.d.ts.map +1 -1
- package/dist/types/conversation.js +5 -0
- package/dist/utils/common.js +2 -2
- package/dist/utils/conversation.d.ts +1 -0
- package/dist/utils/conversation.d.ts.map +1 -1
- package/dist/utils/conversation.js +11 -1
- package/package.json +1 -1
|
@@ -4,12 +4,13 @@ import { useTranslation } from "react-i18next";
|
|
|
4
4
|
import { Icon } from "../../components/icon";
|
|
5
5
|
import ConversationPeerAvatar from "../../components/conversation-inbox/ConversationPeerAvatar";
|
|
6
6
|
import ConversationInboxTitle from "../../components/conversation-inbox/ConversationInboxTitle";
|
|
7
|
-
import {
|
|
7
|
+
import { resolveConversationDisplayName, resolvePeerBadgeLabel, } from "../../utils/conversation";
|
|
8
|
+
import { useConversationAvatarUrl } from "../../hooks/conversation/useConversationAvatarUrl";
|
|
8
9
|
const HeaderIconButton = ({ icon, onClick, testId, }) => (_jsx("button", { type: "button", onClick: onClick, "data-testid": testId, className: "flex shrink-0 cursor-pointer items-center justify-center p-2 text-primary-400", children: _jsx(Icon, { icon: icon, size: 24 }) }));
|
|
9
10
|
const ConversationDetailHeader = ({ conversation, onBack, }) => {
|
|
10
11
|
const { t } = useTranslation("conversation-inbox");
|
|
11
12
|
const displayName = resolveConversationDisplayName(conversation, t);
|
|
12
|
-
const avatarUrl =
|
|
13
|
+
const avatarUrl = useConversationAvatarUrl(conversation);
|
|
13
14
|
const peerType = conversation.peerType;
|
|
14
15
|
const badgeLabel = resolvePeerBadgeLabel(peerType, t);
|
|
15
16
|
const subtitle = t("thread_detail.profile_hint");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationDetailInput.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationDetailInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConversationDetailInput.d.ts","sourceRoot":"","sources":["../../../src/components/conversation-detail/ConversationDetailInput.tsx"],"names":[],"mappings":"AA+BA,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,QAAA,MAAM,uBAAuB,GAAI,gDAI9B,4BAA4B,4CA6Y9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -16,6 +16,7 @@ import { useFetchUrlMetadata } from "../../hooks/common/useFetchUrlMetadata";
|
|
|
16
16
|
import { processAndValidateDocuments, processAndValidateFiles, } from "../../utils/fileValidation";
|
|
17
17
|
import { FilePreviewList } from "../../components/message/footer/FilePreview";
|
|
18
18
|
import LinkInputPreview from "../../components/message/footer/LinkInputPreview";
|
|
19
|
+
import { ReplyPreviewBar } from "../../components/message/reply/ReplyPreviewBar";
|
|
19
20
|
import ConversationMoreOptionPanel from "./ConversationMoreOptionPanel";
|
|
20
21
|
const MAX_LINES = 5;
|
|
21
22
|
const CONTAINER_MIN_HEIGHT = 48;
|
|
@@ -251,7 +252,7 @@ const ConversationDetailInput = ({ placeholder, onSendMessage, onInputChange, })
|
|
|
251
252
|
event.preventDefault();
|
|
252
253
|
void handleSend();
|
|
253
254
|
};
|
|
254
|
-
return (_jsxs("div", { ref: containerRef, "data-testid": "conversation-detail-input", className: "flex w-full shrink-0 flex-col bg-chat-bubble-neutral/[0.05]", children: [_jsx("input", { ref: mediaInputRef, type: "file", accept: "image/jpeg,image/png,image/jpg,video/*", multiple: true, className: "hidden", onChange: handleMediaInputChange }), _jsx("input", { ref: documentInputRef, type: "file", accept: ".pdf,.doc,.docx", multiple: true, className: "hidden", onChange: handleDocumentInputChange }), listUploadFiles.length > 0 && (_jsx(FilePreviewList, { files: listUploadFiles, onRemove: (file) => handleRemoveFile(file.uid), onVideoReady: () => setIsVideoLoading(false) })), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setPreviewDismissed(true) })), _jsxs("div", { className: "flex items-end gap-3 px-3 py-2", children: [_jsx("div", { className: "flex shrink-0 items-center", children: _jsx("button", { type: "button", onClick: handleToggleMoreOption, "aria-label": t("thread_detail.more_option.toggle"), "aria-expanded": isMoreOptionOpen, "data-testid": "conversation-detail-more-option-toggle", className: "flex py-3 items-center justify-center rounded-full", children: isMoreOptionOpen ? (_jsx(Icon, { icon: "close-circle-o", size: 24, className: "text-primary-400" })) : (_jsx(Icon, { icon: "plus-circle-o", size: 24, className: "text-gray-900" })) }) }), _jsx("div", { className: clsx("flex min-w-0 flex-1 overflow-hidden rounded-xl border bg-white transition-shadow", isFocused
|
|
255
|
+
return (_jsxs("div", { ref: containerRef, "data-testid": "conversation-detail-input", className: "flex w-full shrink-0 flex-col bg-chat-bubble-neutral/[0.05]", children: [_jsx("input", { ref: mediaInputRef, type: "file", accept: "image/jpeg,image/png,image/jpg,video/*", multiple: true, className: "hidden", onChange: handleMediaInputChange }), _jsx("input", { ref: documentInputRef, type: "file", accept: ".pdf,.doc,.docx", multiple: true, className: "hidden", onChange: handleDocumentInputChange }), _jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && (_jsx(FilePreviewList, { files: listUploadFiles, onRemove: (file) => handleRemoveFile(file.uid), onVideoReady: () => setIsVideoLoading(false) })), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setPreviewDismissed(true) })), _jsxs("div", { className: "flex items-end gap-3 px-3 py-2", children: [_jsx("div", { className: "flex shrink-0 items-center", children: _jsx("button", { type: "button", onClick: handleToggleMoreOption, "aria-label": t("thread_detail.more_option.toggle"), "aria-expanded": isMoreOptionOpen, "data-testid": "conversation-detail-more-option-toggle", className: "flex py-3 items-center justify-center rounded-full", children: isMoreOptionOpen ? (_jsx(Icon, { icon: "close-circle-o", size: 24, className: "text-primary-400" })) : (_jsx(Icon, { icon: "plus-circle-o", size: 24, className: "text-gray-900" })) }) }), _jsx("div", { className: clsx("flex min-w-0 flex-1 overflow-hidden rounded-xl border bg-white transition-shadow", isFocused
|
|
255
256
|
? "border-primary-200 shadow-primary-focus"
|
|
256
257
|
: "border-gray-50"), style: { minHeight: CONTAINER_MIN_HEIGHT }, children: _jsx("div", { className: "flex min-w-0 flex-[1_0_0] items-center gap-2 self-stretch px-3 py-1", children: _jsx("textarea", { ref: textareaRef, value: value, rows: 1, onChange: (event) => handleChange(event.target.value), onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : t("thread_detail.input_placeholder"), "data-testid": "conversation-detail-message-input", className: "conversation-message-input-scrollbar min-h-0 min-w-0 flex-1 resize-none appearance-none border-0 bg-transparent p-0 text-[16px] leading-[1.6] tracking-[0.16px] text-black outline-none ring-0 placeholder:text-gray-400 focus:border-0 focus:outline-none focus:ring-0" }) }) }), _jsx("div", { className: "flex shrink-0 items-center pb-1", children: _jsx("button", { type: "button", onClick: () => void handleSend(), disabled: !canSend, "data-testid": "conversation-detail-send", className: clsx("flex h-10 w-10 items-center justify-center rounded-full", canSend ? "bg-chat-send" : "bg-chat-send opacity-25"), children: _jsx(Icon, { icon: "send-b", size: 20, className: "text-white" }) }) })] }), isMoreOptionOpen && (_jsx(ConversationMoreOptionPanel, { disabled: !isConversationReady, onTriggerMediaInput: () => { var _a; return (_a = mediaInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, onTriggerDocumentInput: () => { var _a; return (_a = documentInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); } }))] }));
|
|
257
258
|
};
|
|
@@ -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;AAczE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,QAAA,MAAM,uBAAuB,GAAI,gBAAgB,4BAA4B,
|
|
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;AAczE,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,QAAA,MAAM,uBAAuB,GAAI,gBAAgB,4BAA4B,4CAsH5E,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -19,24 +19,38 @@ const ConversationMessageList = ({ bottomSlot }) => {
|
|
|
19
19
|
const authUserID = useAuthStore((state) => state.userID);
|
|
20
20
|
const conversation = useConversationStore((state) => state.conversationData);
|
|
21
21
|
const selectedConversationId = useConversationStore((state) => state.selectedConversationId);
|
|
22
|
+
const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
|
|
23
|
+
const searchClientMsgID = useConversationStore((state) => state.searchClientMsgID);
|
|
24
|
+
const setSearchClientMsgID = useConversationStore((state) => state.setSearchClientMsgID);
|
|
22
25
|
const conversationId = selectedConversationId || (conversation === null || conversation === void 0 ? void 0 : conversation.conversationID) || "";
|
|
23
26
|
const isGroupChat = conversation ? resolveIsGroupChat(conversation) : false;
|
|
24
|
-
const messageController = useMessage(conversationId);
|
|
25
|
-
const { scrollRef, loadMoreOldMessage, handleInfiniteScroll, scrollToBottomIfAtBottom, } = useMessageListScroll(Object.assign({ conversationId, userId: (user === null || user === void 0 ? void 0 : user.userID) || authUserID }, messageController));
|
|
27
|
+
const messageController = useMessage(conversationId, searchClientMsgID);
|
|
28
|
+
const { scrollRef, loadMoreOldMessage, handleInfiniteScroll, scrollToBottomIfAtBottom, scrollToMessage, } = useMessageListScroll(Object.assign({ conversationId, userId: (user === null || user === void 0 ? void 0 : user.userID) || authUserID }, messageController));
|
|
26
29
|
const { loadState, moreOldLoading } = messageController;
|
|
27
30
|
const isMessageLoading = !conversationId || loadState.initLoading;
|
|
28
31
|
const [openToolboxMessageId, setOpenToolboxMessageId] = useState(null);
|
|
29
32
|
const closeToolbox = useCallback(() => setOpenToolboxMessageId(null), []);
|
|
33
|
+
const onPressQuoteMessage = useCallback((clientMsgID) => {
|
|
34
|
+
const hasMessage = loadState.messageList.some((msg) => msg.clientMsgID === clientMsgID);
|
|
35
|
+
if (hasMessage) {
|
|
36
|
+
scrollToMessage(clientMsgID);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
setSearchClientMsgID(clientMsgID);
|
|
40
|
+
}
|
|
41
|
+
}, [scrollToMessage, loadState.messageList, setSearchClientMsgID]);
|
|
30
42
|
useEffect(() => {
|
|
31
43
|
emitter.on("CONVERSATION_CHAT_SCROLL_TO_BOTTOM_IF_AT_BOTTOM", scrollToBottomIfAtBottom);
|
|
44
|
+
emitter.on("CHAT_LIST_SCROLL_TO_MESSAGE", scrollToMessage);
|
|
32
45
|
return () => {
|
|
33
46
|
emitter.off("CONVERSATION_CHAT_SCROLL_TO_BOTTOM_IF_AT_BOTTOM", scrollToBottomIfAtBottom);
|
|
47
|
+
emitter.off("CHAT_LIST_SCROLL_TO_MESSAGE", scrollToMessage);
|
|
34
48
|
};
|
|
35
|
-
}, [scrollToBottomIfAtBottom]);
|
|
49
|
+
}, [scrollToBottomIfAtBottom, scrollToMessage]);
|
|
36
50
|
useEventListener("scroll", closeToolbox, {
|
|
37
51
|
target: scrollRef,
|
|
38
52
|
enable: !!openToolboxMessageId,
|
|
39
53
|
});
|
|
40
|
-
return (_jsx("div", { "data-testid": "conversation-message-list", className: "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden bg-white", children: isMessageLoading ? (_jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Spin, {}) })) : (_jsxs(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableConversationMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, containerClassName: "h-full", empty: _jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Empty, { description: t("empty.no_messages") }) }), children: [bottomSlot, loadState.messageList.map((message, index, array) => (_jsx(MessageItem, { message: message, allMessages: array, isGroupChat: isGroupChat, forceHideTip: index === 0 && !!bottomSlot, contextMenuOpen: openToolboxMessageId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenToolboxMessageId(open ? message.clientMsgID : null), onQuoteMessage:
|
|
54
|
+
return (_jsx("div", { "data-testid": "conversation-message-list", className: "relative flex min-h-0 min-w-0 flex-1 flex-col overflow-x-hidden bg-white", children: isMessageLoading ? (_jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Spin, {}) })) : (_jsxs(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableConversationMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, containerClassName: "h-full", empty: _jsx("div", { className: "flex flex-1 items-center justify-center py-12", children: _jsx(Empty, { description: t("empty.no_messages") }) }), children: [bottomSlot, loadState.messageList.map((message, index, array) => (_jsx(MessageItem, { message: message, allMessages: array, isGroupChat: isGroupChat, forceHideTip: index === 0 && !!bottomSlot, contextMenuOpen: openToolboxMessageId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenToolboxMessageId(open ? message.clientMsgID : null), onQuoteMessage: setQuotedMessage, onRevokeMessage: closeToolbox, onPressQuoteMessage: onPressQuoteMessage, enableLongPress: true }, message.clientMsgID)))] })) }));
|
|
41
55
|
};
|
|
42
56
|
export default ConversationMessageList;
|
|
@@ -12,7 +12,7 @@ const ConversationMoreOptionItem = ({ option, onSelect }) => {
|
|
|
12
12
|
return;
|
|
13
13
|
onSelect(option);
|
|
14
14
|
};
|
|
15
|
-
return (_jsxs("button", { type: "button", onClick: handleClick, disabled: !option.enabled, "aria-label": label, "data-testid": `
|
|
15
|
+
return (_jsxs("button", { type: "button", onClick: handleClick, disabled: !option.enabled, "aria-label": label, "data-testid": `more-option-${option.labelKey}`, className: clsx("flex flex-col items-center gap-1 rounded-xl px-1 transition-colors", option.enabled
|
|
16
16
|
? "active:bg-chat-bubble-neutral/[0.08]"
|
|
17
17
|
: "cursor-not-allowed opacity-40"), children: [_jsx("span", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-gray-200/10", children: _jsx(Icon, { icon: option.icon, size: ICON_SIZE, className: "text-gray-900" }) }), _jsx("span", { className: "line-clamp-2 text-center text-[12px] leading-[1.4] text-gray-900", children: label })] }));
|
|
18
18
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BotInactiveNotice.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-detail/bot/BotInactiveNotice.tsx"],"names":[],"mappings":"AAOA,QAAA,MAAM,iBAAiB,+CActB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { Icon } from "../../../components/icon";
|
|
5
|
+
const ICON_SIZE = 16;
|
|
6
|
+
const BotInactiveNotice = () => {
|
|
7
|
+
const { t } = useTranslation("conversation-inbox");
|
|
8
|
+
return (_jsxs("div", { "data-testid": "conversation-bot-inactive-notice", className: "flex w-full items-center justify-center gap-1 bg-white px-4 py-1", children: [_jsx(Icon, { icon: "info-circle-o", size: ICON_SIZE, className: "shrink-0 text-gray-900" }), _jsx("span", { className: "text-[12px] font-normal leading-[1.6] text-gray-900", children: t("thread_detail.bot.inactive_notice") })] }));
|
|
9
|
+
};
|
|
10
|
+
export default BotInactiveNotice;
|
|
@@ -4,4 +4,5 @@ export { default as BotButtonMessage } from "./BotButtonMessage";
|
|
|
4
4
|
export type { BotButtonMessageProps } from "./BotButtonMessage";
|
|
5
5
|
export { default as BotSuggest } from "./BotSuggest";
|
|
6
6
|
export type { BotSuggestProps } from "./BotSuggest";
|
|
7
|
+
export { default as BotInactiveNotice } from "./BotInactiveNotice";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-detail/bot/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/conversation-detail/bot/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -4,7 +4,8 @@ import dayjs from "dayjs";
|
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
5
5
|
import useAuthStore from "../../store/auth";
|
|
6
6
|
import { formatTimestamp, parseLatestMessage } from "../../utils/common";
|
|
7
|
-
import { isBotPeer,
|
|
7
|
+
import { isBotPeer, resolvePeerBadgeLabel, resolveConversationDisplayName, } from "../../utils/conversation";
|
|
8
|
+
import { useConversationAvatarUrl } from "../../hooks/conversation/useConversationAvatarUrl";
|
|
8
9
|
import ThreadCard from "../../components/conversation/ThreadCard";
|
|
9
10
|
import ConversationPeerAvatar from "./ConversationPeerAvatar";
|
|
10
11
|
import ConversationInboxTitle from "./ConversationInboxTitle";
|
|
@@ -20,7 +21,7 @@ const ConversationInboxItem = ({ item, onClick }) => {
|
|
|
20
21
|
const { t: tCommon } = useTranslation("common");
|
|
21
22
|
const currentUserId = useAuthStore((state) => state.userID);
|
|
22
23
|
const displayName = resolveConversationDisplayName(item, t);
|
|
23
|
-
const avatarUrl =
|
|
24
|
+
const avatarUrl = useConversationAvatarUrl(item);
|
|
24
25
|
const badgeLabel = resolvePeerBadgeLabel(item.peerType, t);
|
|
25
26
|
const latestMessagePreview = parseLatestMessage(item.latestMsg, currentUserId, tCommon, isBotPeer(item));
|
|
26
27
|
const latestMessageTime = formatLatestMessageTime(item.latestMsgSendTime || null);
|
|
@@ -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":"AAyBA,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;CACpC;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAgO3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -15,7 +15,6 @@ import { useTranslation } from "react-i18next";
|
|
|
15
15
|
import useConversationStore from "../../store/conversation";
|
|
16
16
|
import { useBoolean } from "ahooks";
|
|
17
17
|
import { useMessageListScroll } from "../../hooks/message/useMessageListScroll";
|
|
18
|
-
import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../constants";
|
|
19
18
|
import { useChatContext } from "../../context/ChatContext";
|
|
20
19
|
import { useRevokeMessage } from "../../hooks/message/useRevokeMessage";
|
|
21
20
|
import { useConversationSessionState } from "../../hooks/session/useConversationSessionState";
|
|
@@ -49,7 +48,7 @@ const MessageList = (props) => {
|
|
|
49
48
|
customerUserID,
|
|
50
49
|
});
|
|
51
50
|
const { loadState, moreOldLoading, moreNewLoading } = messageController;
|
|
52
|
-
const { scrollRef, loadMoreOldMessage, handleInfiniteScroll, scrollToBottom } = useMessageListScroll(Object.assign({ conversationId, userId: user === null || user === void 0 ? void 0 : user.userID }, messageController));
|
|
51
|
+
const { scrollRef, loadMoreOldMessage, handleInfiniteScroll, scrollToBottom, scrollToMessage, } = useMessageListScroll(Object.assign({ conversationId, userId: user === null || user === void 0 ? void 0 : user.userID }, messageController));
|
|
53
52
|
const handleOpenRevoke = useCallback((clientMsgID) => {
|
|
54
53
|
setSelectedItem(clientMsgID);
|
|
55
54
|
openConfirmRevoke();
|
|
@@ -67,27 +66,6 @@ const MessageList = (props) => {
|
|
|
67
66
|
revokeMessage,
|
|
68
67
|
handleCloseRevoke,
|
|
69
68
|
]);
|
|
70
|
-
const scrollToMessage = (clientMsgID) => {
|
|
71
|
-
setTimeout(() => {
|
|
72
|
-
const targetElement = document.getElementById(`${MSG_ITEM_PREFIX}${clientMsgID}`);
|
|
73
|
-
targetElement === null || targetElement === void 0 ? void 0 : targetElement.scrollIntoView({
|
|
74
|
-
behavior: "auto",
|
|
75
|
-
block: "center",
|
|
76
|
-
});
|
|
77
|
-
setTimeout(() => {
|
|
78
|
-
const targetContentElement = document.getElementById(`${MSG_ITEM_CONTENT_PREFIX}${clientMsgID}`);
|
|
79
|
-
targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.classList.add("zoom-in-out-element", "border-blue-500", "border");
|
|
80
|
-
// Khi animation kết thúc thì remove element
|
|
81
|
-
const onEnd = () => {
|
|
82
|
-
targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.classList.remove("zoom-in-out-element", "border-blue-500", "border");
|
|
83
|
-
targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.removeEventListener("animationend", onEnd);
|
|
84
|
-
};
|
|
85
|
-
targetContentElement === null || targetContentElement === void 0 ? void 0 : targetContentElement.addEventListener("animationend", onEnd, {
|
|
86
|
-
once: true,
|
|
87
|
-
});
|
|
88
|
-
}, 500);
|
|
89
|
-
}, 200);
|
|
90
|
-
};
|
|
91
69
|
const onPressQuoteMessage = useCallback((clientMsgID) => {
|
|
92
70
|
const hasMessage = loadState.messageList.some((msg) => msg.clientMsgID === clientMsgID);
|
|
93
71
|
if (hasMessage) {
|
|
@@ -18,7 +18,7 @@ import { extractLinkUrls } from "../../../utils/link";
|
|
|
18
18
|
import { useFetchUrlMetadata } from "../../../hooks/common/useFetchUrlMetadata";
|
|
19
19
|
import { useTranslation } from "react-i18next";
|
|
20
20
|
import PasteAndDropPlugin from "./PasteAndDropPlugin";
|
|
21
|
-
import {
|
|
21
|
+
import { ReplyPreviewBar } from "../../../components/message/reply/ReplyPreviewBar";
|
|
22
22
|
import CannedResponse from "../../../components/canned-response";
|
|
23
23
|
import { CannedResponseTriggerPlugin } from "./CannedResponsePlugin";
|
|
24
24
|
import { useBoolean } from "ahooks";
|
|
@@ -214,6 +214,6 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
|
|
|
214
214
|
setMaxActiveCannedIndex,
|
|
215
215
|
}, children: [_jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Popover, { open: isOpenCanned, content: _jsx(CannedResponse, { onClose: closeCanned, openCreateCannedModal: onOpenCreateCannedModal, cannedQuery: cannedQuery }), placement: "topLeft", trigger: "click", arrow: false, classNames: {
|
|
216
216
|
body: "mx-1 !p-0",
|
|
217
|
-
}, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(
|
|
217
|
+
}, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(ReplyPreviewBar, {}), listUploadFiles.length > 0 && _jsx(FilePreview, {}), showLinkPreview && previewUrl && (_jsx(LinkInputPreview, { url: previewUrl, onRemove: () => setIsLinkPreviewDismissed(true) })), _jsx(ToolbarPlugin, {}), _jsxs("div", { children: [_jsx(ComposerTabs, { canUseInternal: canUseInternal, hintText: t("canned_response_hint"), isInternal: isInternal, lockToInternal: lockToInternal, setIsInternal: setIsInternal }), _jsx(ComposerEditor, { isInternal: isInternal, placeholderText: placeholderText })] }), _jsx(ActionBar, {})] }) }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(ComposerTextSyncPlugin, { onChange: setComposerText }), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {}), isCrm && (_jsx(CannedResponseTriggerPlugin, { onClose: closeCanned, onOpen: onOpenCanned }))] }), _jsx(SessionClosedModal, { open: isSessionClosedModalOpen, loading: isSessionActionLoading, onReopen: handleReopenSession, onCreateNew: handleCreateNewSession, onClose: handleCloseSessionModal })] }));
|
|
218
218
|
};
|
|
219
219
|
export default MessageFooterProvider;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { MessageItem } from "@openim/wasm-client-sdk";
|
|
2
2
|
interface QuoteMessageItemProps {
|
|
3
3
|
message: MessageItem;
|
|
4
|
-
isMine: boolean;
|
|
5
4
|
onPressQuoteMessage?: (clientMsgID: string) => void;
|
|
6
5
|
}
|
|
7
|
-
declare const QuoteMessageItem: ({ message,
|
|
6
|
+
declare const QuoteMessageItem: ({ message, onPressQuoteMessage, }: QuoteMessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
8
7
|
export default QuoteMessageItem;
|
|
9
8
|
//# sourceMappingURL=QuoteMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuoteMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/QuoteMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"QuoteMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/QuoteMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAOtD,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,mDAkDvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import { generateContentBasedOnMessageType } from "../../../utils/common";
|
|
3
|
-
import { Icon } from "../../../components/icon";
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
2
|
import { useTranslation } from "react-i18next";
|
|
5
|
-
import clsx from "clsx";
|
|
6
|
-
import MediaPreviewIcon from "../../../components/message/MediaPreviewIcon";
|
|
7
|
-
import useAuthStore from "../../../store/auth";
|
|
8
3
|
import { useCallback, useMemo } from "react";
|
|
4
|
+
import useAuthStore from "../../../store/auth";
|
|
9
5
|
import useConversationStore from "../../../store/conversation";
|
|
10
|
-
|
|
11
|
-
const QuoteMessageItem = ({ message,
|
|
12
|
-
var _a
|
|
6
|
+
import ReplyQuoteContent from "../../../components/message/reply/ReplyQuoteContent";
|
|
7
|
+
const QuoteMessageItem = ({ message, onPressQuoteMessage, }) => {
|
|
8
|
+
var _a;
|
|
13
9
|
const userID = useAuthStore((state) => state.userID);
|
|
14
10
|
const isCrm = useAuthStore((state) => state.isCrm);
|
|
15
11
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
@@ -33,45 +29,13 @@ const QuoteMessageItem = ({ message, isMine, onPressQuoteMessage, }) => {
|
|
|
33
29
|
return t("you");
|
|
34
30
|
return name;
|
|
35
31
|
}, [isCrm, isChatSupport, conversationData === null || conversationData === void 0 ? void 0 : conversationData.showName, userID, t]);
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const targetName = quoteMsg === null || quoteMsg === void 0 ? void 0 : quoteMsg.senderNickname;
|
|
45
|
-
const isSelfReply = senderID === targetID;
|
|
46
|
-
const isFromMe = senderID === userID;
|
|
47
|
-
const isReplyToMe = targetID === userID;
|
|
48
|
-
const senderDisplay = getDisplayName({ name: senderName, id: senderID });
|
|
49
|
-
const targetDisplay = getDisplayName({ name: targetName, id: targetID });
|
|
50
|
-
if (isSelfReply) {
|
|
51
|
-
return isFromMe
|
|
52
|
-
? capitalize(t("replied_yourself"))
|
|
53
|
-
: `${senderDisplay} ${t("replied_yourself")}`;
|
|
54
|
-
}
|
|
55
|
-
if (isFromMe) {
|
|
56
|
-
return `${capitalize(t("replied"))} ${targetDisplay}`;
|
|
57
|
-
}
|
|
58
|
-
if (isReplyToMe) {
|
|
59
|
-
return `${senderDisplay} ${t("replied_you")}`;
|
|
60
|
-
}
|
|
61
|
-
return `${senderDisplay} ${t("replied")} ${targetDisplay}`;
|
|
62
|
-
}, [
|
|
63
|
-
message,
|
|
64
|
-
userID,
|
|
65
|
-
isCrm,
|
|
66
|
-
isChatSupport,
|
|
67
|
-
conversationData,
|
|
68
|
-
t,
|
|
69
|
-
getDisplayName,
|
|
70
|
-
]);
|
|
71
|
-
const replyText = useMemo(() => parseReplyText(), [parseReplyText]);
|
|
72
|
-
return (_jsxs("div", { className: clsx("mb-[-4px] flex flex-col gap-1 flex-1 w-full", isMine ? "items-end" : "items-start"), children: [_jsxs("div", { className: "flex flex-row flex-1 items-center gap-2", children: [_jsx(Icon, { icon: "arrow-reply-b", size: 16, className: "text-blue-500" }), _jsx("span", { className: "text-xs text-gray-500", children: replyText })] }), _jsxs("div", { className: "flex flex-row flex-1 max-w-full items-center gap-2 border border-gray-200 rounded-2xl min-w-0 px-3 py-2 bg-gray-100 cursor-pointer", onClick: () => {
|
|
73
|
-
var _a, _b;
|
|
74
|
-
return onPressQuoteMessage === null || onPressQuoteMessage === void 0 ? void 0 : onPressQuoteMessage(((_b = (_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage) === null || _b === void 0 ? void 0 : _b.clientMsgID) || "");
|
|
75
|
-
}, children: [_jsx(MediaPreviewIcon, { message: (_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage }), _jsx("span", { className: "text-sm text-gray-500 truncate", children: generateContentBasedOnMessageType((_c = (_b = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _b === void 0 ? void 0 : _b.quoteMessage) === null || _c === void 0 ? void 0 : _c.contentType, ((_f = (_e = (_d = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _d === void 0 ? void 0 : _d.quoteMessage) === null || _e === void 0 ? void 0 : _e.textElem) === null || _f === void 0 ? void 0 : _f.content) || "") })] })] }));
|
|
32
|
+
const quoteMessage = (_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage;
|
|
33
|
+
if (!quoteMessage)
|
|
34
|
+
return null;
|
|
35
|
+
const title = getDisplayName({
|
|
36
|
+
name: quoteMessage.senderNickname,
|
|
37
|
+
id: quoteMessage.sendID,
|
|
38
|
+
});
|
|
39
|
+
return (_jsx("div", { className: "flex cursor-pointer items-center overflow-hidden rounded-r-xl bg-white/70", onClick: () => onPressQuoteMessage === null || onPressQuoteMessage === void 0 ? void 0 : onPressQuoteMessage(quoteMessage.clientMsgID || ""), children: _jsx(ReplyQuoteContent, { message: quoteMessage, title: title }) }));
|
|
76
40
|
};
|
|
77
41
|
export default QuoteMessageItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/TextMessage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAQnE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,
|
|
1
|
+
{"version":3,"file":"TextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/TextMessage.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAQnE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,mDAqDnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -25,7 +25,7 @@ const TextMessageItem = (props) => {
|
|
|
25
25
|
const richHtmlContent = ((_b = (_a = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.content) || "";
|
|
26
26
|
if (richHtmlContent && htmlHasFormatting(richHtmlContent)) {
|
|
27
27
|
const sanitizedContent = sanitizeHtml(richHtmlContent);
|
|
28
|
-
return (_jsx("div", { className: clsx("
|
|
28
|
+
return (_jsx("div", { className: clsx("min-w-0 flex-1 whitespace-pre-line [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), dangerouslySetInnerHTML: { __html: sanitizedContent } }));
|
|
29
29
|
}
|
|
30
30
|
const text = ((_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) ||
|
|
31
31
|
((_d = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _d === void 0 ? void 0 : _d.text) ||
|
|
@@ -36,6 +36,6 @@ const TextMessageItem = (props) => {
|
|
|
36
36
|
if (extractLinkUrls(text).length > 0) {
|
|
37
37
|
return _jsx(LinkText, { text: text });
|
|
38
38
|
}
|
|
39
|
-
return (_jsx("p", { className: clsx("whitespace-pre-wrap
|
|
39
|
+
return (_jsx("p", { className: clsx("min-w-0 whitespace-pre-wrap [overflow-wrap:anywhere]", MESSAGE_TEXT_CLASS), children: text }));
|
|
40
40
|
};
|
|
41
41
|
export default TextMessageItem;
|
|
@@ -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,yBAAyB,CAAC;AAuCjC,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,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAeD,QAAA,MAAM,WAAW,GAAI,uKAWlB,gBAAgB,
|
|
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,yBAAyB,CAAC;AAuCjC,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,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAeD,QAAA,MAAM,WAAW,GAAI,uKAWlB,gBAAgB,mDAoSlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createElement as _createElement } from "react";
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import dayjs from "dayjs";
|
|
4
4
|
import clsx from "clsx";
|
|
5
5
|
import { Dropdown, message as toastMessage } from "antd";
|
|
@@ -160,13 +160,22 @@ const MessageItem = ({ message, allMessages, isGroupChat = false, forceHideTip =
|
|
|
160
160
|
timeBreakNode,
|
|
161
161
|
_jsx(SystemLogMessageItem, { message: message })));
|
|
162
162
|
}
|
|
163
|
-
const
|
|
163
|
+
const renderBubbleContent = () => {
|
|
164
|
+
if (message === null || message === void 0 ? void 0 : message.quoteElem) {
|
|
165
|
+
return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(QuoteMessageItem, { message: message, onPressQuoteMessage: onPressQuoteMessage }), renderMessageByType(message)] }));
|
|
166
|
+
}
|
|
167
|
+
if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.MergeMessage) {
|
|
168
|
+
return (_jsxs(_Fragment, { children: [_jsx(MergeImageMessageItem, { message: message }), (message === null || message === void 0 ? void 0 : message.textElem) && _jsx(TextMessageItem, { message: message })] }));
|
|
169
|
+
}
|
|
170
|
+
return renderMessageByType(message);
|
|
171
|
+
};
|
|
172
|
+
const bubbleNode = (_jsx(MessageBubble, { isMine: isMine, isInternal: isInternalMessage, senderName: message === null || message === void 0 ? void 0 : message.senderNickname, showSenderName: showSenderName, showTip: showTip, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, content: renderBubbleContent() }));
|
|
164
173
|
const wrappedBubble = hasContextMenu ? (_jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: ["contextMenu"], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, overlayClassName: MESSAGE_TOOLBOX_OVERLAY_CLASSNAME, children: _jsx("div", { ref: bubbleWrapperRef, className: "min-w-0", children: bubbleNode }) })) : (bubbleNode);
|
|
165
174
|
return (_createElement("div", Object.assign({}, messageContainerProps, { key: message === null || message === void 0 ? void 0 : message.clientMsgID }),
|
|
166
175
|
timeBreakNode,
|
|
167
176
|
_jsxs("div", { className: clsx("flex min-w-0 items-end gap-1", isMine ? "justify-end pl-12 pr-3" : "justify-start pl-3 pr-12"), children: [!isMine &&
|
|
168
177
|
showPeerInfo &&
|
|
169
|
-
(showAvatar ? (_jsx(MessageAvatar, { avatarUrl: message === null || message === void 0 ? void 0 : message.senderFaceUrl })) : (_jsx("div", { className: "h-6 w-6 shrink-0 self-end" }))), _jsxs("div", { className: clsx("flex min-w-0 max-w-[75%] flex-col gap-1", isMine ? "items-end" : "items-start"), children: [
|
|
178
|
+
(showAvatar ? (_jsx(MessageAvatar, { avatarUrl: message === null || message === void 0 ? void 0 : message.senderFaceUrl })) : (_jsx("div", { className: "h-6 w-6 shrink-0 self-end" }))), _jsxs("div", { className: clsx("flex min-w-0 max-w-[75%] flex-col gap-1", isMine ? "items-end" : "items-start"), children: [_jsxs("div", { className: "flex items-end gap-1.5", children: [isMine && (_jsx(MessageStatusIndicator, { message: message, isLatest: isLatestMine })), wrappedBubble] }), isMine && message.status === MessageStatus.Failed && (_jsx("span", { className: "mt-1 text-xs text-red-500", children: isMediaResendable(message) ? (_jsx(Trans, { i18nKey: "message_send_failed", components: {
|
|
170
179
|
bold: (_jsx("strong", { className: "cursor-pointer", onClick: () => resendMessage(message) })),
|
|
171
180
|
} })) : (t("message_send_failed_no_retry")) }))] })] })));
|
|
172
181
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReplyPreviewBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyPreviewBar.tsx"],"names":[],"mappings":"AAMA,eAAO,MAAM,eAAe,sDAuC3B,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { Icon } from "../../../components/icon";
|
|
4
|
+
import useAuthStore from "../../../store/auth";
|
|
5
|
+
import useConversationStore from "../../../store/conversation";
|
|
6
|
+
import { ReplyQuoteContent } from "./ReplyQuoteContent";
|
|
7
|
+
export const ReplyPreviewBar = () => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
const quotedMessage = useConversationStore((state) => state.quotedMessage);
|
|
10
|
+
const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
|
|
11
|
+
const userID = useAuthStore((state) => state.userID);
|
|
12
|
+
const handleClearQuotedMessage = () => {
|
|
13
|
+
setQuotedMessage(null);
|
|
14
|
+
};
|
|
15
|
+
if (!quotedMessage)
|
|
16
|
+
return null;
|
|
17
|
+
const isMe = quotedMessage.sendID === userID;
|
|
18
|
+
const senderName = isMe
|
|
19
|
+
? t("your_self")
|
|
20
|
+
: quotedMessage.senderNickname || "";
|
|
21
|
+
return (_jsxs("div", { "data-testid": "reply-preview-bar", 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
|
+
};
|
|
23
|
+
export default ReplyPreviewBar;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MessageItem } from "@openim/wasm-client-sdk";
|
|
2
|
+
interface ReplyPreviewMediaProps {
|
|
3
|
+
message: MessageItem;
|
|
4
|
+
}
|
|
5
|
+
declare const ReplyPreviewMedia: ({ message }: ReplyPreviewMediaProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export default ReplyPreviewMedia;
|
|
7
|
+
//# sourceMappingURL=ReplyPreviewMedia.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReplyPreviewMedia.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyPreviewMedia.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAKnE,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;CACtB;AAYD,QAAA,MAAM,iBAAiB,GAAI,aAAa,sBAAsB,mDAoD7D,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { MessageType } from "@openim/wasm-client-sdk";
|
|
3
|
+
import { documentIcon } from "../../../assets/svg";
|
|
4
|
+
import { Icon } from "../../../components/icon";
|
|
5
|
+
const parseUrlMetadataImage = (ex) => {
|
|
6
|
+
var _a;
|
|
7
|
+
if (!ex)
|
|
8
|
+
return undefined;
|
|
9
|
+
try {
|
|
10
|
+
const extendMessageInfo = JSON.parse(ex);
|
|
11
|
+
return (_a = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.urlMetadata) === null || _a === void 0 ? void 0 : _a.image;
|
|
12
|
+
}
|
|
13
|
+
catch (_b) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const ReplyPreviewMedia = ({ message }) => {
|
|
18
|
+
var _a, _b, _c, _d, _e;
|
|
19
|
+
if (message.contentType === MessageType.FileMessage) {
|
|
20
|
+
return (_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-6 [&>svg]:w-6", children: documentIcon }));
|
|
21
|
+
}
|
|
22
|
+
if (message.contentType === MessageType.PictureMessage) {
|
|
23
|
+
const imageUrl = ((_b = (_a = message.pictureElem) === null || _a === void 0 ? void 0 : _a.sourcePicture) === null || _b === void 0 ? void 0 : _b.url) ||
|
|
24
|
+
((_d = (_c = message.pictureElem) === null || _c === void 0 ? void 0 : _c.snapshotPicture) === null || _d === void 0 ? void 0 : _d.url);
|
|
25
|
+
if (!imageUrl)
|
|
26
|
+
return null;
|
|
27
|
+
return (_jsx("img", { src: imageUrl, alt: "", className: "h-[42px] w-[42px] shrink-0 rounded-lg object-cover" }));
|
|
28
|
+
}
|
|
29
|
+
if (message.contentType === MessageType.VideoMessage) {
|
|
30
|
+
const posterUrl = (_e = message.videoElem) === null || _e === void 0 ? void 0 : _e.snapshotUrl;
|
|
31
|
+
return (_jsxs("div", { className: "relative h-[42px] w-[42px] shrink-0 overflow-hidden rounded-lg bg-gray-900", children: [posterUrl && (_jsx("img", { src: posterUrl, alt: "", className: "h-full w-full object-cover" })), _jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-black/60", children: _jsx(Icon, { icon: "play-o", size: 12, className: "text-white" }) }) })] }));
|
|
32
|
+
}
|
|
33
|
+
if (message.contentType === MessageType.UrlTextMessage) {
|
|
34
|
+
const imageUrl = parseUrlMetadataImage(message.ex);
|
|
35
|
+
if (!imageUrl)
|
|
36
|
+
return null;
|
|
37
|
+
return (_jsx("img", { src: imageUrl, alt: "", className: "h-[42px] w-[42px] shrink-0 rounded-lg object-cover" }));
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
export default ReplyPreviewMedia;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MessageItem, MessageType } from "@openim/wasm-client-sdk";
|
|
2
|
+
export declare const hasReplyMediaPreview: (contentType: MessageType) => boolean;
|
|
3
|
+
interface ReplyQuoteContentProps {
|
|
4
|
+
message: MessageItem;
|
|
5
|
+
title?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const ReplyQuoteContent: ({ message, title, }: ReplyQuoteContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default ReplyQuoteContent;
|
|
9
|
+
//# sourceMappingURL=ReplyQuoteContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReplyQuoteContent.d.ts","sourceRoot":"","sources":["../../../../src/components/message/reply/ReplyQuoteContent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AASnE,eAAO,MAAM,oBAAoB,GAAI,aAAa,WAAW,YACb,CAAC;AAEjD,UAAU,sBAAsB;IAC9B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iBAAiB,GAAI,qBAG/B,sBAAsB,4CAsBxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { MessageType } from "@openim/wasm-client-sdk";
|
|
4
|
+
import { generateContentBasedOnMessageType } from "../../../utils/common";
|
|
5
|
+
import ReplyPreviewMedia from "./ReplyPreviewMedia";
|
|
6
|
+
const TEXT_LIKE_MESSAGE_TYPES = [
|
|
7
|
+
MessageType.TextMessage,
|
|
8
|
+
MessageType.QuoteMessage,
|
|
9
|
+
];
|
|
10
|
+
export const hasReplyMediaPreview = (contentType) => !TEXT_LIKE_MESSAGE_TYPES.includes(contentType);
|
|
11
|
+
export const ReplyQuoteContent = ({ message, title = "", }) => {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const hasMedia = hasReplyMediaPreview(message.contentType);
|
|
15
|
+
return (_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-0.5 pr-2 self-stretch", children: [_jsx("div", { className: "w-[3px] shrink-0 self-stretch rounded bg-gray-cool-200" }), hasMedia && _jsx(ReplyPreviewMedia, { message: message }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center py-1 pl-2", children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[160%] text-gray-900", children: title }), _jsx("p", { className: "truncate text-[13px] leading-[160%] text-gray-400", children: generateContentBasedOnMessageType(message.contentType, ((_a = message.textElem) === null || _a === void 0 ? void 0 : _a.content) || ((_b = message.quoteElem) === null || _b === void 0 ? void 0 : _b.text), t) })] })] }));
|
|
16
|
+
};
|
|
17
|
+
export default ReplyQuoteContent;
|
|
@@ -5,9 +5,9 @@ import { ENDPOINTS } from "../../services/routes";
|
|
|
5
5
|
import { QUERY_KEYS } from "../../services/query";
|
|
6
6
|
export const useBotConversationDetail = (conversationId, enabled) => {
|
|
7
7
|
return useQuery({
|
|
8
|
-
queryKey: [QUERY_KEYS.
|
|
8
|
+
queryKey: [QUERY_KEYS.GET_CONVERSATION_DETAIL, conversationId],
|
|
9
9
|
queryFn: async () => {
|
|
10
|
-
const res = await apiInstance.get(ENDPOINTS.chatService.
|
|
10
|
+
const res = await apiInstance.get(ENDPOINTS.chatService.getConversationDetail(conversationId));
|
|
11
11
|
return res.data.data;
|
|
12
12
|
},
|
|
13
13
|
enabled: enabled && !!conversationId,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBotDetail.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useBotDetail.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,SAAS,OAAO,qEAc3D,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { apiInstance } from "../../services/api";
|
|
4
|
+
import { ENDPOINTS } from "../../services/routes";
|
|
5
|
+
import { QUERY_KEYS } from "../../services/query";
|
|
6
|
+
export const useBotDetail = (botId, enabled) => {
|
|
7
|
+
return useQuery({
|
|
8
|
+
queryKey: [QUERY_KEYS.GET_BOT_DETAIL, botId],
|
|
9
|
+
queryFn: async () => {
|
|
10
|
+
const res = await apiInstance.get(ENDPOINTS.chatService.getBotDetail(botId));
|
|
11
|
+
return res.data.data;
|
|
12
|
+
},
|
|
13
|
+
enabled: enabled && !!botId,
|
|
14
|
+
staleTime: 0,
|
|
15
|
+
refetchOnWindowFocus: false,
|
|
16
|
+
refetchOnReconnect: false,
|
|
17
|
+
});
|
|
18
|
+
};
|
|
@@ -7,6 +7,7 @@ interface UseBotFlowParams {
|
|
|
7
7
|
export declare const useBotFlow: ({ conversationId, isBotThread, }: UseBotFlowParams) => {
|
|
8
8
|
status: BotFlowStatus;
|
|
9
9
|
flowIsEnd: boolean;
|
|
10
|
+
isBotInactive: boolean;
|
|
10
11
|
isProcessing: boolean;
|
|
11
12
|
shouldShowButtons: boolean;
|
|
12
13
|
currentButtonsBlock: BotInputButtonsBlock | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBotFlow.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useBotFlow.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"useBotFlow.d.ts","sourceRoot":"","sources":["../../../src/hooks/conversation/useBotFlow.ts"],"names":[],"mappings":"AAKA,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAa9B,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,aAAa,CAAC;AAEtD,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB;AAsBD,eAAO,MAAM,UAAU,GAAI,kCAGxB,gBAAgB;;;;;;;;6BAmHqB,MAAM;;CAkD7C,CAAC"}
|