@droppii-org/chat-sdk 0.8.1 → 0.8.3
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/canned-response/cannedTrigger.d.ts +2 -0
- package/dist/components/canned-response/cannedTrigger.d.ts.map +1 -0
- package/dist/components/canned-response/cannedTrigger.js +3 -0
- package/dist/components/canned-response/insertCannedContent.js +2 -2
- package/dist/components/conversation/ConversationByGroupItem.js +1 -1
- package/dist/components/conversation/ConversationBySessionItem.js +4 -4
- package/dist/components/conversation/DeskConversationList.d.ts.map +1 -1
- package/dist/components/conversation/DeskConversationList.js +6 -4
- package/dist/components/conversation/folderEmptyState.d.ts.map +1 -1
- package/dist/components/conversation/folderEmptyState.js +2 -0
- package/dist/components/conversation/internalNotePreview.d.ts +1 -1
- package/dist/components/conversation/internalNotePreview.d.ts.map +1 -1
- package/dist/components/conversation/internalNotePreview.js +22 -3
- package/dist/components/conversation/listHeading.d.ts +1 -1
- package/dist/components/conversation/listHeading.d.ts.map +1 -1
- package/dist/components/conversation/listHeading.js +7 -1
- package/dist/components/conversation/rowTime.d.ts +2 -2
- package/dist/components/conversation/rowTime.d.ts.map +1 -1
- package/dist/components/conversation/rowTime.js +2 -4
- package/dist/components/conversation-detail/ConversationDetailInput.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationDetailInput.js +8 -3
- package/dist/components/conversation-detail/ConversationMessageList.d.ts.map +1 -1
- package/dist/components/conversation-detail/ConversationMessageList.js +6 -3
- package/dist/components/conversation-detail/bot/BotMenuSheet.d.ts.map +1 -1
- package/dist/components/conversation-detail/bot/BotMenuSheet.js +1 -1
- package/dist/components/conversation-inbox/ConversationInboxList.d.ts.map +1 -1
- package/dist/components/conversation-inbox/ConversationInboxList.js +4 -0
- package/dist/components/conversation-inbox/InboxBootStatus.d.ts.map +1 -1
- package/dist/components/conversation-inbox/InboxBootStatus.js +10 -2
- package/dist/components/group/CreateGroupForm.d.ts.map +1 -1
- package/dist/components/group/CreateGroupForm.js +2 -1
- package/dist/components/group/CreateGroupFormCrmView.d.ts.map +1 -1
- package/dist/components/group/CreateGroupFormCrmView.js +1 -1
- package/dist/components/group/GroupMemberPickerCrm.d.ts.map +1 -1
- package/dist/components/group/GroupMemberPickerCrm.js +1 -1
- package/dist/components/media-collection/FileCollection.d.ts.map +1 -1
- package/dist/components/media-collection/FileCollection.js +4 -3
- package/dist/components/media-collection/ImageCollection.d.ts.map +1 -1
- package/dist/components/media-collection/ImageCollection.js +2 -1
- package/dist/components/media-collection/LinkCollection.d.ts.map +1 -1
- package/dist/components/media-collection/LinkCollection.js +14 -26
- package/dist/components/media-collection/VideoCollection.d.ts.map +1 -1
- package/dist/components/media-collection/VideoCollection.js +2 -1
- package/dist/components/media-resources/FileResourceList.js +2 -2
- package/dist/components/media-resources/ResourceScrollContainer.d.ts.map +1 -1
- package/dist/components/media-resources/ResourceScrollContainer.js +34 -2
- package/dist/components/message/GroupMembersDrawer.d.ts.map +1 -1
- package/dist/components/message/GroupMembersDrawer.js +2 -3
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +15 -4
- package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
- package/dist/components/message/footer/ActionBar.js +10 -44
- package/dist/components/message/footer/CannedResponsePlugin.d.ts.map +1 -1
- package/dist/components/message/footer/CannedResponsePlugin.js +3 -2
- package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
- package/dist/components/message/footer/EnterHandler.js +10 -47
- package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
- package/dist/components/message/footer/FilePreview.js +2 -1
- package/dist/components/message/footer/LinkInputPreview.d.ts +1 -1
- package/dist/components/message/footer/LinkInputPreview.d.ts.map +1 -1
- package/dist/components/message/footer/LinkInputPreview.js +8 -1
- package/dist/components/message/footer/MediaUploadButtons.d.ts.map +1 -1
- package/dist/components/message/footer/MediaUploadButtons.js +4 -7
- package/dist/components/message/footer/index.d.ts.map +1 -1
- package/dist/components/message/footer/index.js +57 -16
- package/dist/components/message/footer/mention/useMentionOptions.d.ts.map +1 -1
- package/dist/components/message/footer/mention/useMentionOptions.js +2 -6
- package/dist/components/message/footer/resetEditorAfterSend.d.ts +7 -0
- package/dist/components/message/footer/resetEditorAfterSend.d.ts.map +1 -0
- package/dist/components/message/footer/resetEditorAfterSend.js +62 -0
- package/dist/components/message/groupMemberMenuCrm.d.ts +4 -4
- package/dist/components/message/groupMemberMenuCrm.d.ts.map +1 -1
- package/dist/components/message/groupMemberMenuCrm.js +73 -60
- package/dist/components/message/item/FileMessage.js +2 -2
- package/dist/components/message/item/SystemLogMessage.d.ts.map +1 -1
- package/dist/components/message/item/SystemLogMessage.js +5 -2
- package/dist/components/search-conversation/SearchConversationAsGroups.js +1 -1
- package/dist/components/search-conversation/SearchConversationAsMessages.js +1 -1
- package/dist/components/search-conversation/SearchConversationMyInbox.js +1 -1
- package/dist/components/session/SessionFolderList.d.ts +4 -3
- package/dist/components/session/SessionFolderList.d.ts.map +1 -1
- package/dist/components/session/SessionFolderList.js +14 -5
- package/dist/components/thread/GroupInfoBodyCrm.d.ts.map +1 -1
- package/dist/components/thread/GroupInfoBodyCrm.js +2 -2
- package/dist/components/thread/GroupThreadInfo.d.ts.map +1 -1
- package/dist/components/thread/GroupThreadInfo.js +2 -6
- package/dist/components/thread/ManualAssignPopover.d.ts.map +1 -1
- package/dist/components/thread/ManualAssignPopover.js +6 -8
- package/dist/components/thread/SessionDetailCard.d.ts.map +1 -1
- package/dist/components/thread/SessionDetailCard.js +3 -3
- package/dist/components/thread/SessionSection.d.ts.map +1 -1
- package/dist/components/thread/SessionSection.js +3 -9
- package/dist/components/thread/SessionTagPicker.d.ts +3 -1
- package/dist/components/thread/SessionTagPicker.d.ts.map +1 -1
- package/dist/components/thread/SessionTagPicker.js +2 -2
- package/dist/components/thread/sessionDateFormat.d.ts +2 -0
- package/dist/components/thread/sessionDateFormat.d.ts.map +1 -1
- package/dist/components/thread/sessionDateFormat.js +6 -0
- package/dist/constants/dateFormat.d.ts +2 -0
- package/dist/constants/dateFormat.d.ts.map +1 -0
- package/dist/constants/dateFormat.js +2 -0
- package/dist/hooks/common/useFetchUrlMetadata.d.ts +1 -0
- package/dist/hooks/common/useFetchUrlMetadata.d.ts.map +1 -1
- package/dist/hooks/conversation/useBotFlow.d.ts.map +1 -1
- package/dist/hooks/conversation/useBotFlow.js +64 -12
- package/dist/hooks/conversation/useCloseBotSession.d.ts +2 -0
- package/dist/hooks/conversation/useCloseBotSession.d.ts.map +1 -1
- package/dist/hooks/conversation/useCloseBotSession.js +17 -1
- package/dist/hooks/global/useGlobalEvent.d.ts.map +1 -1
- package/dist/hooks/global/useGlobalEvent.js +148 -16
- package/dist/hooks/global/useLoginHealth.d.ts +3 -0
- package/dist/hooks/global/useLoginHealth.d.ts.map +1 -0
- package/dist/hooks/global/useLoginHealth.js +55 -0
- package/dist/hooks/group/useCreateGroup.d.ts.map +1 -1
- package/dist/hooks/group/useCreateGroup.js +75 -6
- package/dist/hooks/init/useChatBootPhase.d.ts +2 -0
- package/dist/hooks/init/useChatBootPhase.d.ts.map +1 -1
- package/dist/hooks/init/useChatBootPhase.js +11 -6
- package/dist/hooks/message/useMessage.d.ts.map +1 -1
- package/dist/hooks/message/useMessage.js +97 -28
- package/dist/hooks/message/usePinnedMessages.d.ts.map +1 -1
- package/dist/hooks/message/usePinnedMessages.js +13 -2
- package/dist/hooks/message/useRevokeMessage.d.ts.map +1 -1
- package/dist/hooks/message/useRevokeMessage.js +25 -0
- package/dist/hooks/message/useSendMessage.d.ts +15 -12
- package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
- package/dist/hooks/message/useSendMessage.js +199 -133
- package/dist/hooks/search/useSearchMessage.d.ts.map +1 -1
- package/dist/hooks/search/useSearchMessage.js +57 -3
- package/dist/hooks/session/useConversationSessionState.d.ts.map +1 -1
- package/dist/hooks/session/useConversationSessionState.js +4 -1
- package/dist/hooks/session/useGetSession.d.ts.map +1 -1
- package/dist/hooks/session/useGetSession.js +2 -0
- package/dist/hooks/session/useGetSessionList.d.ts +235 -0
- package/dist/hooks/session/useGetSessionList.d.ts.map +1 -0
- package/dist/hooks/session/useGetSessionList.js +23 -0
- package/dist/hooks/session/useSessionLatestPreview.d.ts.map +1 -1
- package/dist/hooks/session/useSessionLatestPreview.js +34 -4
- package/dist/hooks/user/useAuth.d.ts +1 -1
- package/dist/hooks/user/useAuth.d.ts.map +1 -1
- package/dist/hooks/user/useAuth.js +31 -15
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/locales/vi/boot.json +5 -1
- package/dist/locales/vi/common.json +35 -15
- 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 +6 -0
- package/dist/screens/desk-message/DeskBootCard.d.ts.map +1 -1
- package/dist/screens/desk-message/DeskBootCard.js +6 -4
- package/dist/store/boot.d.ts +5 -0
- package/dist/store/boot.d.ts.map +1 -1
- package/dist/store/boot.js +11 -1
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +5 -1
- package/dist/store/session.d.ts +1 -13
- package/dist/store/session.d.ts.map +1 -1
- package/dist/store/session.js +10 -9
- package/dist/store/sessionFolder.d.ts +2 -0
- package/dist/store/sessionFolder.d.ts.map +1 -1
- package/dist/store/sessionFolder.js +3 -1
- package/dist/store/type.d.ts +7 -1
- package/dist/store/type.d.ts.map +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/types/chat.d.ts +1 -1
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +4 -1
- package/dist/utils/download.d.ts +10 -0
- package/dist/utils/download.d.ts.map +1 -1
- package/dist/utils/download.js +51 -0
- package/dist/utils/fileValidation.d.ts +7 -0
- package/dist/utils/fileValidation.d.ts.map +1 -1
- package/dist/utils/fileValidation.js +37 -13
- package/dist/utils/latestMessagePreviewable.d.ts +2 -0
- package/dist/utils/latestMessagePreviewable.d.ts.map +1 -0
- package/dist/utils/latestMessagePreviewable.js +18 -0
- package/dist/utils/mentionMembers.d.ts +3 -0
- package/dist/utils/mentionMembers.d.ts.map +1 -0
- package/dist/utils/mentionMembers.js +29 -0
- package/dist/utils/messageLog.d.ts +2 -2
- package/dist/utils/messageLog.d.ts.map +1 -1
- package/dist/utils/messageLog.js +129 -40
- package/dist/utils/notifiableMessage.d.ts +7 -0
- package/dist/utils/notifiableMessage.d.ts.map +1 -0
- package/dist/utils/notifiableMessage.js +26 -0
- package/dist/utils/withSdkTimeout.d.ts +11 -0
- package/dist/utils/withSdkTimeout.d.ts.map +1 -0
- package/dist/utils/withSdkTimeout.js +30 -0
- package/package.json +1 -1
|
@@ -3,36 +3,24 @@ import { Dropdown, Empty, Spin } from "antd";
|
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import useConversationStore from "../../store/conversation";
|
|
5
5
|
import { useSearchMessage } from "../../hooks/search/useSearchMessage";
|
|
6
|
-
import { useCallback
|
|
6
|
+
import { useCallback } from "react";
|
|
7
7
|
import dayjs from "dayjs";
|
|
8
|
+
import { LIBRARY_DATE_HEADER_FORMAT } from "../../constants/dateFormat";
|
|
8
9
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
9
10
|
import { MessageType, SessionType } from "@droppii-org/wasm-client-sdk";
|
|
10
11
|
import { Icon } from "../../components/icon";
|
|
11
12
|
import { DChatSDK } from "../../constants/sdk";
|
|
12
13
|
import { useChatContext } from "../../context/ChatContext";
|
|
13
14
|
import { message as antdMessage } from "antd";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.then((res) => {
|
|
24
|
-
var _a;
|
|
25
|
-
if ((_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.title) {
|
|
26
|
-
setTitle(res.data.title);
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
.catch(() => {
|
|
30
|
-
setTitle("");
|
|
31
|
-
})
|
|
32
|
-
.finally(() => {
|
|
33
|
-
setIsLoading(false);
|
|
34
|
-
});
|
|
35
|
-
}, [url]);
|
|
15
|
+
import { useFetchUrlMetadata } from "../../hooks/common/useFetchUrlMetadata";
|
|
16
|
+
import { parseUrlMetadata } from "../../utils/common";
|
|
17
|
+
const LinkPreview = ({ url, messageMetadata, }) => {
|
|
18
|
+
// Title saved on the message wins; otherwise ask the in-house metadata
|
|
19
|
+
// endpoint instead of a third-party service.
|
|
20
|
+
const hasMessageTitle = Boolean(messageMetadata === null || messageMetadata === void 0 ? void 0 : messageMetadata.title);
|
|
21
|
+
const { data, isLoading: isFetching } = useFetchUrlMetadata(url, !hasMessageTitle);
|
|
22
|
+
const title = (messageMetadata === null || messageMetadata === void 0 ? void 0 : messageMetadata.title) || ((data === null || data === void 0 ? void 0 : data.isEmpty) ? "" : data === null || data === void 0 ? void 0 : data.title) || "";
|
|
23
|
+
const isLoading = !hasMessageTitle && isFetching;
|
|
36
24
|
return (_jsxs("a", { href: url, target: "_blank", rel: "noopener noreferrer", "data-cp-name": "LinkPreview", className: "flex flex-col truncate text-[var(--dc-color-link)] cursor-pointer", title: title || url, children: [isLoading && (_jsx("span", { className: "font-medium truncate text-gray-900", children: url })), !isLoading &&
|
|
37
25
|
(title ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "font-medium truncate text-gray-900", children: title }), _jsx("span", { className: "text-sm text-gray-500 truncate", children: url })] })) : (_jsx("span", { className: "font-medium truncate text-gray-900", children: url })))] }));
|
|
38
26
|
};
|
|
@@ -67,7 +55,7 @@ const LinkCollection = ({ onClose }) => {
|
|
|
67
55
|
},
|
|
68
56
|
});
|
|
69
57
|
const renderItem = useCallback((date, items) => {
|
|
70
|
-
return (_jsxs("div", { className: "px-3", children: [_jsx("span", { className: "text-sm font-medium text-gray-500 px-3", children: dayjs(date).format(
|
|
58
|
+
return (_jsxs("div", { className: "px-3", children: [_jsx("span", { className: "text-sm font-medium text-gray-500 px-3", children: dayjs(date).format(LIBRARY_DATE_HEADER_FORMAT) }), _jsx("div", { className: "flex flex-col gap-1 mt-2", children: items.map((item) => {
|
|
71
59
|
var _a, _b, _c;
|
|
72
60
|
const urls = ((_b = JSON.parse(((_a = item === null || item === void 0 ? void 0 : item.chatLog) === null || _a === void 0 ? void 0 : _a.content) || "{}")) === null || _b === void 0 ? void 0 : _b.urls) || [];
|
|
73
61
|
const menuItems = [
|
|
@@ -78,8 +66,8 @@ const LinkCollection = ({ onClose }) => {
|
|
|
78
66
|
},
|
|
79
67
|
];
|
|
80
68
|
return (_jsx("div", { children: urls.map((url, index) => {
|
|
81
|
-
var _a;
|
|
82
|
-
return (_jsxs("div", { className: "bg-gray-100 flex gap-2 items-center p-2 mb-1", children: [_jsx("div", { className: "flex items-center justify-center shrink-0", children: _jsx(Icon, { icon: "link-b", size: 16 }) }), _jsx("div", { className: "flex-1 min-w-0", children: _jsx(LinkPreview, { url: url }) }), _jsx(Dropdown, { menu: { items: menuItems }, trigger: ["click"], placement: "bottomRight", children: _jsx("div", { className: "flex items-center justify-center shrink-0 cursor-pointer p-1 hover:bg-gray-200 rounded ml-2", onClick: (e) => e.stopPropagation(), children: _jsx(Icon, { icon: "more-horizontal-b", size: 16 }) }) })] }, `${(
|
|
69
|
+
var _a, _b;
|
|
70
|
+
return (_jsxs("div", { className: "bg-gray-100 flex gap-2 items-center p-2 mb-1", children: [_jsx("div", { className: "flex items-center justify-center shrink-0", children: _jsx(Icon, { icon: "link-b", size: 16 }) }), _jsx("div", { className: "flex-1 min-w-0", children: _jsx(LinkPreview, { url: url, messageMetadata: index === 0 ? parseUrlMetadata((_a = item.chatLog) === null || _a === void 0 ? void 0 : _a.ex) : undefined }) }), _jsx(Dropdown, { menu: { items: menuItems }, trigger: ["click"], placement: "bottomRight", children: _jsx("div", { className: "flex items-center justify-center shrink-0 cursor-pointer p-1 hover:bg-gray-200 rounded ml-2", onClick: (e) => e.stopPropagation(), children: _jsx(Icon, { icon: "more-horizontal-b", size: 16 }) }) })] }, `${(_b = item.chatLog) === null || _b === void 0 ? void 0 : _b.clientMsgID}-${index}`));
|
|
83
71
|
}) }, (_c = item.chatLog) === null || _c === void 0 ? void 0 : _c.clientMsgID));
|
|
84
72
|
}) })] }, date));
|
|
85
73
|
}, []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoCollection.d.ts","sourceRoot":"","sources":["../../../src/components/media-collection/VideoCollection.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VideoCollection.d.ts","sourceRoot":"","sources":["../../../src/components/media-collection/VideoCollection.tsx"],"names":[],"mappings":"AAkBA,QAAA,MAAM,eAAe,+CAqGpB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -5,6 +5,7 @@ import InfiniteScroll from "react-infinite-scroll-component";
|
|
|
5
5
|
import { Empty, Image, Spin } from "antd";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import dayjs from "dayjs";
|
|
8
|
+
import { LIBRARY_DATE_HEADER_FORMAT } from "../../constants/dateFormat";
|
|
8
9
|
import useConversationStore from "../../store/conversation";
|
|
9
10
|
import { useBoolean } from "ahooks";
|
|
10
11
|
import { images } from "../../constants/images";
|
|
@@ -29,7 +30,7 @@ const VideoCollection = () => {
|
|
|
29
30
|
setTrue();
|
|
30
31
|
};
|
|
31
32
|
const renderItem = (date, items) => {
|
|
32
|
-
return (_jsxs("div", { className: "mb-2", children: [_jsx("span", { className: "text-sm font-medium text-gray-500 px-3", children: dayjs(date).format(
|
|
33
|
+
return (_jsxs("div", { className: "mb-2", children: [_jsx("span", { className: "text-sm font-medium text-gray-500 px-3", children: dayjs(date).format(LIBRARY_DATE_HEADER_FORMAT) }), _jsx("div", { className: "grid grid-cols-3 justify-start gap-px py-2", children: items.map((item) => {
|
|
33
34
|
var _a, _b, _c, _d;
|
|
34
35
|
const videoContent = parseMessageContent((_a = item === null || item === void 0 ? void 0 : item.chatLog) === null || _a === void 0 ? void 0 : _a.content);
|
|
35
36
|
const globalIndex = (_c = videoIndexByMsgId.get((_b = item.chatLog) === null || _b === void 0 ? void 0 : _b.clientMsgID)) !== null && _c !== void 0 ? _c : 0;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { documentIcon } from "../../assets/svg";
|
|
4
4
|
import { parseMessageContent, renderFileSize, shortenFileName, } from "../../utils/common";
|
|
5
|
-
import {
|
|
5
|
+
import { openFileOrDownload } from "../../utils/download";
|
|
6
6
|
import { MediaResourceTabKey } from "./constants";
|
|
7
7
|
import ResourceScrollContainer from "./ResourceScrollContainer";
|
|
8
8
|
import { useResourceTab } from "./useResourceTab";
|
|
@@ -11,7 +11,7 @@ const FileResourceList = () => {
|
|
|
11
11
|
return (_jsx(ResourceScrollContainer, Object.assign({ "data-cp-name": "FileResourceList" }, containerProps, { itemCount: items.length, children: _jsx("div", { className: "flex flex-col gap-2 p-3", children: items.map((item) => {
|
|
12
12
|
var _a, _b;
|
|
13
13
|
const fileContent = parseMessageContent((_a = item === null || item === void 0 ? void 0 : item.chatLog) === null || _a === void 0 ? void 0 : _a.content);
|
|
14
|
-
return (_jsxs("div", { className: "flex w-full cursor-pointer items-center gap-2 rounded-[12px] bg-[#f5f5f5]/20 p-3", onClick: () =>
|
|
14
|
+
return (_jsxs("div", { className: "flex w-full cursor-pointer items-center gap-2 rounded-[12px] bg-[#f5f5f5]/20 p-3", onClick: () => void openFileOrDownload((fileContent === null || fileContent === void 0 ? void 0 : fileContent.sourceUrl) || "", (fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) || ""), children: [_jsx("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center [&>svg]:h-full [&>svg]:w-auto", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[16px] font-medium leading-[1.6] text-gray-900", children: shortenFileName(fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileName) }), _jsx("span", { className: "text-[13px] font-normal leading-[1.6] text-gray-400", children: renderFileSize((fileContent === null || fileContent === void 0 ? void 0 : fileContent.fileSize) || 0) })] })] }, (_b = item.chatLog) === null || _b === void 0 ? void 0 : _b.clientMsgID));
|
|
15
15
|
}) }) })));
|
|
16
16
|
};
|
|
17
17
|
export default FileResourceList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceScrollContainer.d.ts","sourceRoot":"","sources":["../../../src/components/media-resources/ResourceScrollContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"ResourceScrollContainer.d.ts","sourceRoot":"","sources":["../../../src/components/media-resources/ResourceScrollContainer.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAA+B,MAAM,OAAO,CAAC;AAI/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAQD,QAAA,MAAM,uBAAuB,GAAI,+GAU9B,4BAA4B,4CAmF9B,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect } from "react";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
5
5
|
import { Button, Spin } from "antd";
|
|
6
6
|
import { useTranslation } from "react-i18next";
|
|
@@ -14,6 +14,38 @@ const ResourceScrollContainer = ({ tabKey, itemCount, isLoading, isError, hasNex
|
|
|
14
14
|
fetchNextPage();
|
|
15
15
|
}
|
|
16
16
|
}, [isEmptyWithMorePages, isFetchingNextPage, fetchNextPage]);
|
|
17
|
+
// A page that fits without scrolling never fires the scroll trigger, so
|
|
18
|
+
// keep loading until the content overflows or the pages run out.
|
|
19
|
+
// The panel is mounted inside a closed drawer (display:none, 0 height), so a
|
|
20
|
+
// hidden container must not trigger background fetching; the resize tick
|
|
21
|
+
// re-checks once the drawer becomes visible.
|
|
22
|
+
const scrollRef = useRef(null);
|
|
23
|
+
const [resizeTick, setResizeTick] = useState(0);
|
|
24
|
+
const hasContainer = !isLoading && !isError && itemCount > 0;
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const el = scrollRef.current;
|
|
27
|
+
if (!el || typeof ResizeObserver === "undefined")
|
|
28
|
+
return;
|
|
29
|
+
const observer = new ResizeObserver(() => setResizeTick((n) => n + 1));
|
|
30
|
+
observer.observe(el);
|
|
31
|
+
return () => observer.disconnect();
|
|
32
|
+
}, [hasContainer]);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const el = scrollRef.current;
|
|
35
|
+
if (!el || !hasNextPage || isFetchingNextPage || isError)
|
|
36
|
+
return;
|
|
37
|
+
if (!el.isConnected || el.clientHeight === 0)
|
|
38
|
+
return;
|
|
39
|
+
if (el.scrollHeight <= el.clientHeight)
|
|
40
|
+
fetchNextPage();
|
|
41
|
+
}, [
|
|
42
|
+
itemCount,
|
|
43
|
+
hasNextPage,
|
|
44
|
+
isFetchingNextPage,
|
|
45
|
+
isError,
|
|
46
|
+
fetchNextPage,
|
|
47
|
+
resizeTick,
|
|
48
|
+
]);
|
|
17
49
|
if (isLoading || isEmptyWithMorePages) {
|
|
18
50
|
return (_jsx("div", { className: "flex h-full items-center justify-center py-6", children: _jsx(Spin, {}) }));
|
|
19
51
|
}
|
|
@@ -24,6 +56,6 @@ const ResourceScrollContainer = ({ tabKey, itemCount, isLoading, isError, hasNex
|
|
|
24
56
|
return _jsx(ResourceEmptyState, { tabKey: tabKey });
|
|
25
57
|
}
|
|
26
58
|
const scrollableId = `resource-scroll-${tabKey}`;
|
|
27
|
-
return (_jsx("div", { id: scrollableId, "data-cp-name": "ResourceScrollContainer", className: "h-full overflow-auto", children: _jsx(InfiniteScroll, { dataLength: itemCount, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx(LoadingIndicator, {}), scrollableTarget: scrollableId, children: children }) }));
|
|
59
|
+
return (_jsx("div", { ref: scrollRef, id: scrollableId, "data-cp-name": "ResourceScrollContainer", className: "h-full overflow-auto", children: _jsx(InfiniteScroll, { dataLength: itemCount, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx(LoadingIndicator, {}), scrollableTarget: scrollableId, children: children }) }));
|
|
28
60
|
};
|
|
29
61
|
export default ResourceScrollContainer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GroupMembersDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/message/GroupMembersDrawer.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA8B/C,UAAU,uBAAuB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA6BD,QAAA,MAAM,kBAAkB,GAAI,wDAKzB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"GroupMembersDrawer.d.ts","sourceRoot":"","sources":["../../../src/components/message/GroupMembersDrawer.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AA8B/C,UAAU,uBAAuB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA6BD,QAAA,MAAM,kBAAkB,GAAI,wDAKzB,uBAAuB,4CAwsBzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -250,7 +250,7 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
250
250
|
});
|
|
251
251
|
message.success(member.isAdmin
|
|
252
252
|
? t("remove_from_admin_success")
|
|
253
|
-
: t("assign_as_admin_success"));
|
|
253
|
+
: t("assign_as_admin_success", { name: member.nickname }));
|
|
254
254
|
// Optimistically patch the role in place instead of refetching the
|
|
255
255
|
// whole list — a full refetch replaces every member's object
|
|
256
256
|
// identity and re-sorts, which visibly re-renders/reorders rows that
|
|
@@ -283,7 +283,7 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
283
283
|
groupID,
|
|
284
284
|
newOwnerUserID: confirmMemberAction.member.userID,
|
|
285
285
|
});
|
|
286
|
-
message.success(t("transfer_owner_success"));
|
|
286
|
+
message.success(t("transfer_owner_success", { name: confirmMemberAction.member.nickname }));
|
|
287
287
|
void refetch();
|
|
288
288
|
}
|
|
289
289
|
catch (error) {
|
|
@@ -314,7 +314,6 @@ const GroupMembersDrawer = ({ groupID, conversationId, currentSession, disabled
|
|
|
314
314
|
}, [groupID]);
|
|
315
315
|
const renderCrmPanel = (closeOnEscape) => (_jsx(GroupMembersPanelCrm, { totalCount: totalCount, members: sortedMembers.map((member) => isRealGroup ? member : Object.assign(Object.assign({}, member), { roleLabel: "" })), isRealGroup: isRealGroup, isLoading: isLoading || (isSearchActive && isSearching), isLoadingMore: isLoadingMore && !isSearchActive, onListScroll: handleListScroll, error: error, isSearchActive: isSearchActive, search: search, onSearchChange: setSearch, canAddMember: canAddMember, onAddMember: () => setShowAddMember(true), onClose: handleCloseDrawer, closeOnEscape: closeOnEscape, buildMenu: (member) => buildCrmMemberMenu({
|
|
316
316
|
member,
|
|
317
|
-
isRealGroup,
|
|
318
317
|
permissions,
|
|
319
318
|
actingIsOwner,
|
|
320
319
|
leaveBlockedReason,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,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,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAChE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/message/MessageList.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,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,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAChE,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1E,kGAAkG;IAClG,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;IACpC,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,WAAW,GAAI,OAAO,gBAAgB,4CAoc3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -86,6 +86,7 @@ const MessageList = (props) => {
|
|
|
86
86
|
const { revokeMessage, loading: isRevoking } = useRevokeMessage();
|
|
87
87
|
const { pinMessage, unpinMessage } = usePinMessage();
|
|
88
88
|
const pinnedTotalCount = useConversationStore((state) => state.pinnedTotalCount);
|
|
89
|
+
const pinnedBackendTotalCount = useConversationStore((state) => state.pinnedBackendTotalCount);
|
|
89
90
|
const pinnedRemainingCount = useConversationStore((state) => state.pinnedRemainingCount);
|
|
90
91
|
const [pinLimitModalOpen, setPinLimitModalOpen] = useState(false);
|
|
91
92
|
const { rawGroupId, latestConversationSession, refetchConversationSessions } = useConversationSessionState({
|
|
@@ -136,13 +137,23 @@ const MessageList = (props) => {
|
|
|
136
137
|
closeConfirmRevoke();
|
|
137
138
|
}, [closeConfirmRevoke]);
|
|
138
139
|
const onRevokeMessage = useCallback(async () => {
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
try {
|
|
141
|
+
await revokeMessage((conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID) || "", selectedItem || "");
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// Keep the cause visible: the toast alone hides why core rejected it.
|
|
145
|
+
console.warn("revokeMessage failed", error);
|
|
146
|
+
toastMessage.error(t("revoke_message_failed"));
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
handleCloseRevoke();
|
|
150
|
+
}
|
|
141
151
|
}, [
|
|
142
152
|
conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID,
|
|
143
153
|
selectedItem,
|
|
144
154
|
revokeMessage,
|
|
145
155
|
handleCloseRevoke,
|
|
156
|
+
t,
|
|
146
157
|
]);
|
|
147
158
|
const onPressQuoteMessage = useCallback((clientMsgID) => {
|
|
148
159
|
const hasMessage = loadState.messageList.some((msg) => msg.clientMsgID === clientMsgID);
|
|
@@ -160,7 +171,7 @@ const MessageList = (props) => {
|
|
|
160
171
|
onPressQuoteMessage(firstUnreadMessageId);
|
|
161
172
|
}, [firstUnreadMessageId, markDividerSeen, onPressQuoteMessage]);
|
|
162
173
|
const handlePinMessage = useCallback(async (message) => {
|
|
163
|
-
if (pinnedRemainingCount <= 0 &&
|
|
174
|
+
if (pinnedRemainingCount <= 0 && pinnedBackendTotalCount > 0) {
|
|
164
175
|
setPinLimitModalOpen(true);
|
|
165
176
|
return;
|
|
166
177
|
}
|
|
@@ -171,7 +182,7 @@ const MessageList = (props) => {
|
|
|
171
182
|
catch (_a) {
|
|
172
183
|
toastMessage.error(t("pin_message_failed"));
|
|
173
184
|
}
|
|
174
|
-
}, [conversationId, pinMessage, pinnedRemainingCount,
|
|
185
|
+
}, [conversationId, pinMessage, pinnedRemainingCount, pinnedBackendTotalCount, t]);
|
|
175
186
|
const handleUnpinMessage = useCallback(async (message) => {
|
|
176
187
|
try {
|
|
177
188
|
await unpinMessage(conversationId, message.clientMsgID);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ActionBar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ActionBar.tsx"],"names":[],"mappings":"AAiBA,UAAU,cAAc;IAEtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,QAAA,MAAM,SAAS,GAAI,gCAAwC,cAAc,4CA2HxE,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -8,13 +8,11 @@ import { useTranslation } from "react-i18next";
|
|
|
8
8
|
import { Icon } from "../../../components/icon";
|
|
9
9
|
import useAuthStore from "../../../store/auth";
|
|
10
10
|
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
11
|
-
import { $
|
|
11
|
+
import { $getRoot } from "lexical";
|
|
12
12
|
import { $generateHtmlFromNodes } from "@lexical/html";
|
|
13
|
-
import { $isListNode, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, } from "@lexical/list";
|
|
14
|
-
import { $isQuoteNode } from "@lexical/rich-text";
|
|
15
13
|
import { useMessageFooterContext } from ".";
|
|
16
14
|
import MediaActions from "./MediaActions";
|
|
17
|
-
import {
|
|
15
|
+
import { resetEditorAfterSend, resetEditorIfUnchanged } from "./resetEditorAfterSend";
|
|
18
16
|
import useConversationStore from "../../../store/conversation";
|
|
19
17
|
import { extractMentions } from "./mention/extractMentions";
|
|
20
18
|
const ActionBar = ({ formatOpen = false, onToggleFormat }) => {
|
|
@@ -39,53 +37,21 @@ const ActionBar = ({ formatOpen = false, onToggleFormat }) => {
|
|
|
39
37
|
});
|
|
40
38
|
if (canSend) {
|
|
41
39
|
const mentions = extractMentions(editor);
|
|
42
|
-
const
|
|
40
|
+
const sending = onSendMessage({
|
|
43
41
|
plainText,
|
|
44
42
|
richText,
|
|
45
43
|
type: listUploadFiles.length > 0 ? "file" : "text",
|
|
46
44
|
isInternal,
|
|
47
45
|
mentions,
|
|
48
46
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
// Clear only once the message is built; a failed build keeps the draft.
|
|
48
|
+
void Promise.resolve(sending).then((sent) => {
|
|
49
|
+
if (sent)
|
|
50
|
+
resetEditorIfUnchanged(editor, { plainText, richText });
|
|
51
|
+
});
|
|
52
|
+
return;
|
|
52
53
|
}
|
|
53
|
-
|
|
54
|
-
editor.update(() => {
|
|
55
|
-
const root = $getRoot();
|
|
56
|
-
root.clear();
|
|
57
|
-
const paragraph = $createParagraphNode();
|
|
58
|
-
root.append(paragraph);
|
|
59
|
-
paragraph.select();
|
|
60
|
-
const selection = $getSelection();
|
|
61
|
-
if ($isRangeSelection(selection)) {
|
|
62
|
-
const anchorNode = selection.anchor.getNode();
|
|
63
|
-
const topLevelNode = anchorNode.getTopLevelElementOrThrow();
|
|
64
|
-
const isListNode = $isListNode(topLevelNode);
|
|
65
|
-
const isQuoteNode = $isQuoteNode(topLevelNode);
|
|
66
|
-
const listType = isListNode ? topLevelNode.getListType() : undefined;
|
|
67
|
-
if (selection.hasFormat("bold")) {
|
|
68
|
-
selection.formatText("bold");
|
|
69
|
-
}
|
|
70
|
-
if (selection.hasFormat("italic")) {
|
|
71
|
-
selection.formatText("italic");
|
|
72
|
-
}
|
|
73
|
-
if (selection.hasFormat("strikethrough")) {
|
|
74
|
-
selection.formatText("strikethrough");
|
|
75
|
-
}
|
|
76
|
-
if (isQuoteNode) {
|
|
77
|
-
const paragraph = $createParagraphNode();
|
|
78
|
-
const children = topLevelNode.getChildren();
|
|
79
|
-
children.forEach((child) => paragraph.append(child));
|
|
80
|
-
topLevelNode.replace(paragraph);
|
|
81
|
-
}
|
|
82
|
-
if (isListNode && listType) {
|
|
83
|
-
editor.dispatchCommand(listType === "number"
|
|
84
|
-
? INSERT_ORDERED_LIST_COMMAND
|
|
85
|
-
: INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
});
|
|
54
|
+
resetEditorAfterSend(editor);
|
|
89
55
|
}, [editor, onSendMessage, canSend, isInternal, listUploadFiles.length]);
|
|
90
56
|
useEffect(() => {
|
|
91
57
|
return editor.registerUpdateListener(({ editorState }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CannedResponsePlugin.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/CannedResponsePlugin.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CannedResponsePlugin.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/CannedResponsePlugin.tsx"],"names":[],"mappings":"AAaA,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,QAwGrE"}
|
|
@@ -2,6 +2,7 @@ import { useEffect, useRef } from "react";
|
|
|
2
2
|
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
3
3
|
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, } from "lexical";
|
|
4
4
|
import { useMessageFooterContext } from ".";
|
|
5
|
+
import { CANNED_TRIGGER_BEFORE_CURSOR } from "../../../components/canned-response/cannedTrigger";
|
|
5
6
|
export function CannedResponseTriggerPlugin({ onOpen, onClose }) {
|
|
6
7
|
const [editor] = useLexicalComposerContext();
|
|
7
8
|
const { activeCannedIndex, setActiveCannedIndex, isOpenCanned, maxActiveCannedIndex, } = useMessageFooterContext();
|
|
@@ -21,8 +22,8 @@ export function CannedResponseTriggerPlugin({ onOpen, onClose }) {
|
|
|
21
22
|
const text = node.getTextContent();
|
|
22
23
|
const offset = anchor.offset;
|
|
23
24
|
const before = text.slice(0, offset);
|
|
24
|
-
// match #abc (
|
|
25
|
-
const match = before.match(
|
|
25
|
+
// match #abc or #abc-def (no space after the cursor)
|
|
26
|
+
const match = before.match(CANNED_TRIGGER_BEFORE_CURSOR);
|
|
26
27
|
lastBeforeRef.current = before;
|
|
27
28
|
if (match && dismissedRef.current !== before) {
|
|
28
29
|
onOpen(match[2] || "");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnterHandler.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/EnterHandler.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EnterHandler.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/EnterHandler.tsx"],"names":[],"mappings":"AAoBA,MAAM,CAAC,OAAO,UAAU,YAAY,SAkHnC"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
3
|
-
import { KEY_ENTER_COMMAND, COMMAND_PRIORITY_NORMAL, $
|
|
3
|
+
import { KEY_ENTER_COMMAND, COMMAND_PRIORITY_NORMAL, $createParagraphNode, $getRoot, } from "lexical";
|
|
4
4
|
import { clearComposerHistoryAfterUpdate } from "./clearComposerHistory";
|
|
5
|
+
import { resetEditorAfterSend, resetEditorIfUnchanged } from "./resetEditorAfterSend";
|
|
5
6
|
import { useEffect, useRef } from "react";
|
|
6
7
|
import { $generateHtmlFromNodes } from "@lexical/html";
|
|
7
|
-
import { $isListNode, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, } from "@lexical/list";
|
|
8
|
-
import { $isQuoteNode } from "@lexical/rich-text";
|
|
9
8
|
import { useMessageFooterContext } from ".";
|
|
10
9
|
import useConversationStore from "../../../store/conversation";
|
|
11
10
|
import emitter, { emit } from "../../../utils/events";
|
|
@@ -56,57 +55,21 @@ export default function EnterHandler() {
|
|
|
56
55
|
const canSend = hasQuote ? hasText : hasText || hasFiles;
|
|
57
56
|
if (canSend) {
|
|
58
57
|
const mentions = extractMentions(editor);
|
|
59
|
-
const
|
|
58
|
+
const sending = onSendMessage({
|
|
60
59
|
plainText,
|
|
61
60
|
richText,
|
|
62
61
|
type: hasFiles ? "file" : "text",
|
|
63
62
|
isInternal,
|
|
64
63
|
mentions,
|
|
65
64
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
// Clear only once the message is built; a failed build keeps the draft.
|
|
66
|
+
void Promise.resolve(sending).then((sent) => {
|
|
67
|
+
if (sent)
|
|
68
|
+
resetEditorIfUnchanged(editor, { plainText, richText });
|
|
69
|
+
});
|
|
70
|
+
return true;
|
|
69
71
|
}
|
|
70
|
-
|
|
71
|
-
editor.update(() => {
|
|
72
|
-
const root = $getRoot();
|
|
73
|
-
root.clear();
|
|
74
|
-
const paragraph = $createParagraphNode();
|
|
75
|
-
root.append(paragraph);
|
|
76
|
-
paragraph.select();
|
|
77
|
-
const selection = $getSelection();
|
|
78
|
-
if ($isRangeSelection(selection)) {
|
|
79
|
-
const anchorNode = selection.anchor.getNode();
|
|
80
|
-
const topLevelNode = anchorNode.getTopLevelElementOrThrow();
|
|
81
|
-
const isListNode = $isListNode(topLevelNode);
|
|
82
|
-
const isQuoteNode = $isQuoteNode(topLevelNode);
|
|
83
|
-
const listType = isListNode
|
|
84
|
-
? topLevelNode.getListType()
|
|
85
|
-
: undefined;
|
|
86
|
-
if (selection.hasFormat("bold")) {
|
|
87
|
-
selection.formatText("bold");
|
|
88
|
-
}
|
|
89
|
-
if (selection.hasFormat("italic")) {
|
|
90
|
-
selection.formatText("italic");
|
|
91
|
-
}
|
|
92
|
-
if (selection.hasFormat("strikethrough")) {
|
|
93
|
-
selection.formatText("strikethrough");
|
|
94
|
-
}
|
|
95
|
-
if (isQuoteNode) {
|
|
96
|
-
// Nếu đang là QuoteNode → chuyển về Paragraph (bình thường)
|
|
97
|
-
const paragraph = $createParagraphNode();
|
|
98
|
-
// copy con của quote sang paragraph
|
|
99
|
-
const children = topLevelNode.getChildren();
|
|
100
|
-
children.forEach((child) => paragraph.append(child));
|
|
101
|
-
topLevelNode.replace(paragraph);
|
|
102
|
-
}
|
|
103
|
-
if (isListNode && listType) {
|
|
104
|
-
editor.dispatchCommand(listType === "number"
|
|
105
|
-
? INSERT_ORDERED_LIST_COMMAND
|
|
106
|
-
: INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
});
|
|
72
|
+
resetEditorAfterSend(editor);
|
|
110
73
|
return true;
|
|
111
74
|
}
|
|
112
75
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/FilePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/FilePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AA+IlC,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,YAAY,GACb,EAAE;IACD,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC,kDAsBA;AAED,QAAA,MAAM,WAAW,+CAQhB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -45,7 +45,8 @@ const MediaThumb = ({ file, onRemove, onVideoReady }) => {
|
|
|
45
45
|
return () => URL.revokeObjectURL(url);
|
|
46
46
|
}, [file.originFileObj, file.url]);
|
|
47
47
|
const handleLoadedMetadata = (event) => {
|
|
48
|
-
|
|
48
|
+
const { duration: videoDuration } = event.currentTarget;
|
|
49
|
+
setDuration(Number.isFinite(videoDuration) ? videoDuration : null);
|
|
49
50
|
onVideoReady === null || onVideoReady === void 0 ? void 0 : onVideoReady(file.uid);
|
|
50
51
|
};
|
|
51
52
|
return (_jsxs("div", { "data-cp-name": "MediaThumb", className: "relative h-12 w-12 shrink-0", children: [isVideo ? (_jsx("video", { src: src, className: "h-12 w-12 rounded-lg object-cover", preload: "metadata", muted: true, onLoadedMetadata: handleLoadedMetadata })) : (_jsx("img", { src: src, alt: file.name, className: "h-12 w-12 rounded-lg object-cover" })), isLoading && (_jsx("div", { className: "absolute inset-0 flex items-center justify-center rounded-lg bg-black/60", children: _jsxs("span", { className: "text-xs font-semibold text-white", children: [percent, "%"] }) })), isVideo && duration !== null && (_jsx("div", { className: "absolute bottom-1 left-1/2 flex w-9 -translate-x-1/2 items-center justify-center rounded-xl bg-black/70 px-1 text-center text-[10px] font-normal leading-4 text-white", children: formatDuration(duration) })), _jsx(RemoveButton, { file: file, onRemove: onRemove })] }));
|
|
@@ -2,6 +2,6 @@ export interface LinkInputPreviewProps {
|
|
|
2
2
|
url: string;
|
|
3
3
|
onRemove: () => void;
|
|
4
4
|
}
|
|
5
|
-
declare const LinkInputPreview: ({ url, onRemove }: LinkInputPreviewProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare const LinkInputPreview: ({ url, onRemove }: LinkInputPreviewProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
6
6
|
export default LinkInputPreview;
|
|
7
7
|
//# sourceMappingURL=LinkInputPreview.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LinkInputPreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/LinkInputPreview.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,mBAAmB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"LinkInputPreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/LinkInputPreview.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,mBAAmB,qBAAqB,mDAwEjE,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -8,9 +8,16 @@ import { useTranslation } from "react-i18next";
|
|
|
8
8
|
const LinkInputPreview = ({ url, onRemove }) => {
|
|
9
9
|
const { t } = useTranslation("conversation-inbox");
|
|
10
10
|
const { data, isLoading, isError } = useFetchUrlMetadata(url);
|
|
11
|
+
// A link whose preview cannot be loaded is shown as a plain link only.
|
|
12
|
+
const hasNoPreview = isError ||
|
|
13
|
+
!!(data === null || data === void 0 ? void 0 : data.isEmpty) ||
|
|
14
|
+
(!!data && !data.title && !data.description && !data.image) ||
|
|
15
|
+
data === null;
|
|
16
|
+
if (!isLoading && hasNoPreview)
|
|
17
|
+
return null;
|
|
11
18
|
const handleOpen = () => {
|
|
12
19
|
openLink(url, t);
|
|
13
20
|
};
|
|
14
|
-
return (_jsxs("div", { "data-testid": "link-input-preview", "data-cp-name": "LinkInputPreview", className: "flex w-full shrink-0 items-center gap-2 overflow-hidden bg-blue-25 pr-2", children: [_jsxs("button", { type: "button", onClick: handleOpen, className: "flex min-w-0 flex-1 items-center gap-2 py-0 pl-0 text-left", children: [_jsx("div", { className: "flex h-[51px] w-[51px] shrink-0 items-center justify-center overflow-hidden bg-blue-25", children: isLoading ? (_jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-[var(--dc-color-primary)] border-t-transparent" })) : (data === null || data === void 0 ? void 0 : data.image) ? (_jsx("img", { src: data.image, alt: "", className: "h-full w-full object-cover" })) : (_jsx(AdaptiveIcon, { stroke: "link", font: "link-alt-b", size: 24, className: "text-[var(--dc-color-primary)]" })) }),
|
|
21
|
+
return (_jsxs("div", { "data-testid": "link-input-preview", "data-cp-name": "LinkInputPreview", className: "flex w-full shrink-0 items-center gap-2 overflow-hidden bg-blue-25 pr-2", children: [_jsxs("button", { type: "button", onClick: handleOpen, className: "flex min-w-0 flex-1 items-center gap-2 py-0 pl-0 text-left", children: [_jsx("div", { className: "flex h-[51px] w-[51px] shrink-0 items-center justify-center overflow-hidden bg-blue-25", children: isLoading ? (_jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-[var(--dc-color-primary)] border-t-transparent" })) : (data === null || data === void 0 ? void 0 : data.image) ? (_jsx("img", { src: data.image, alt: "", className: "h-full w-full object-cover" })) : (_jsx(AdaptiveIcon, { stroke: "link", font: "link-alt-b", size: 24, className: "text-[var(--dc-color-primary)]" })) }), _jsx("div", { className: "min-w-0 flex-1", children: isLoading ? (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: t("link_preview.loading") })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-gray-900", children: (data === null || data === void 0 ? void 0 : data.title) || getHostLabel(url) }), ((data === null || data === void 0 ? void 0 : data.description) || !(data === null || data === void 0 ? void 0 : data.title)) && (_jsx("p", { className: "truncate text-[13px] leading-[1.6] text-gray-400", children: (data === null || data === void 0 ? void 0 : data.description) || getHostLabel(url) }))] })) })] }), _jsx("button", { type: "button", onClick: onRemove, "data-testid": "link-input-preview-remove", className: "flex h-4 w-4 shrink-0 items-center justify-center", "aria-label": t("link_preview.remove"), children: _jsx(AdaptiveIcon, { stroke: "x", font: "close-b", size: 16, className: "text-gray-900" }) })] }));
|
|
15
22
|
};
|
|
16
23
|
export default LinkInputPreview;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaUploadButtons.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/MediaUploadButtons.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,UAAU,EAA0B,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"MediaUploadButtons.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/MediaUploadButtons.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,UAAU,EAA0B,MAAM,MAAM,CAAC;AAiC1E,UAAU,uBAAuB;IAC/B,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,aAAa,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAE9D,WAAW,CAAC,EAAE,OAAO,CAAC;IAGtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,eAAe,EACf,aAAa,EACb,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,WAAkB,EAClB,cAAsB,GACvB,EAAE,uBAAuB,2CA0FzB"}
|
|
@@ -3,7 +3,7 @@ import { Button, Upload, message as antdMessage } from "antd";
|
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
import { Icon } from "../../../components/icon";
|
|
5
5
|
import { StrokeIcon } from "../../../components/icon/StrokeIcon";
|
|
6
|
-
import { MAX_DOCUMENT_SIZE_MB, validateFile } from "../../../utils/fileValidation";
|
|
6
|
+
import { getAttachmentSizeError, getDocumentFormatError, getImageFormatError, MAX_DOCUMENT_SIZE_MB, validateFile, } from "../../../utils/fileValidation";
|
|
7
7
|
import { DOCUMENT_TYPES } from "./editorConfig";
|
|
8
8
|
import { mergePickedUploadFiles } from "./mergePickedUploadFiles";
|
|
9
9
|
const AttachIcon = (_jsx("svg", { width: "22", height: "22", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M15.6 10.0001V11.2001C15.6 14.5137 12.9137 17.2001 9.59998 17.2001C6.28626 17.2001 3.59998 14.5137 3.59998 11.2001V6.79999C3.59998 4.59085 5.39084 2.79999 7.59998 2.79999C9.8091 2.79999 11.6 4.59085 11.6 6.79999V11.2C11.6 12.3045 10.7045 13.2 9.59998 13.2C8.49542 13.2 7.59998 12.3045 7.59998 11.2V7.99999", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
@@ -13,7 +13,7 @@ export default function MediaUploadButtons({ listUploadFiles, onFilesChange, btn
|
|
|
13
13
|
listUploadFiles.some((f) => DOCUMENT_TYPES.includes(f.type || ""));
|
|
14
14
|
const beforeUploadImagesAndVideo = (file) => {
|
|
15
15
|
if (!acceptVideo && file.type.startsWith("video/")) {
|
|
16
|
-
antdMessage.error(t
|
|
16
|
+
antdMessage.error(getImageFormatError(t, file));
|
|
17
17
|
return Upload.LIST_IGNORE;
|
|
18
18
|
}
|
|
19
19
|
const validation = validateFile(file, t);
|
|
@@ -29,14 +29,11 @@ export default function MediaUploadButtons({ listUploadFiles, onFilesChange, btn
|
|
|
29
29
|
return Upload.LIST_IGNORE;
|
|
30
30
|
const isAllowed = DOCUMENT_TYPES.includes(file.type);
|
|
31
31
|
if (!isAllowed) {
|
|
32
|
-
antdMessage.error(t
|
|
32
|
+
antdMessage.error(getDocumentFormatError(t, file));
|
|
33
33
|
return Upload.LIST_IGNORE;
|
|
34
34
|
}
|
|
35
35
|
if (file.size / 1024 / 1024 > MAX_DOCUMENT_SIZE_MB) {
|
|
36
|
-
antdMessage.error(t
|
|
37
|
-
fileName: file.name,
|
|
38
|
-
maxSize: MAX_DOCUMENT_SIZE_MB,
|
|
39
|
-
}));
|
|
36
|
+
antdMessage.error(getAttachmentSizeError(t, file, "document", MAX_DOCUMENT_SIZE_MB));
|
|
40
37
|
return Upload.LIST_IGNORE;
|
|
41
38
|
}
|
|
42
39
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAEL,mBAAmB,EAEnB,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAwB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACjE;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAEL,mBAAmB,EAEnB,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAUtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAwB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACjE;AASD,eAAO,MAAM,oBAAoB,mDAc/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CAydpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|