@droppii-org/chat-sdk 0.1.49 → 0.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/svg/expand.d.ts +7 -0
- package/dist/assets/svg/expand.d.ts.map +1 -0
- package/dist/assets/svg/expand.js +2 -0
- package/dist/assets/svg/expand.tsx +44 -0
- package/dist/assets/svg/index.ts +1 -1
- package/dist/components/biz-inbox/BizThreadCard.d.ts.map +1 -1
- package/dist/components/biz-inbox/BizThreadCard.js +3 -11
- package/dist/components/biz-thread-detail/BizAttachmentPreview.d.ts.map +1 -1
- package/dist/components/biz-thread-detail/BizAttachmentPreview.js +1 -5
- package/dist/components/biz-thread-detail/BizLinkMessageCard.d.ts +3 -2
- package/dist/components/biz-thread-detail/BizLinkMessageCard.d.ts.map +1 -1
- package/dist/components/biz-thread-detail/BizLinkMessageCard.js +4 -8
- package/dist/components/biz-thread-detail/BizMessageContent.d.ts.map +1 -1
- package/dist/components/biz-thread-detail/BizMessageContent.js +59 -5
- package/dist/components/biz-thread-detail/BizMessageList.js +2 -2
- package/dist/components/biz-thread-detail/BizThreadDetailInput.d.ts.map +1 -1
- package/dist/components/biz-thread-detail/BizThreadDetailInput.js +20 -17
- package/dist/components/biz-thread-detail/BizVideoViewer.d.ts +8 -0
- package/dist/components/biz-thread-detail/BizVideoViewer.d.ts.map +1 -0
- package/dist/components/biz-thread-detail/BizVideoViewer.js +103 -0
- package/dist/components/biz-thread-detail/index.d.ts +0 -4
- package/dist/components/biz-thread-detail/index.d.ts.map +1 -1
- package/dist/components/biz-thread-detail/index.js +0 -2
- package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationBySessionItem.js +6 -5
- package/dist/components/conversation/ThreadCard.d.ts +14 -0
- package/dist/components/conversation/ThreadCard.d.ts.map +1 -0
- package/dist/components/conversation/ThreadCard.js +16 -0
- package/dist/components/media-collection/ImageCollection.d.ts.map +1 -1
- package/dist/components/media-collection/ImageCollection.js +3 -17
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +1 -7
- package/dist/components/message/footer/ComposerTextSyncPlugin.d.ts +6 -0
- package/dist/components/message/footer/ComposerTextSyncPlugin.d.ts.map +1 -0
- package/dist/components/message/footer/ComposerTextSyncPlugin.js +16 -0
- package/dist/components/message/footer/FilePreview.d.ts +3 -2
- package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
- package/dist/components/message/footer/FilePreview.js +61 -21
- package/dist/components/message/footer/LinkInputPreview.d.ts +7 -0
- package/dist/components/message/footer/LinkInputPreview.d.ts.map +1 -0
- package/dist/components/message/footer/LinkInputPreview.js +16 -0
- package/dist/components/message/footer/MediaActions.d.ts.map +1 -1
- package/dist/components/message/footer/MediaActions.js +8 -5
- package/dist/components/message/footer/index.d.ts.map +1 -1
- package/dist/components/message/footer/index.js +48 -35
- package/dist/components/message/item/FileMessage.d.ts +2 -2
- package/dist/components/message/item/FileMessage.d.ts.map +1 -1
- package/dist/components/message/item/FileMessage.js +20 -12
- package/dist/components/message/item/ImageMessage.d.ts.map +1 -1
- package/dist/components/message/item/ImageMessage.js +11 -15
- package/dist/components/message/item/LinkCard.d.ts +7 -0
- package/dist/components/message/item/LinkCard.d.ts.map +1 -0
- package/dist/components/message/item/LinkCard.js +17 -0
- package/dist/components/message/item/LinkText.d.ts +6 -0
- package/dist/components/message/item/LinkText.d.ts.map +1 -0
- package/dist/components/message/item/LinkText.js +13 -0
- package/dist/components/message/item/MergeImageMessage.d.ts +7 -0
- package/dist/components/message/item/MergeImageMessage.d.ts.map +1 -0
- package/dist/components/message/item/MergeImageMessage.js +30 -0
- package/dist/components/message/item/MessageBubble.d.ts +13 -0
- package/dist/components/message/item/MessageBubble.d.ts.map +1 -0
- package/dist/components/message/item/MessageBubble.js +19 -0
- package/dist/components/message/item/RevokeMessage.js +1 -1
- package/dist/components/message/item/TextMessage.d.ts.map +1 -1
- package/dist/components/message/item/TextMessage.js +20 -9
- package/dist/components/message/item/UrlTextMessage.d.ts.map +1 -1
- package/dist/components/message/item/UrlTextMessage.js +19 -17
- package/dist/components/message/item/VideoMessage.d.ts.map +1 -1
- package/dist/components/message/item/VideoMessage.js +4 -12
- package/dist/components/message/item/imagePreviewToolbar.d.ts +5 -0
- package/dist/components/message/item/imagePreviewToolbar.d.ts.map +1 -0
- package/dist/components/message/item/imagePreviewToolbar.js +14 -0
- package/dist/components/message/item/index.d.ts +2 -1
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +38 -41
- package/dist/components/message/item/textStyle.d.ts +2 -0
- package/dist/components/message/item/textStyle.d.ts.map +1 -0
- package/dist/components/message/item/textStyle.js +1 -0
- package/dist/hooks/message/useSendMessage.d.ts +7 -13
- package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
- package/dist/hooks/message/useSendMessage.js +87 -113
- package/dist/styles/global.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/chat.d.ts +8 -1
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/utils/bizMessage.d.ts +1 -14
- package/dist/utils/bizMessage.d.ts.map +1 -1
- package/dist/utils/bizMessage.js +1 -26
- package/dist/utils/common.d.ts +3 -1
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +16 -3
- package/dist/utils/fileValidation.d.ts +1 -0
- package/dist/utils/fileValidation.d.ts.map +1 -1
- package/dist/utils/fileValidation.js +10 -17
- package/dist/utils/link.d.ts +13 -0
- package/dist/utils/link.d.ts.map +1 -0
- package/dist/utils/link.js +77 -0
- package/dist/utils/openLink.d.ts +3 -0
- package/dist/utils/openLink.d.ts.map +1 -0
- package/dist/utils/openLink.js +19 -0
- package/package.json +126 -127
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface ThreadCardProps {
|
|
3
|
+
avatar: ReactNode;
|
|
4
|
+
title: ReactNode;
|
|
5
|
+
preview: string;
|
|
6
|
+
time?: string;
|
|
7
|
+
unreadCount?: number;
|
|
8
|
+
isSelected?: boolean;
|
|
9
|
+
onClick: () => void;
|
|
10
|
+
testId?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const ThreadCard: ({ avatar, title, preview, time, unreadCount, isSelected, onClick, testId, }: ThreadCardProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export default ThreadCard;
|
|
14
|
+
//# sourceMappingURL=ThreadCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThreadCard.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/ThreadCard.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAoBvC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,QAAA,MAAM,UAAU,GAAI,6EASjB,eAAe,4CA4CjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
const formatUnreadCount = (count) => (count > 99 ? "99+" : count);
|
|
5
|
+
const UnreadBadge = ({ count }) => {
|
|
6
|
+
const label = String(formatUnreadCount(count));
|
|
7
|
+
const isWide = label.length > 1;
|
|
8
|
+
return (_jsx("span", { className: clsx("inline-flex h-5 shrink-0 items-center justify-center rounded-[32px] border-2 border-white bg-[linear-gradient(93deg,#FF7D74_0%,#F04438_100%)] px-[3px] text-center text-[12px] font-semibold leading-[160%] text-white", isWide ? "min-w-8" : "min-w-5"), children: label }));
|
|
9
|
+
};
|
|
10
|
+
const ThreadCard = ({ avatar, title, preview, time, unreadCount = 0, isSelected = false, onClick, testId, }) => {
|
|
11
|
+
const hasUnread = unreadCount > 0;
|
|
12
|
+
return (_jsxs("button", { type: "button", onClick: onClick, "data-testid": testId, className: clsx("relative flex w-full shrink-0 items-start gap-2 border-b border-[#EFEFEF] p-3 text-left transition-colors hover:bg-gray-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-[#1677ff]", isSelected ? "bg-blue-50" : "bg-white"), children: [isSelected && (_jsx("span", { className: "absolute bottom-0 left-0 top-0 w-1 bg-blue-500" })), avatar, _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsxs("div", { className: "flex min-h-[25.6px] items-center justify-between gap-1", children: [_jsx("div", { className: "min-w-0 flex-1", children: title }), time && (_jsx("span", { className: "shrink-0 text-[12px] font-normal leading-[160%] text-[#747B7E] [font-feature-settings:'liga'_off,'clig'_off]", children: time }))] }), _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("p", { className: clsx("min-w-0 flex-1 truncate text-[14px] leading-[160%] [font-feature-settings:'liga'_off,'clig'_off]", hasUnread
|
|
13
|
+
? "font-[510] text-black"
|
|
14
|
+
: "font-normal tracking-[0.14px] text-[#5C6366]"), children: preview }), hasUnread && _jsx(UnreadBadge, { count: unreadCount })] })] })] }));
|
|
15
|
+
};
|
|
16
|
+
export default ThreadCard;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageCollection.d.ts","sourceRoot":"","sources":["../../../src/components/media-collection/ImageCollection.tsx"],"names":[],"mappings":"AAYA,QAAA,MAAM,eAAe,+
|
|
1
|
+
{"version":3,"file":"ImageCollection.d.ts","sourceRoot":"","sources":["../../../src/components/media-collection/ImageCollection.tsx"],"names":[],"mappings":"AAYA,QAAA,MAAM,eAAe,+CAqFpB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -2,13 +2,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { MessageType } from "@openim/wasm-client-sdk";
|
|
3
3
|
import { useSearchMessage } from "../../hooks/search/useSearchMessage";
|
|
4
4
|
import InfiniteScroll from "react-infinite-scroll-component";
|
|
5
|
-
import {
|
|
5
|
+
import { Empty, Image, Spin } from "antd";
|
|
6
6
|
import { useCallback } from "react";
|
|
7
7
|
import dayjs from "dayjs";
|
|
8
8
|
import useConversationStore from "../../store/conversation";
|
|
9
9
|
import { images } from "../../constants/images";
|
|
10
10
|
import { useTranslation } from "react-i18next";
|
|
11
|
-
import {
|
|
11
|
+
import { renderImagePreviewToolbar } from "../../components/message/item/imagePreviewToolbar";
|
|
12
12
|
const ImageCollection = () => {
|
|
13
13
|
const { t } = useTranslation();
|
|
14
14
|
const selectedSourceId = useConversationStore((state) => state.selectedSourceId);
|
|
@@ -18,16 +18,6 @@ const ImageCollection = () => {
|
|
|
18
18
|
contentType: MessageType.PictureMessage,
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
|
-
const handleDownload = (imageUrl) => {
|
|
22
|
-
if (!imageUrl)
|
|
23
|
-
return;
|
|
24
|
-
const link = document.createElement("a");
|
|
25
|
-
link.href = imageUrl;
|
|
26
|
-
link.download = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
|
|
27
|
-
document.body.appendChild(link);
|
|
28
|
-
link.click();
|
|
29
|
-
document.body.removeChild(link);
|
|
30
|
-
};
|
|
31
21
|
const renderItem = useCallback((date, items) => {
|
|
32
22
|
return (_jsxs("div", { className: "mb-2", children: [_jsx("span", { className: "text-sm font-medium text-gray-500 px-3", children: dayjs(date).format("DD MMMM, YYYY") }), _jsx("div", { className: "grid grid-cols-3 justify-start gap-px py-2", children: items.map((item) => {
|
|
33
23
|
var _a, _b, _c, _d;
|
|
@@ -42,11 +32,7 @@ const ImageCollection = () => {
|
|
|
42
32
|
if (isLoading)
|
|
43
33
|
return (_jsx("div", { className: "flex items-center justify-center", children: _jsx(Spin, {}) }));
|
|
44
34
|
return (_jsx("div", { id: "scrollableImageDiv", className: "h-full overflow-auto", children: _jsx(Image.PreviewGroup, { preview: {
|
|
45
|
-
toolbarRender: (originalNode, info) => {
|
|
46
|
-
var _a;
|
|
47
|
-
const imageUrl = (_a = info === null || info === void 0 ? void 0 : info.image) === null || _a === void 0 ? void 0 : _a.url;
|
|
48
|
-
return (_jsxs("div", { className: "flex flex-col justify-center gap-2", children: [originalNode, imageUrl && (_jsx(Button, { type: "primary", icon: _jsx(DownloadOutlined, {}), className: "self-center", onClick: () => handleDownload(imageUrl), children: t("download") }))] }));
|
|
49
|
-
},
|
|
35
|
+
toolbarRender: (originalNode, info) => { var _a; return renderImagePreviewToolbar(originalNode, (_a = info === null || info === void 0 ? void 0 : info.image) === null || _a === void 0 ? void 0 : _a.url, t); },
|
|
50
36
|
}, children: _jsx(InfiniteScroll, { dataLength: dataFlatten.length, next: fetchNextPage, hasMore: hasNextPage, loader: _jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) }), scrollableTarget: "scrollableImageDiv", children: Object.entries(groupedData).map(([date, items]) => renderItem(date, items)) }) }) }));
|
|
51
37
|
};
|
|
52
38
|
export default ImageCollection;
|
|
@@ -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":"AA0BA,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,4CAgQ3C,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -11,7 +11,6 @@ import MessageInfiniteScroll from "./MessageInfiniteScroll";
|
|
|
11
11
|
import MessageHeader from "./MessageHeader";
|
|
12
12
|
import MessageFooter from "./footer";
|
|
13
13
|
import UnassignedSessionFooter from "./UnassignedSessionFooter";
|
|
14
|
-
import { images } from "../../constants/images";
|
|
15
14
|
import { useTranslation } from "react-i18next";
|
|
16
15
|
import useConversationStore from "../../store/conversation";
|
|
17
16
|
import { useBoolean } from "ahooks";
|
|
@@ -130,11 +129,6 @@ const MessageList = (props) => {
|
|
|
130
129
|
if (!conversationData) {
|
|
131
130
|
return (_jsx("div", { className: "flex flex-1 items-center justify-center h-full", children: connectStatus !== ConnectStatus.Connected ? (_jsx(Spin, {})) : (_jsx(Empty, { description: t("no_conversation_data") })) }));
|
|
132
131
|
}
|
|
133
|
-
return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0", style: {
|
|
134
|
-
backgroundImage: `url(${images.conversationBg})`,
|
|
135
|
-
backgroundSize: "cover",
|
|
136
|
-
backgroundPosition: "center",
|
|
137
|
-
overflowX: "hidden",
|
|
138
|
-
}, children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), isCheckingMembership ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: joinGroup, loading: isJoining, children: t("join_group") })] })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(Modal, { centered: true, open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, getContainer: false, forceRender: true, children: _jsx("p", { children: t("revoke_message_confirm_message") }) })] }));
|
|
132
|
+
return (_jsxs("div", { className: "flex flex-col flex-1 relative h-full min-w-0 bg-white", style: { overflowX: "hidden" }, children: [_jsx(MessageHeader, { onClose: onClose, currentSession: latestConversationSession, isJoined: isJoined }), _jsx(MessageInfiniteScroll, { scrollRef: scrollRef, scrollableTargetId: "scrollableMessagesDiv", loadState: loadState, moreOldLoading: moreOldLoading, onLoadMoreOld: loadMoreOldMessage, onScroll: handleInfiniteScroll, children: loadState.messageList.map((message, _, array) => (_jsx(MessageItem, { message: message, allMessages: array, contextMenuOpen: openMenuId === message.clientMsgID, onContextMenuOpenChange: (open) => setOpenMenuId(open ? message.clientMsgID : null), onRevokeMessage: handleOpenRevoke, onQuoteMessage: setQuotedMessage, onPressQuoteMessage: onPressQuoteMessage }, message.clientMsgID))) }), moreNewLoading && (_jsx("div", { className: "flex items-center justify-center py-2", children: _jsx(Spin, {}) })), isCheckingMembership ? (_jsx("div", { className: "border-t bg-white py-4 flex items-center justify-center", children: _jsx(Spin, {}) })) : (latestConversationSession === null || latestConversationSession === void 0 ? void 0 : latestConversationSession.status) === SessionStatus.UNASSIGNED ? (_jsx(UnassignedSessionFooter, { sessionId: latestConversationSession.id, teamId: latestConversationSession.teamId })) : shouldRestrictToLastSession ? (_jsxs("div", { className: "border-t bg-white py-4 flex flex-col items-center gap-2", children: [_jsx("p", { className: "text-sm text-gray-500", children: t("join_group_required") }), _jsx(Button, { type: "primary", onClick: joinGroup, loading: isJoining, children: t("join_group") })] })) : (_jsx(MessageFooter, { currentSession: latestConversationSession, openCreateCannedModal: openCreateCannedModal })), _jsx(Modal, { centered: true, open: showConfirmRevoke, onOk: onRevokeMessage, onCancel: handleCloseRevoke, title: t("revoke_message_confirm_title"), okText: t("revoke"), cancelText: t("cancel"), okType: "danger", confirmLoading: isRevoking, getContainer: false, forceRender: true, children: _jsx("p", { children: t("revoke_message_confirm_message") }) })] }));
|
|
139
133
|
};
|
|
140
134
|
export default MessageList;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComposerTextSyncPlugin.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/ComposerTextSyncPlugin.tsx"],"names":[],"mappings":"AAMA,UAAU,2BAA2B;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,QAAA,MAAM,sBAAsB,GAAI,cAAc,2BAA2B,SAYxE,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
3
|
+
import { $getRoot } from "lexical";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
const ComposerTextSyncPlugin = ({ onChange }) => {
|
|
6
|
+
const [editor] = useLexicalComposerContext();
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
return editor.registerUpdateListener(({ editorState }) => {
|
|
9
|
+
editorState.read(() => {
|
|
10
|
+
onChange($getRoot().getTextContent());
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
}, [editor, onChange]);
|
|
14
|
+
return null;
|
|
15
|
+
};
|
|
16
|
+
export default ComposerTextSyncPlugin;
|
|
@@ -4,10 +4,11 @@ interface ShortenOptions {
|
|
|
4
4
|
keepStart?: number;
|
|
5
5
|
keepEnd?: number;
|
|
6
6
|
}
|
|
7
|
-
export declare const shortenFileName: (name
|
|
8
|
-
export declare function FilePreviewList({ files, onRemove, }: {
|
|
7
|
+
export declare const shortenFileName: (name?: string, options?: ShortenOptions) => string;
|
|
8
|
+
export declare function FilePreviewList({ files, onRemove, onVideoReady, }: {
|
|
9
9
|
files: UploadFile[];
|
|
10
10
|
onRemove: (file: UploadFile) => void;
|
|
11
|
+
onVideoReady?: () => void;
|
|
11
12
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
12
13
|
declare const FilePreview: () => import("react/jsx-runtime").JSX.Element;
|
|
13
14
|
export default FilePreview;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/FilePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,
|
|
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;AAOlC,UAAU,cAAc;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,EAAE,UAAS,cAAmB,WAmB1E,CAAC;AAwIF,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,MAAM,IAAI,CAAC;CAC3B,kDAsBA;AAED,QAAA,MAAM,WAAW,+CAQhB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
4
|
import { useMessageFooterContext } from ".";
|
|
5
|
-
import { Button } from "antd";
|
|
6
5
|
import { Icon } from "../../../components/icon";
|
|
7
6
|
import { documentIcon } from "../../../assets/svg";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"application/msword",
|
|
11
|
-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
12
|
-
];
|
|
7
|
+
import { DOCUMENT_MIME_TYPES } from "../../../utils/fileValidation";
|
|
8
|
+
import { formatDuration } from "../../../utils/common";
|
|
13
9
|
export const shortenFileName = (name, options = {}) => {
|
|
10
|
+
if (!name)
|
|
11
|
+
return "";
|
|
14
12
|
const { maxLength = 20, keepStart = 8, keepEnd = 3 } = options;
|
|
15
13
|
if (name.length <= maxLength)
|
|
16
14
|
return name;
|
|
@@ -24,23 +22,65 @@ export const shortenFileName = (name, options = {}) => {
|
|
|
24
22
|
const end = base.slice(-endLen);
|
|
25
23
|
return `${start}...${end}${ext}`;
|
|
26
24
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
const formatFileSize = (bytes) => {
|
|
26
|
+
if (bytes === 0)
|
|
27
|
+
return "0 B";
|
|
28
|
+
if (bytes < 1024)
|
|
29
|
+
return `${bytes} B`;
|
|
30
|
+
const kb = bytes / 1024;
|
|
31
|
+
if (kb < 1024)
|
|
32
|
+
return `${Math.round(kb)} KB`;
|
|
33
|
+
return `${(kb / 1024).toFixed(1)} MB`;
|
|
34
|
+
};
|
|
35
|
+
const getFileType = (file) => {
|
|
36
|
+
var _a, _b, _c;
|
|
37
|
+
const mimeType = (_c = (_b = (_a = file.originFileObj) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : file.type) !== null && _c !== void 0 ? _c : "";
|
|
38
|
+
if (DOCUMENT_MIME_TYPES.includes(mimeType))
|
|
39
|
+
return "document";
|
|
40
|
+
if (mimeType.startsWith("video/"))
|
|
41
|
+
return "video";
|
|
42
|
+
return "image";
|
|
43
|
+
};
|
|
44
|
+
const RemoveButton = ({ file, onRemove }) => (_jsx("button", { type: "button", onClick: () => onRemove(file), className: "absolute -right-1 -top-1 flex h-5 w-5 items-center justify-center rounded-full bg-[#393E40]", "aria-label": "X\u00F3a", children: _jsx(Icon, { icon: "close-o", size: 12, className: "text-white" }) }));
|
|
45
|
+
const MediaThumb = ({ file, onRemove, onVideoReady }) => {
|
|
46
|
+
var _a;
|
|
47
|
+
const [src, setSrc] = useState("");
|
|
48
|
+
const [duration, setDuration] = useState(null);
|
|
49
|
+
const isVideo = getFileType(file) === "video";
|
|
50
|
+
const isLoading = file.status === "uploading";
|
|
51
|
+
const percent = Math.round((_a = file.percent) !== null && _a !== void 0 ? _a : 0);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
var _a;
|
|
54
|
+
const originFile = file.originFileObj;
|
|
55
|
+
if (!originFile) {
|
|
56
|
+
setSrc((_a = file.url) !== null && _a !== void 0 ? _a : "");
|
|
57
|
+
return;
|
|
38
58
|
}
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
const url = URL.createObjectURL(originFile);
|
|
60
|
+
setSrc(url);
|
|
61
|
+
return () => URL.revokeObjectURL(url);
|
|
62
|
+
}, [file.originFileObj, file.url]);
|
|
63
|
+
const handleLoadedMetadata = (event) => {
|
|
64
|
+
setDuration(event.currentTarget.duration);
|
|
65
|
+
onVideoReady === null || onVideoReady === void 0 ? void 0 : onVideoReady();
|
|
66
|
+
};
|
|
67
|
+
return (_jsxs("div", { 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 })] }));
|
|
68
|
+
};
|
|
69
|
+
const DocumentCard = ({ file, onRemove }) => {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
const isLoading = file.status === "uploading";
|
|
72
|
+
const percent = Math.round((_a = file.percent) !== null && _a !== void 0 ? _a : 0);
|
|
73
|
+
return (_jsxs("div", { className: "relative flex h-12 w-40 shrink-0 items-center gap-[7px] rounded-lg bg-[rgba(131,137,157,0.08)] py-[4px] pl-2 pr-5", children: [_jsx("div", { className: "flex h-full w-8 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-8 [&>svg]:w-8", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[11px] font-normal leading-[160%] text-[#393E40]", children: shortenFileName(file.name) }), isLoading ? (_jsxs("span", { className: "text-[10px] leading-[160%] tracking-[0.1px] text-[#747B7E]", children: [percent, "%"] })) : (_jsx("span", { className: "text-[10px] leading-[160%] tracking-[0.1px] text-[#747B7E]", children: formatFileSize((_b = file.size) !== null && _b !== void 0 ? _b : 0) }))] }), _jsx(RemoveButton, { file: file, onRemove: onRemove })] }));
|
|
74
|
+
};
|
|
75
|
+
export function FilePreviewList({ files, onRemove, onVideoReady, }) {
|
|
41
76
|
if (files.length === 0)
|
|
42
77
|
return null;
|
|
43
|
-
return (_jsx("div", { className: "
|
|
78
|
+
return (_jsx("div", { className: "flex items-center gap-3 self-stretch overflow-x-auto px-2 pb-2 pt-3", children: files.map((file) => {
|
|
79
|
+
if (getFileType(file) === "document") {
|
|
80
|
+
return (_jsx(DocumentCard, { file: file, onRemove: onRemove }, file.uid));
|
|
81
|
+
}
|
|
82
|
+
return (_jsx(MediaThumb, { file: file, onRemove: onRemove, onVideoReady: onVideoReady }, file.uid));
|
|
83
|
+
}) }));
|
|
44
84
|
}
|
|
45
85
|
const FilePreview = () => {
|
|
46
86
|
const { listUploadFiles, setListUploadFiles } = useMessageFooterContext();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface LinkInputPreviewProps {
|
|
2
|
+
url: string;
|
|
3
|
+
onRemove: () => void;
|
|
4
|
+
}
|
|
5
|
+
declare const LinkInputPreview: ({ url, onRemove }: LinkInputPreviewProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export default LinkInputPreview;
|
|
7
|
+
//# sourceMappingURL=LinkInputPreview.d.ts.map
|
|
@@ -0,0 +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,4CAoEjE,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Icon } from "../../../components/icon";
|
|
4
|
+
import { useFetchUrlMetadata } from "../../../hooks/common/useFetchUrlMetadata";
|
|
5
|
+
import { getHostLabel } from "../../../utils/link";
|
|
6
|
+
import { openLink } from "../../../utils/openLink";
|
|
7
|
+
import { useTranslation } from "react-i18next";
|
|
8
|
+
const LinkInputPreview = ({ url, onRemove }) => {
|
|
9
|
+
const { t } = useTranslation("biz-inbox");
|
|
10
|
+
const { data, isLoading, isError } = useFetchUrlMetadata(url);
|
|
11
|
+
const handleOpen = () => {
|
|
12
|
+
openLink(url, t);
|
|
13
|
+
};
|
|
14
|
+
return (_jsxs("div", { "data-testid": "link-input-preview", className: "flex w-full shrink-0 items-center gap-2 overflow-hidden bg-[#EAF5FF] 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-[#EAF5FF]", children: isLoading ? (_jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-[#1B3FE4] 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(Icon, { icon: "link-alt-b", size: 24, className: "text-[#1B3FE4]" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [isLoading ? (_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-[#393E40]", children: t("link_preview.loading") })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "truncate text-[14px] font-medium leading-[1.6] text-[#393E40]", 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-[#747B7E]", children: (data === null || data === void 0 ? void 0 : data.description) || getHostLabel(url) }))] })), isError && !isLoading && (_jsx("p", { className: "truncate text-[13px] leading-[1.6] text-[#747B7E]", children: 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(Icon, { icon: "close-b", size: 16, className: "text-[#393E40]" }) })] }));
|
|
15
|
+
};
|
|
16
|
+
export default LinkInputPreview;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaActions.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/MediaActions.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAkB,UAAU,EAA0B,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"MediaActions.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/MediaActions.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAkB,UAAU,EAA0B,MAAM,MAAM,CAAC;AAqD1E,UAAU,iBAAiB;IACzB,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,aAAa,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,eAAe,EACf,aAAa,EACb,eAAe,EACf,eAAsB,GACvB,EAAE,iBAAiB,2CAyKnB"}
|
|
@@ -8,7 +8,7 @@ import clsx from "clsx";
|
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
import EmojiPicker from "./EmojiPicker";
|
|
10
10
|
import { Icon } from "../../../components/icon";
|
|
11
|
-
import { validateFile, validateVideoLimit, } from "../../../utils/fileValidation";
|
|
11
|
+
import { createUploadFile, validateFile, validateVideoLimit, } from "../../../utils/fileValidation";
|
|
12
12
|
import { DOCUMENT_TYPES } from "./editorConfig";
|
|
13
13
|
import CannedResponseIcon from "../../../assets/svg/canned-response";
|
|
14
14
|
import { useMessageFooterContext } from ".";
|
|
@@ -58,15 +58,18 @@ export default function MediaActions({ listUploadFiles, onFilesChange, buttonCla
|
|
|
58
58
|
return false;
|
|
59
59
|
};
|
|
60
60
|
const handleChange = (info) => {
|
|
61
|
-
var _a;
|
|
62
61
|
let newList = [...info.fileList];
|
|
63
62
|
const lastFile = info.file;
|
|
64
63
|
if (DOCUMENT_TYPES.includes(lastFile.type || "")) {
|
|
65
64
|
newList = newList.filter((f) => !DOCUMENT_TYPES.includes(f.type || ""));
|
|
66
|
-
|
|
67
|
-
newList.push(Object.assign(Object.assign({}, lastFile), { originFileObj: originFile }));
|
|
65
|
+
newList.push(lastFile);
|
|
68
66
|
}
|
|
69
|
-
|
|
67
|
+
const normalizedList = newList.map((file) => {
|
|
68
|
+
var _a;
|
|
69
|
+
const originFile = ((_a = file.originFileObj) !== null && _a !== void 0 ? _a : file);
|
|
70
|
+
return Object.assign(Object.assign({}, createUploadFile(originFile)), { uid: file.uid });
|
|
71
|
+
});
|
|
72
|
+
onFilesChange(normalizedList);
|
|
70
73
|
};
|
|
71
74
|
const onPressCanned = useCallback(async () => {
|
|
72
75
|
if (!isOpenCanned) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAEL,wBAAwB,EAEzB,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAkB/C,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;CACpC;AASD,eAAO,MAAM,oBAAoB,mDAY/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,4CAG5B,kBAAkB,4CAuSpB,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -5,13 +5,17 @@ import { ToolbarPlugin } from "./ToolbarPlugin";
|
|
|
5
5
|
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
|
|
6
6
|
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
|
|
7
7
|
import { editorTheme, editorNodes, editorOnError } from "./editorConfig";
|
|
8
|
-
import { createContext, useCallback, useContext, useEffect, useRef, useState, } from "react";
|
|
8
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
9
9
|
import EnterHandler from "./EnterHandler";
|
|
10
10
|
import ActionBar from "./ActionBar";
|
|
11
|
-
import { AccountType } from "../../../types/chat";
|
|
11
|
+
import { AccountType, } from "../../../types/chat";
|
|
12
12
|
import { useSendMessage } from "../../../hooks/message/useSendMessage";
|
|
13
13
|
import { Modal, Popover } from "antd";
|
|
14
14
|
import FilePreview from "./FilePreview";
|
|
15
|
+
import LinkInputPreview from "./LinkInputPreview";
|
|
16
|
+
import ComposerTextSyncPlugin from "./ComposerTextSyncPlugin";
|
|
17
|
+
import { extractLinkUrls } from "../../../utils/link";
|
|
18
|
+
import { useFetchUrlMetadata } from "../../../hooks/common/useFetchUrlMetadata";
|
|
15
19
|
import { useTranslation } from "react-i18next";
|
|
16
20
|
import PasteAndDropPlugin from "./PasteAndDropPlugin";
|
|
17
21
|
import { QuotedMessageFooter } from "./QuotedMessage";
|
|
@@ -48,9 +52,11 @@ export const MessageFooterContext = createContext({
|
|
|
48
52
|
export const useMessageFooterContext = () => useContext(MessageFooterContext);
|
|
49
53
|
const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
|
|
50
54
|
const { t } = useTranslation();
|
|
51
|
-
const {
|
|
55
|
+
const { sendMergeMessage } = useSendMessage();
|
|
52
56
|
const accountType = useCurrentUserAccountType();
|
|
53
57
|
const [listUploadFiles, setListUploadFiles] = useState([]);
|
|
58
|
+
const [composerText, setComposerText] = useState("");
|
|
59
|
+
const [isLinkPreviewDismissed, setIsLinkPreviewDismissed] = useState(false);
|
|
54
60
|
const [isOpenCanned, { setTrue: openCanned, setFalse: closeCanned }] = useBoolean(false);
|
|
55
61
|
const isCrm = useAuthStore((state) => state.isCrm);
|
|
56
62
|
const [cannedQuery, setCannedQuery] = useState("");
|
|
@@ -61,6 +67,25 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
|
|
|
61
67
|
const quotedMessage = useConversationStore((state) => state.quotedMessage);
|
|
62
68
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
63
69
|
const lockToInternal = Boolean((quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.clientMsgID) && (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.isInternal));
|
|
70
|
+
const previewUrl = useMemo(() => {
|
|
71
|
+
const urls = extractLinkUrls(composerText);
|
|
72
|
+
return urls.length === 1 ? urls[0] : null;
|
|
73
|
+
}, [composerText]);
|
|
74
|
+
const showLinkPreview = !!previewUrl && !isLinkPreviewDismissed && !isInternal;
|
|
75
|
+
const { data: previewMetadata } = useFetchUrlMetadata(previewUrl !== null && previewUrl !== void 0 ? previewUrl : "", showLinkPreview);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
setIsLinkPreviewDismissed(false);
|
|
78
|
+
}, [previewUrl]);
|
|
79
|
+
const resolveUrlMetadata = useCallback(() => {
|
|
80
|
+
if (!showLinkPreview || !previewUrl || !previewMetadata)
|
|
81
|
+
return undefined;
|
|
82
|
+
return {
|
|
83
|
+
url: previewUrl,
|
|
84
|
+
title: previewMetadata.title,
|
|
85
|
+
description: previewMetadata.description,
|
|
86
|
+
image: previewMetadata.image,
|
|
87
|
+
};
|
|
88
|
+
}, [showLinkPreview, previewUrl, previewMetadata]);
|
|
64
89
|
const [isSessionClosedModalOpen, { setTrue: openSessionClosedModal, setFalse: closeSessionClosedModal },] = useBoolean(false);
|
|
65
90
|
const pendingMessageRef = useRef(null);
|
|
66
91
|
const { mutateAsync: createSession, isPending: isCreatingSession } = useCreateSession();
|
|
@@ -90,57 +115,45 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
|
|
|
90
115
|
type,
|
|
91
116
|
isInternal,
|
|
92
117
|
files: [...listUploadFiles],
|
|
118
|
+
urlMetadata: resolveUrlMetadata(),
|
|
93
119
|
};
|
|
94
120
|
openSessionClosedModal();
|
|
95
121
|
return false;
|
|
96
122
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
currentSession,
|
|
106
|
-
isInternal,
|
|
107
|
-
});
|
|
108
|
-
}
|
|
123
|
+
sendMergeMessage({
|
|
124
|
+
plainText,
|
|
125
|
+
richText,
|
|
126
|
+
files: listUploadFiles,
|
|
127
|
+
currentSession,
|
|
128
|
+
isInternal,
|
|
129
|
+
urlMetadata: resolveUrlMetadata(),
|
|
130
|
+
});
|
|
109
131
|
setListUploadFiles([]);
|
|
110
132
|
return true;
|
|
111
133
|
}, [
|
|
112
134
|
sendMergeMessage,
|
|
113
|
-
sendTextMessage,
|
|
114
135
|
listUploadFiles,
|
|
115
136
|
currentSession,
|
|
116
137
|
openSessionClosedModal,
|
|
138
|
+
resolveUrlMetadata,
|
|
117
139
|
]);
|
|
118
140
|
const executePendingSend = useCallback((newSession) => {
|
|
119
141
|
const pending = pendingMessageRef.current;
|
|
120
142
|
if (!pending)
|
|
121
143
|
return;
|
|
122
144
|
const sessionToUse = newSession || currentSession;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
sendMergeMessage({
|
|
133
|
-
plainText: pending.plainText,
|
|
134
|
-
richText: pending.richText,
|
|
135
|
-
files: pending.files,
|
|
136
|
-
currentSession: sessionToUse,
|
|
137
|
-
isInternal: pending.isInternal,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
145
|
+
sendMergeMessage({
|
|
146
|
+
plainText: pending.plainText,
|
|
147
|
+
richText: pending.richText,
|
|
148
|
+
files: pending.files,
|
|
149
|
+
currentSession: sessionToUse,
|
|
150
|
+
isInternal: pending.isInternal,
|
|
151
|
+
urlMetadata: pending.urlMetadata,
|
|
152
|
+
});
|
|
140
153
|
setListUploadFiles([]);
|
|
141
154
|
pendingMessageRef.current = null;
|
|
142
155
|
emit("CLEAR_COMPOSER");
|
|
143
|
-
}, [
|
|
156
|
+
}, [sendMergeMessage, currentSession]);
|
|
144
157
|
const handleSessionAction = useCallback(async (action) => {
|
|
145
158
|
const conversationId = conversationData === null || conversationData === void 0 ? void 0 : conversationData.conversationID;
|
|
146
159
|
if (!conversationId)
|
|
@@ -202,6 +215,6 @@ const MessageFooterProvider = ({ currentSession, openCreateCannedModal, }) => {
|
|
|
202
215
|
setMaxActiveCannedIndex,
|
|
203
216
|
}, 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: {
|
|
204
217
|
body: "mx-1 !p-0",
|
|
205
|
-
}, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(QuotedMessageFooter, {}), listUploadFiles.length > 0 && _jsx(FilePreview, {}), _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(EnterHandler, {}), _jsx(PasteAndDropPlugin, {}), isCrm && (_jsx(CannedResponseTriggerPlugin, { onClose: closeCanned, onOpen: onOpenCanned }))] }), _jsx(SessionClosedModal, { open: isSessionClosedModalOpen, loading: isSessionActionLoading, onReopen: handleReopenSession, onCreateNew: handleCreateNewSession, onClose: handleCloseSessionModal })] }));
|
|
218
|
+
}, destroyOnHidden: true, children: _jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [_jsx(QuotedMessageFooter, {}), 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 })] }));
|
|
206
219
|
};
|
|
207
220
|
export default MessageFooterProvider;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MessageItem } from "@openim/wasm-client-sdk";
|
|
2
|
-
interface
|
|
2
|
+
interface FileMessageItemProps {
|
|
3
3
|
message: MessageItem;
|
|
4
4
|
}
|
|
5
|
-
declare const FileMessageItem: (props:
|
|
5
|
+
declare const FileMessageItem: (props: FileMessageItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
export default FileMessageItem;
|
|
7
7
|
//# sourceMappingURL=FileMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/FileMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"FileMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/FileMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;AAOrE,UAAU,oBAAoB;IAC5B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,eAAe,GAAI,OAAO,oBAAoB,4CAiEnD,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,28 +1,36 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { MessageStatus } from "@openim/wasm-client-sdk";
|
|
3
|
+
import { Spin } from "antd";
|
|
4
|
+
import { Icon } from "../../../components/icon";
|
|
3
5
|
import { documentIcon } from "../../../assets/svg";
|
|
6
|
+
import { shortenFileName } from "../../../components/message/footer/FilePreview";
|
|
7
|
+
import { renderFileSize } from "../../../utils/common";
|
|
4
8
|
const FileMessageItem = (props) => {
|
|
5
9
|
var _a;
|
|
6
10
|
const { message } = props;
|
|
11
|
+
const fileElem = message.fileElem;
|
|
12
|
+
const fileName = (fileElem === null || fileElem === void 0 ? void 0 : fileElem.fileName) || "";
|
|
13
|
+
const fileSize = (_a = fileElem === null || fileElem === void 0 ? void 0 : fileElem.fileSize) !== null && _a !== void 0 ? _a : 0;
|
|
14
|
+
const sourceUrl = (fileElem === null || fileElem === void 0 ? void 0 : fileElem.sourceUrl) || "";
|
|
15
|
+
const isSending = message.status === MessageStatus.Sending;
|
|
16
|
+
const hasUrl = !!sourceUrl;
|
|
17
|
+
const handleView = () => {
|
|
18
|
+
if (!hasUrl)
|
|
19
|
+
return;
|
|
20
|
+
window.open(sourceUrl, "_blank", "noopener,noreferrer");
|
|
21
|
+
};
|
|
7
22
|
const handleDownload = () => {
|
|
8
|
-
|
|
9
|
-
const url = ((_a = message.fileElem) === null || _a === void 0 ? void 0 : _a.sourceUrl) || "";
|
|
10
|
-
const fileName = ((_b = message.fileElem) === null || _b === void 0 ? void 0 : _b.fileName) || "";
|
|
11
|
-
if (!url) {
|
|
12
|
-
console.warn("Không có link file để tải");
|
|
23
|
+
if (!hasUrl)
|
|
13
24
|
return;
|
|
14
|
-
}
|
|
15
25
|
const link = document.createElement("a");
|
|
16
|
-
link.href =
|
|
17
|
-
|
|
18
|
-
link.setAttribute("download", fileName);
|
|
19
|
-
}
|
|
26
|
+
link.href = sourceUrl;
|
|
27
|
+
link.setAttribute("download", fileName);
|
|
20
28
|
link.setAttribute("target", "_blank");
|
|
21
29
|
link.setAttribute("rel", "noopener noreferrer");
|
|
22
30
|
document.body.appendChild(link);
|
|
23
31
|
link.click();
|
|
24
32
|
link.remove();
|
|
25
33
|
};
|
|
26
|
-
return (_jsxs("div", { className: "
|
|
34
|
+
return (_jsx(Spin, { spinning: isSending, children: _jsxs("div", { className: "flex h-[51px] w-[292px] items-center gap-3 rounded-xl border border-[rgba(168,173,175,0.2)] bg-white px-3 py-1", children: [_jsx("div", { className: "flex h-6 w-6 shrink-0 items-center justify-center overflow-hidden [&>svg]:h-6 [&>svg]:w-6", children: documentIcon }), _jsxs("div", { className: "flex min-w-0 w-[168px] flex-col justify-center", children: [_jsx("span", { className: "truncate text-[14px] font-medium leading-[160%] text-[#393E40]", children: shortenFileName(fileName) }), _jsx("span", { className: "truncate text-[13px] leading-[160%] text-[#5C6366]", children: renderFileSize(fileSize) })] }), _jsxs("div", { className: "flex w-[52px] shrink-0 items-center justify-end gap-3", children: [_jsx("button", { type: "button", onClick: handleView, disabled: !hasUrl, "aria-label": "Xem file", className: !hasUrl ? "opacity-30" : undefined, children: _jsx(Icon, { icon: "eye-o", size: 20, className: "text-[#393E40]" }) }), _jsx("button", { type: "button", onClick: handleDownload, disabled: !hasUrl, "aria-label": "T\u1EA3i xu\u1ED1ng", className: !hasUrl ? "opacity-30" : undefined, children: _jsx(Icon, { icon: "download-o", size: 20, className: "text-[#393E40]" }) })] })] }) }));
|
|
27
35
|
};
|
|
28
36
|
export default FileMessageItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/ImageMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/ImageMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;AAKrE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,4CA+BrD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|