@droppii-org/chat-sdk 0.1.1 → 0.1.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/assets/sdk/sql-wasm.wasm +0 -0
- package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
- package/dist/components/conversation/ConversationBySessionItem.js +6 -2
- package/dist/components/mediaCollection/LinkCollection.js +1 -1
- package/dist/components/message/MediaPreviewIcon.d.ts +7 -0
- package/dist/components/message/MediaPreviewIcon.d.ts.map +1 -0
- package/dist/components/message/MediaPreviewIcon.js +24 -0
- package/dist/components/message/MessageHeader.js +1 -1
- package/dist/components/message/MessageList.d.ts.map +1 -1
- package/dist/components/message/MessageList.js +48 -5
- package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
- package/dist/components/message/footer/ActionBar.js +15 -86
- package/dist/components/message/footer/EmojiPicker.d.ts.map +1 -1
- package/dist/components/message/footer/EmojiPicker.js +9 -5
- package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
- package/dist/components/message/footer/EnterHandler.js +16 -5
- package/dist/components/message/footer/FilePreview.d.ts +5 -0
- package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
- package/dist/components/message/footer/FilePreview.js +15 -12
- package/dist/components/message/footer/MediaActions.d.ts +10 -0
- package/dist/components/message/footer/MediaActions.d.ts.map +1 -0
- package/dist/components/message/footer/MediaActions.js +78 -0
- package/dist/components/message/footer/QuotedMessage.d.ts +2 -0
- package/dist/components/message/footer/QuotedMessage.d.ts.map +1 -0
- package/dist/components/message/footer/QuotedMessage.js +24 -0
- package/dist/components/message/footer/editorConfig.d.ts +24 -0
- package/dist/components/message/footer/editorConfig.d.ts.map +1 -0
- package/dist/components/message/footer/editorConfig.js +33 -0
- package/dist/components/message/footer/index.d.ts.map +1 -1
- package/dist/components/message/footer/index.js +6 -27
- package/dist/components/message/item/MessageStatusIndicator.d.ts +8 -0
- package/dist/components/message/item/MessageStatusIndicator.d.ts.map +1 -0
- package/dist/components/message/item/MessageStatusIndicator.js +16 -0
- package/dist/components/message/item/QuoteMessage.d.ts +9 -0
- package/dist/components/message/item/QuoteMessage.d.ts.map +1 -0
- package/dist/components/message/item/QuoteMessage.js +22 -0
- package/dist/components/message/item/RevokeMessage.d.ts +5 -0
- package/dist/components/message/item/RevokeMessage.d.ts.map +1 -0
- package/dist/components/message/item/RevokeMessage.js +8 -0
- package/dist/components/message/item/TextMessage.js +1 -1
- package/dist/components/message/item/UrlTextMessage.d.ts.map +1 -1
- package/dist/components/message/item/UrlTextMessage.js +3 -3
- package/dist/components/message/item/index.d.ts +6 -1
- package/dist/components/message/item/index.d.ts.map +1 -1
- package/dist/components/message/item/index.js +88 -25
- package/dist/components/richTextEditor/RichTextEditor.d.ts +12 -0
- package/dist/components/richTextEditor/RichTextEditor.d.ts.map +1 -0
- package/dist/components/richTextEditor/RichTextEditor.js +62 -0
- package/dist/components/searchConversation/SearchDrawer.js +1 -1
- package/dist/components/searchConversation/item/SearchItemAsMessage.d.ts +3 -1
- package/dist/components/searchConversation/item/SearchItemAsMessage.d.ts.map +1 -1
- package/dist/components/searchConversation/item/SearchItemAsMessage.js +5 -2
- package/dist/components/thread/AssignConfirmModal.d.ts +12 -0
- package/dist/components/thread/AssignConfirmModal.d.ts.map +1 -0
- package/dist/components/thread/AssignConfirmModal.js +11 -0
- package/dist/components/thread/ManualAssignPopover.d.ts +14 -0
- package/dist/components/thread/ManualAssignPopover.d.ts.map +1 -0
- package/dist/components/thread/ManualAssignPopover.js +83 -0
- package/dist/components/thread/SessionSection.d.ts.map +1 -1
- package/dist/components/thread/SessionSection.js +11 -6
- package/dist/components/thread/UserSection.js +1 -1
- package/dist/hooks/message/useMessage.d.ts +1 -0
- package/dist/hooks/message/useMessage.d.ts.map +1 -1
- package/dist/hooks/message/useMessage.js +7 -0
- package/dist/hooks/message/useRevokeMessage.d.ts +5 -0
- package/dist/hooks/message/useRevokeMessage.d.ts.map +1 -0
- package/dist/hooks/message/useRevokeMessage.js +16 -0
- package/dist/hooks/message/useSendMessage.d.ts +6 -0
- package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
- package/dist/hooks/message/useSendMessage.js +170 -32
- package/dist/hooks/session/useAssignSession.d.ts +8 -0
- package/dist/hooks/session/useAssignSession.d.ts.map +1 -0
- package/dist/hooks/session/useAssignSession.js +15 -0
- package/dist/hooks/session/useCreateNote.d.ts.map +1 -1
- package/dist/hooks/session/useCreateNote.js +2 -1
- package/dist/hooks/session/useGetTeamSupporters.d.ts +8 -0
- package/dist/hooks/session/useGetTeamSupporters.d.ts.map +1 -0
- package/dist/hooks/session/useGetTeamSupporters.js +20 -0
- 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/common.json +49 -37
- package/dist/services/query.d.ts +2 -0
- package/dist/services/query.d.ts.map +1 -1
- package/dist/services/query.js +2 -0
- package/dist/services/routes.d.ts +2 -0
- package/dist/services/routes.d.ts.map +1 -1
- package/dist/services/routes.js +2 -0
- package/dist/store/conversation.d.ts.map +1 -1
- package/dist/store/conversation.js +7 -1
- package/dist/styles/global.css +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/chat.d.ts +1 -1
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/types/dto.d.ts +26 -0
- package/dist/types/dto.d.ts.map +1 -1
- package/dist/utils/common.d.ts +3 -2
- package/dist/utils/common.d.ts.map +1 -1
- package/dist/utils/common.js +43 -19
- package/dist/utils/events.d.ts +1 -0
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/fileValidation.d.ts.map +1 -1
- package/dist/utils/fileValidation.js +2 -8
- package/dist/utils/queryHelpers.d.ts +3 -0
- package/dist/utils/queryHelpers.d.ts.map +1 -0
- package/dist/utils/queryHelpers.js +11 -0
- package/package.json +11 -10
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
5
|
+
import { $getSelection, $isRangeSelection } from "lexical";
|
|
6
|
+
import { Button, Upload, message as antdMessage } from "antd";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import { useTranslation } from "react-i18next";
|
|
9
|
+
import EmojiPicker from "./EmojiPicker";
|
|
10
|
+
import { Icon } from "../../icon";
|
|
11
|
+
import { validateFile, validateVideoLimit } from "../../../utils/fileValidation";
|
|
12
|
+
import { DOCUMENT_TYPES } from "./editorConfig";
|
|
13
|
+
const EmojiIcon = (_jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M7.59997 12.4C7.59997 12.4 8.49997 13.2 9.99997 13.2C11.5 13.2 12.4 12.4 12.4 12.4M14 8.39997C14 8.8418 13.6418 9.19997 13.2 9.19997C12.7581 9.19997 12.4 8.8418 12.4 8.39997C12.4 7.95814 12.7581 7.59997 13.2 7.59997C13.6418 7.59997 14 7.95814 14 8.39997ZM18 9.99997C18 14.4182 14.4182 18 9.99997 18C5.58169 18 1.99997 14.4182 1.99997 9.99997C1.99997 5.58169 5.58169 1.99997 9.99997 1.99997C14.4182 1.99997 18 5.58169 18 9.99997ZM7.59997 8.39997C7.59997 8.8418 7.2418 9.19997 6.79997 9.19997C6.35814 9.19997 5.99997 8.8418 5.99997 8.39997C5.99997 7.95814 6.35814 7.59997 6.79997 7.59997C7.2418 7.59997 7.59997 7.95814 7.59997 8.39997Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
14
|
+
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" }) }));
|
|
15
|
+
export default function MediaActions({ listUploadFiles, onFilesChange, buttonClassName, showMediaUpload = true, }) {
|
|
16
|
+
const [editor] = useLexicalComposerContext();
|
|
17
|
+
const { t } = useTranslation();
|
|
18
|
+
const [showEmojiPicker, setShowEmojiPicker] = useState(false);
|
|
19
|
+
const containerRef = useRef(null);
|
|
20
|
+
const handleEmojiSelect = useCallback((emoji) => {
|
|
21
|
+
editor.update(() => {
|
|
22
|
+
const selection = $getSelection();
|
|
23
|
+
if ($isRangeSelection(selection)) {
|
|
24
|
+
selection.insertText(emoji);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
setShowEmojiPicker(false);
|
|
28
|
+
}, [editor]);
|
|
29
|
+
const beforeUploadImagesAndVideo = (file, fileList) => {
|
|
30
|
+
const validation = validateFile(file, t);
|
|
31
|
+
if (!validation.isValid) {
|
|
32
|
+
antdMessage.error(validation.error);
|
|
33
|
+
return Upload.LIST_IGNORE;
|
|
34
|
+
}
|
|
35
|
+
const videoValidation = validateVideoLimit([file], listUploadFiles, t);
|
|
36
|
+
if (!videoValidation.isValid) {
|
|
37
|
+
antdMessage.error(videoValidation.error);
|
|
38
|
+
return Upload.LIST_IGNORE;
|
|
39
|
+
}
|
|
40
|
+
const newVideos = fileList.filter((f) => { var _a; return (_a = f.type) === null || _a === void 0 ? void 0 : _a.startsWith("video/"); });
|
|
41
|
+
if (newVideos.length > 1) {
|
|
42
|
+
antdMessage.error(t("video_limit_exceeded"));
|
|
43
|
+
return Upload.LIST_IGNORE;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
};
|
|
47
|
+
const beforeUploadFile = (file) => {
|
|
48
|
+
const isAllowed = DOCUMENT_TYPES.includes(file.type);
|
|
49
|
+
if (!isAllowed) {
|
|
50
|
+
antdMessage.error(t("invalid_document_format", { fileName: file.name }));
|
|
51
|
+
return Upload.LIST_IGNORE;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
};
|
|
55
|
+
const handleChange = (info) => {
|
|
56
|
+
var _a;
|
|
57
|
+
let newList = [...info.fileList];
|
|
58
|
+
const lastFile = info.file;
|
|
59
|
+
if (DOCUMENT_TYPES.includes(lastFile.type || "")) {
|
|
60
|
+
newList = newList.filter((f) => !DOCUMENT_TYPES.includes(f.type || ""));
|
|
61
|
+
const originFile = ((_a = lastFile.originFileObj) !== null && _a !== void 0 ? _a : lastFile);
|
|
62
|
+
newList.push(Object.assign(Object.assign({}, lastFile), { originFileObj: originFile }));
|
|
63
|
+
}
|
|
64
|
+
onFilesChange(newList);
|
|
65
|
+
};
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
const handleClickOutside = (event) => {
|
|
68
|
+
if (containerRef.current &&
|
|
69
|
+
!containerRef.current.contains(event.target)) {
|
|
70
|
+
setShowEmojiPicker(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
74
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
75
|
+
}, []);
|
|
76
|
+
const btnClass = buttonClassName !== null && buttonClassName !== void 0 ? buttonClassName : "w-8 h-8 p-0 text-gray-500 hover:text-gray-700 hover:bg-gray-100";
|
|
77
|
+
return (_jsxs("div", { className: "flex items-center gap-1 relative", ref: containerRef, children: [_jsx(Button, { type: "text", shape: "default", className: clsx(btnClass, showEmojiPicker && "bg-blue-100 text-blue-600"), onClick: () => setShowEmojiPicker(!showEmojiPicker), children: EmojiIcon }), showMediaUpload && (_jsxs(_Fragment, { children: [_jsx(Upload, { accept: "image/jpeg, image/png, image/jpg, video/*", beforeUpload: beforeUploadImagesAndVideo, multiple: true, onChange: handleChange, showUploadList: false, fileList: listUploadFiles, children: _jsx(Button, { type: "text", shape: "default", className: btnClass, children: _jsx(Icon, { icon: "image-02-o", size: 22 }) }) }), _jsx(Upload, { accept: ".doc,.docx,.pdf", beforeUpload: beforeUploadFile, onChange: handleChange, showUploadList: false, fileList: listUploadFiles, children: _jsx(Button, { type: "text", shape: "default", className: btnClass, children: AttachIcon }) })] })), showEmojiPicker && (_jsx(EmojiPicker, { onEmojiSelect: handleEmojiSelect, onClose: () => setShowEmojiPicker(false) }))] }));
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuotedMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/QuotedMessage.tsx"],"names":[],"mappings":"AASA,eAAO,MAAM,mBAAmB,sDA4C/B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import useConversationStore from "../../../store/conversation";
|
|
4
|
+
import { Icon } from "../../icon";
|
|
5
|
+
import { useCallback } from "react";
|
|
6
|
+
import { Button } from "antd";
|
|
7
|
+
import { useChatContext } from "../../../context/ChatContext";
|
|
8
|
+
import { generateContentBasedOnMessageType } from "../../../utils/common";
|
|
9
|
+
export const QuotedMessageFooter = () => {
|
|
10
|
+
var _a;
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const quotedMessage = useConversationStore((state) => state.quotedMessage);
|
|
13
|
+
const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
|
|
14
|
+
const user = useChatContext().user;
|
|
15
|
+
const isMe = (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.sendID) === (user === null || user === void 0 ? void 0 : user.userID);
|
|
16
|
+
const handleClearQuotedMessage = useCallback(() => {
|
|
17
|
+
setQuotedMessage(null);
|
|
18
|
+
}, [setQuotedMessage]);
|
|
19
|
+
if (!quotedMessage)
|
|
20
|
+
return null;
|
|
21
|
+
return (_jsxs("div", { className: "flex flex-row items-center py-2 px-3 bg-blue-50 flex-1 gap-3", children: [_jsx("div", { className: "flex pr-3 items-center justify-items-center border-r-2 border-blue-500 h-full", children: _jsx(Icon, { icon: "arrow-forward-b", className: "text-blue-500", size: 16 }) }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-medium", children: t("reply_to", {
|
|
22
|
+
name: isMe ? t("your_self") : (quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.senderNickname) || "",
|
|
23
|
+
}) }), _jsx("p", { className: "text-sm text-gray-500 truncate", children: generateContentBasedOnMessageType(quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.contentType, (_a = quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.textElem) === null || _a === void 0 ? void 0 : _a.content) })] }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: handleClearQuotedMessage, children: _jsx(Icon, { icon: "close-o", size: 16 }) })] }));
|
|
24
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { LinkNode } from "@lexical/link";
|
|
2
|
+
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
|
|
3
|
+
import { ListItemNode, ListNode } from "@lexical/list";
|
|
4
|
+
export declare const editorTheme: {
|
|
5
|
+
text: {
|
|
6
|
+
bold: string;
|
|
7
|
+
italic: string;
|
|
8
|
+
strikethrough: string;
|
|
9
|
+
underline: string;
|
|
10
|
+
};
|
|
11
|
+
quote: string;
|
|
12
|
+
list: {
|
|
13
|
+
nested: {
|
|
14
|
+
listitem: string;
|
|
15
|
+
};
|
|
16
|
+
ol: string;
|
|
17
|
+
ul: string;
|
|
18
|
+
};
|
|
19
|
+
link: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const editorNodes: (typeof HeadingNode | typeof ListNode | typeof ListItemNode | typeof QuoteNode | typeof LinkNode)[];
|
|
22
|
+
export declare const editorOnError: (error: Error) => void;
|
|
23
|
+
export declare const DOCUMENT_TYPES: string[];
|
|
24
|
+
//# sourceMappingURL=editorConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editorConfig.d.ts","sourceRoot":"","sources":["../../../../src/components/message/footer/editorConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEvD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CAcvB,CAAC;AAEF,eAAO,MAAM,WAAW,qGAMvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,SAEzC,CAAC;AAEF,eAAO,MAAM,cAAc,UAI1B,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { LinkNode } from "@lexical/link";
|
|
2
|
+
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
|
|
3
|
+
import { ListItemNode, ListNode } from "@lexical/list";
|
|
4
|
+
export const editorTheme = {
|
|
5
|
+
text: {
|
|
6
|
+
bold: "font-bold",
|
|
7
|
+
italic: "italic",
|
|
8
|
+
strikethrough: "line-through",
|
|
9
|
+
underline: "underline",
|
|
10
|
+
},
|
|
11
|
+
quote: "border-l-4 border-gray-300 pl-4 italic text-gray-600",
|
|
12
|
+
list: {
|
|
13
|
+
nested: { listitem: "list-none" },
|
|
14
|
+
ol: "list-decimal list-inside",
|
|
15
|
+
ul: "list-disc list-inside",
|
|
16
|
+
},
|
|
17
|
+
link: "text-blue-500 underline hover:text-blue-700",
|
|
18
|
+
};
|
|
19
|
+
export const editorNodes = [
|
|
20
|
+
HeadingNode,
|
|
21
|
+
ListNode,
|
|
22
|
+
ListItemNode,
|
|
23
|
+
QuoteNode,
|
|
24
|
+
LinkNode,
|
|
25
|
+
];
|
|
26
|
+
export const editorOnError = (error) => {
|
|
27
|
+
console.error(error);
|
|
28
|
+
};
|
|
29
|
+
export const DOCUMENT_TYPES = [
|
|
30
|
+
"application/pdf",
|
|
31
|
+
"application/msword",
|
|
32
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
33
|
+
];
|
|
@@ -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":"AAYA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAK/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAIvD,UAAU,kBAAkB;IAC1B,cAAc,CAAC,EAAE,gBAAgB,CAAC;CACnC;AASD,eAAO,MAAM,oBAAoB,mDAI/B,CAAC;AAEH,eAAO,MAAM,uBAAuB,gCAAyC,CAAC;AAE9E,QAAA,MAAM,qBAAqB,GAAI,oBAAoB,kBAAkB,4CA8DpE,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -7,9 +7,7 @@ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
|
|
|
7
7
|
import { ToolbarPlugin } from "./ToolbarPlugin";
|
|
8
8
|
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
|
|
9
9
|
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
|
|
10
|
-
import {
|
|
11
|
-
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
|
|
12
|
-
import { ListItemNode, ListNode } from "@lexical/list";
|
|
10
|
+
import { editorTheme, editorNodes, editorOnError } from "./editorConfig";
|
|
13
11
|
import { createContext, useCallback, useContext, useState } from "react";
|
|
14
12
|
import EnterHandler from "./EnterHandler";
|
|
15
13
|
import ActionBar from "./ActionBar";
|
|
@@ -17,31 +15,12 @@ import { useSendMessage } from "../../../hooks/message/useSendMessage";
|
|
|
17
15
|
import FilePreview from "./FilePreview";
|
|
18
16
|
import { useTranslation } from "react-i18next";
|
|
19
17
|
import PasteAndDropPlugin from "./PasteAndDropPlugin";
|
|
20
|
-
|
|
21
|
-
text: {
|
|
22
|
-
bold: "font-bold",
|
|
23
|
-
italic: "italic",
|
|
24
|
-
strikethrough: "line-through",
|
|
25
|
-
underline: "underline",
|
|
26
|
-
},
|
|
27
|
-
quote: "border-l-4 border-gray-300 pl-4 italic text-gray-600",
|
|
28
|
-
list: {
|
|
29
|
-
nested: {
|
|
30
|
-
listitem: "list-none",
|
|
31
|
-
},
|
|
32
|
-
ol: "list-decimal list-inside",
|
|
33
|
-
ul: "list-disc list-inside",
|
|
34
|
-
},
|
|
35
|
-
link: "text-blue-500 underline hover:text-blue-700",
|
|
36
|
-
};
|
|
37
|
-
const onError = (error) => {
|
|
38
|
-
console.error(error);
|
|
39
|
-
};
|
|
18
|
+
import { QuotedMessageFooter } from "./QuotedMessage";
|
|
40
19
|
const initialConfig = {
|
|
41
20
|
namespace: "ChatInput",
|
|
42
|
-
theme,
|
|
43
|
-
onError,
|
|
44
|
-
nodes:
|
|
21
|
+
theme: editorTheme,
|
|
22
|
+
onError: editorOnError,
|
|
23
|
+
nodes: editorNodes,
|
|
45
24
|
};
|
|
46
25
|
export const MessageFooterContext = createContext({
|
|
47
26
|
onSendMessage: () => { },
|
|
@@ -67,6 +46,6 @@ const MessageFooterProvider = ({ currentSession }) => {
|
|
|
67
46
|
}
|
|
68
47
|
setListUploadFiles([]);
|
|
69
48
|
}, [sendMergeMessage, sendTextMessage, listUploadFiles, currentSession]);
|
|
70
|
-
return (_jsx(MessageFooterContext.Provider, { value: { onSendMessage, listUploadFiles, setListUploadFiles }, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsxs("div", { className: "border-t pb-2 flex flex-col gap-1 bg-white", children: [listUploadFiles.length > 0 && _jsx(FilePreview, {}), _jsx(ToolbarPlugin, {}), _jsx("div", { className: "relative px-4", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "border border-indigo-500 rounded-md bg-blue-100 min-h-[64px] max-h-[140px] overflow-y-auto px-3 py-2 text-sm" }), ErrorBoundary: LexicalErrorBoundary, "aria-placeholder": t("enter_message"), placeholder: _jsx("div", { className: "absolute top-2 left-7 pointer-events-none", children: _jsx("p", { className: "text-gray-500 text-sm", children: t("enter_message") }) }) }) }), _jsx(ActionBar, {})] }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {})] }) }));
|
|
49
|
+
return (_jsx(MessageFooterContext.Provider, { value: { onSendMessage, listUploadFiles, setListUploadFiles }, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, 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, {}), _jsx("div", { className: "relative px-4", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "border border-indigo-500 rounded-md bg-blue-100 min-h-[64px] max-h-[140px] overflow-y-auto px-3 py-2 text-sm" }), ErrorBoundary: LexicalErrorBoundary, "aria-placeholder": t("enter_message"), placeholder: _jsx("div", { className: "absolute top-2 left-7 pointer-events-none", children: _jsx("p", { className: "text-gray-500 text-sm", children: t("enter_message") }) }) }) }), _jsx(ActionBar, {})] }), _jsx(LinkPlugin, {}), _jsx(ListPlugin, {}), _jsx(EnterHandler, {}), _jsx(PasteAndDropPlugin, {})] }) }));
|
|
71
50
|
};
|
|
72
51
|
export default MessageFooterProvider;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MessageItem } from "@openim/wasm-client-sdk";
|
|
2
|
+
interface Props {
|
|
3
|
+
message: MessageItem;
|
|
4
|
+
isLatest: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const MessageStatusIndicator: ({ message, isLatest }: Props) => import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export default MessageStatusIndicator;
|
|
8
|
+
//# sourceMappingURL=MessageStatusIndicator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MessageStatusIndicator.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/MessageStatusIndicator.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,yBAAyB,CAAC;AAOrE,UAAU,KAAK;IACb,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,QAAA,MAAM,sBAAsB,GAAI,uBAAuB,KAAK,mDAkB3D,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { MessageStatus } from "@openim/wasm-client-sdk";
|
|
3
|
+
import { LoadingOutlined, CheckCircleFilled, ExclamationCircleFilled, } from "@ant-design/icons";
|
|
4
|
+
const MessageStatusIndicator = ({ message, isLatest }) => {
|
|
5
|
+
if (message.status === MessageStatus.Sending) {
|
|
6
|
+
return _jsx(LoadingOutlined, { className: "text-gray-400 text-sm" });
|
|
7
|
+
}
|
|
8
|
+
if (message.status === MessageStatus.Succeed && isLatest) {
|
|
9
|
+
return _jsx(CheckCircleFilled, { className: "text-blue-500 text-sm" });
|
|
10
|
+
}
|
|
11
|
+
if (message.status === MessageStatus.Failed) {
|
|
12
|
+
return (_jsx(ExclamationCircleFilled, { className: "text-red-500 text-sm" }));
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
};
|
|
16
|
+
export default MessageStatusIndicator;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MessageItem } from "@openim/wasm-client-sdk";
|
|
2
|
+
interface QuoteMessageItemProps {
|
|
3
|
+
message: MessageItem;
|
|
4
|
+
isMine: boolean;
|
|
5
|
+
onPressQuoteMessage?: (clientMsgID: string) => void;
|
|
6
|
+
}
|
|
7
|
+
declare const QuoteMessageItem: ({ message, isMine, onPressQuoteMessage, }: QuoteMessageItemProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export default QuoteMessageItem;
|
|
9
|
+
//# sourceMappingURL=QuoteMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuoteMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/QuoteMessage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAOnE,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,QAAA,MAAM,gBAAgB,GAAI,2CAIvB,qBAAqB,4CAwCvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { generateContentBasedOnMessageType } from "../../../utils/common";
|
|
3
|
+
import { Icon } from "../../icon";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import clsx from "clsx";
|
|
6
|
+
import MediaPreviewIcon from "../MediaPreviewIcon";
|
|
7
|
+
const QuoteMessageItem = ({ message, isMine, onPressQuoteMessage, }) => {
|
|
8
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
const from = isMine ? t("you") : message === null || message === void 0 ? void 0 : message.senderNickname;
|
|
11
|
+
const to = isMine
|
|
12
|
+
? t("your_self")
|
|
13
|
+
: (_b = (_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage) === null || _b === void 0 ? void 0 : _b.senderNickname;
|
|
14
|
+
return (_jsxs("div", { className: clsx("mb-[-4px] flex flex-col gap-1", isMine ? "items-end" : "items-start"), children: [_jsxs("div", { className: "flex flex-row items-center gap-2", children: [_jsx(Icon, { icon: "arrow-reply-b", size: 16, className: "text-blue-500" }), _jsx("span", { className: "text-xs text-gray-500", children: t("replied_to", {
|
|
15
|
+
from: from,
|
|
16
|
+
to: to,
|
|
17
|
+
}) })] }), _jsxs("div", { className: "flex flex-row items-center gap-2 border border-gray-200 rounded-2xl min-w-0 px-3 py-2 bg-gray-100 cursor-pointer", onClick: () => {
|
|
18
|
+
var _a, _b;
|
|
19
|
+
return onPressQuoteMessage === null || onPressQuoteMessage === void 0 ? void 0 : onPressQuoteMessage(((_b = (_a = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _a === void 0 ? void 0 : _a.quoteMessage) === null || _b === void 0 ? void 0 : _b.clientMsgID) || "");
|
|
20
|
+
}, children: [_jsx(MediaPreviewIcon, { message: (_c = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _c === void 0 ? void 0 : _c.quoteMessage }), _jsx("span", { className: "text-sm text-gray-500 truncate", children: generateContentBasedOnMessageType((_e = (_d = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _d === void 0 ? void 0 : _d.quoteMessage) === null || _e === void 0 ? void 0 : _e.contentType, ((_h = (_g = (_f = message === null || message === void 0 ? void 0 : message.quoteElem) === null || _f === void 0 ? void 0 : _f.quoteMessage) === null || _g === void 0 ? void 0 : _g.textElem) === null || _h === void 0 ? void 0 : _h.content) || "") })] })] }));
|
|
21
|
+
};
|
|
22
|
+
export default QuoteMessageItem;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RevokeMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/RevokeMessage.tsx"],"names":[],"mappings":"AAIA,UAAU,sBAAsB;CAAG;AACnC,QAAA,MAAM,iBAAiB,GAAI,GAAG,sBAAsB,4CAQnD,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
const RevokeMessageItem = (_) => {
|
|
5
|
+
const { t } = useTranslation();
|
|
6
|
+
return (_jsx("span", { className: "!text-sm sm:text-base whitespace-pre-wrap italic text-gray-500", children: t("revoked") }));
|
|
7
|
+
};
|
|
8
|
+
export default RevokeMessageItem;
|
|
@@ -23,7 +23,7 @@ const TextMessageItem = (props) => {
|
|
|
23
23
|
const htmlContent = ((_b = (_a = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.content) || "";
|
|
24
24
|
// 🔒 Sanitize HTML to prevent XSS attacks
|
|
25
25
|
const sanitizedContent = sanitizeHtml(htmlContent);
|
|
26
|
-
return (_jsx("div", { className: "!text-sm sm:text-base break-
|
|
26
|
+
return (_jsx("div", { className: "!text-sm sm:text-base break-normal whitespace-pre-line flex-1", style: { overflowWrap: "anywhere" }, dangerouslySetInnerHTML: { __html: sanitizedContent } }));
|
|
27
27
|
}
|
|
28
28
|
return (_jsx("span", { className: "!text-sm sm:text-base whitespace-pre-wrap", children: ((_c = message === null || message === void 0 ? void 0 : message.textElem) === null || _c === void 0 ? void 0 : _c.content) || "" }));
|
|
29
29
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UrlTextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/UrlTextMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"UrlTextMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/UrlTextMessage.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAUtD,UAAU,uBAAuB;IAC/B,OAAO,EAAE,WAAW,CAAC;CACtB;AACD,QAAA,MAAM,kBAAkB,GAAI,OAAO,uBAAuB,4CAwEzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { getHostFromUrl, wrapLinksInHtml, sanitizeHtml } from "../../../utils/common";
|
|
3
|
+
import { getHostFromUrl, wrapLinksInHtml, sanitizeHtml, } from "../../../utils/common";
|
|
4
4
|
import { useFetchExternalLink } from "../../../hooks/common/useFetchExternalLink";
|
|
5
5
|
import { Image } from "antd";
|
|
6
6
|
const UrlTextMessageItem = (props) => {
|
|
@@ -25,8 +25,8 @@ const UrlTextMessageItem = (props) => {
|
|
|
25
25
|
const htmlContent = ((_d = (_c = extendMessageInfo === null || extendMessageInfo === void 0 ? void 0 : extendMessageInfo.messageInfo) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.content) || "";
|
|
26
26
|
// 🔒 Sanitize HTML to prevent XSS attacks
|
|
27
27
|
const sanitizedContent = sanitizeHtml(wrapLinksInHtml(htmlContent));
|
|
28
|
-
return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "!text-sm sm:text-base break-
|
|
28
|
+
return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "!text-sm sm:text-base break-normal whitespace-pre-line flex-1", style: { overflowWrap: "anywhere" }, dangerouslySetInnerHTML: { __html: sanitizedContent } }), !!externalLinkData && (_jsxs("div", { className: "flex items-center rounded-md px-3 py-2 border-l-4 border-l-blue-500 bg-blue-50 gap-2 cursor-pointer overflow-hidden", style: { wordBreak: "break-word", overflowWrap: "anywhere" }, onClick: () => onPressExternalLink((externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.url) || ""), children: [_jsxs("div", { className: "flex flex-1 flex-col gap-1", children: [(externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.title) && (_jsx("span", { className: "!text-sm font-semibold truncate break-normal", children: externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.title })), (externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.description) && (_jsx("span", { className: "!text-sm text-gray-500 line-clamp-2", children: externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.description })), (externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.url) && (_jsx("span", { className: "!text-sm font-medium text-blue-500", children: getHostFromUrl(externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.url) }))] }), ((_e = externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.logo) === null || _e === void 0 ? void 0 : _e.url) && (_jsx(Image, { src: (_f = externalLinkData === null || externalLinkData === void 0 ? void 0 : externalLinkData.logo) === null || _f === void 0 ? void 0 : _f.url, width: 48, height: 48 }))] }))] }));
|
|
29
29
|
}
|
|
30
|
-
return (_jsx("span", { className: "!text-sm sm:text-base break-
|
|
30
|
+
return (_jsx("span", { className: "!text-sm sm:text-base break-normal whitespace-pre-line flex-1", style: { overflowWrap: "anywhere" }, children: ((_h = (_g = message === null || message === void 0 ? void 0 : message.urlTextElem) === null || _g === void 0 ? void 0 : _g.urls) === null || _h === void 0 ? void 0 : _h[0]) || "" }));
|
|
31
31
|
};
|
|
32
32
|
export default UrlTextMessageItem;
|
|
@@ -2,7 +2,12 @@ import { MessageItem as MessageItemType } from "@openim/wasm-client-sdk";
|
|
|
2
2
|
interface MessageItemProps {
|
|
3
3
|
message: MessageItemType;
|
|
4
4
|
allMessages: MessageItemType[];
|
|
5
|
+
contextMenuOpen?: boolean;
|
|
6
|
+
onContextMenuOpenChange?: (open: boolean) => void;
|
|
7
|
+
onRevokeMessage?: (clientMsgID: string) => void;
|
|
8
|
+
onQuoteMessage?: (message: MessageItemType) => void;
|
|
9
|
+
onPressQuoteMessage?: (clientMsgID: string) => void;
|
|
5
10
|
}
|
|
6
|
-
declare const MessageItem: ({ message, allMessages }: MessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
declare const MessageItem: ({ message, allMessages, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, }: MessageItemProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
7
12
|
export default MessageItem;
|
|
8
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/message/item/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,IAAI,eAAe,EAG/B,MAAM,yBAAyB,CAAC;AA2BjC,UAAU,gBAAgB;IACxB,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,eAAe,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,QAAA,MAAM,WAAW,GAAI,2HAQlB,gBAAgB,mDA0PlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import dayjs from "dayjs";
|
|
3
3
|
import clsx from "clsx";
|
|
4
|
-
import { Avatar } from "antd";
|
|
5
|
-
import { MessageType, } from "@openim/wasm-client-sdk";
|
|
4
|
+
import { Avatar, Dropdown } from "antd";
|
|
5
|
+
import { MessageStatus, MessageType, } from "@openim/wasm-client-sdk";
|
|
6
6
|
import TextMessageItem from "./TextMessage";
|
|
7
7
|
import ImageMessageItem from "./ImageMessage";
|
|
8
8
|
import FileMessageItem from "./FileMessage";
|
|
@@ -12,27 +12,26 @@ import { MSG_ITEM_CONTENT_PREFIX, MSG_ITEM_PREFIX } from "../../../constants";
|
|
|
12
12
|
import { formatTimestamp } from "../../../utils/common";
|
|
13
13
|
import useAuthStore from "../../../store/auth";
|
|
14
14
|
import useConversationStore from "../../../store/conversation";
|
|
15
|
-
import { useMemo } from "react";
|
|
15
|
+
import { useCallback, useMemo } from "react";
|
|
16
|
+
import { Trans, useTranslation } from "react-i18next";
|
|
16
17
|
import UrlTextMessageItem from "./UrlTextMessage";
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
import MessageStatusIndicator from "./MessageStatusIndicator";
|
|
19
|
+
import { useSendMessage, isMediaResendable, } from "../../../hooks/message/useSendMessage";
|
|
20
|
+
import { Icon } from "../../icon";
|
|
21
|
+
import RevokeMessageItem from "./RevokeMessage";
|
|
22
|
+
import QuoteMessageItem from "./QuoteMessage";
|
|
23
|
+
const ICON_COLOR = "#3278f7";
|
|
24
|
+
const MessageItem = ({ message, allMessages, contextMenuOpen, onContextMenuOpenChange, onRevokeMessage, onQuoteMessage, onPressQuoteMessage, }) => {
|
|
25
|
+
var _a, _b, _c, _d, _e;
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
const { resendMessage } = useSendMessage();
|
|
19
28
|
const userID = useAuthStore((state) => state.userID);
|
|
20
29
|
const isCrm = useAuthStore((state) => state.isCrm);
|
|
21
30
|
const conversationData = useConversationStore((state) => state.conversationData);
|
|
22
|
-
const
|
|
23
|
-
var _a, _b, _c;
|
|
24
|
-
try {
|
|
25
|
-
const isChatSupport = (_c = (_b = (_a = JSON.parse((conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex) || "{}")) === null || _a === void 0 ? void 0 : _a.sessionInfo) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.botId;
|
|
26
|
-
return isChatSupport && isCrm;
|
|
27
|
-
}
|
|
28
|
-
catch (_d) {
|
|
29
|
-
console.log("Failed to parse conversationData.ex");
|
|
30
|
-
}
|
|
31
|
-
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, isCrm]);
|
|
32
|
-
const isVisibleGroup = visibleTypeMessage.includes(message === null || message === void 0 ? void 0 : message.contentType);
|
|
33
|
-
const renderMessageByType = (message) => {
|
|
31
|
+
const renderMessageByType = useCallback((message) => {
|
|
34
32
|
switch (message === null || message === void 0 ? void 0 : message.contentType) {
|
|
35
33
|
case MessageType.TextMessage:
|
|
34
|
+
case MessageType.QuoteMessage:
|
|
36
35
|
return _jsx(TextMessageItem, { message: message });
|
|
37
36
|
case MessageType.PictureMessage:
|
|
38
37
|
return _jsx(ImageMessageItem, { message: message });
|
|
@@ -42,13 +41,70 @@ const MessageItem = ({ message, allMessages }) => {
|
|
|
42
41
|
return _jsx(VideoMessageItem, { message: message });
|
|
43
42
|
case MessageType.UrlTextMessage:
|
|
44
43
|
return _jsx(UrlTextMessageItem, { message: message });
|
|
44
|
+
case MessageType.RevokeMessage:
|
|
45
|
+
return _jsx(RevokeMessageItem, {});
|
|
45
46
|
default:
|
|
46
47
|
return _jsx(TextMessageItem, { message: message });
|
|
47
48
|
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
}, [message]);
|
|
50
|
+
const { isReplyable, isRevocable, isMine } = useMemo(() => {
|
|
51
|
+
const isMyMessage = (message === null || message === void 0 ? void 0 : message.sendID) === userID;
|
|
52
|
+
const isOlderThanOneDay = dayjs().diff(dayjs(message === null || message === void 0 ? void 0 : message.sendTime), "days", true) >= 1;
|
|
53
|
+
return {
|
|
54
|
+
isReplyable: message.status === MessageStatus.Succeed,
|
|
55
|
+
isRevocable: isMyMessage &&
|
|
56
|
+
message.status === MessageStatus.Succeed &&
|
|
57
|
+
!isOlderThanOneDay,
|
|
58
|
+
isMine: isMyMessage,
|
|
59
|
+
};
|
|
60
|
+
}, [userID, message]);
|
|
61
|
+
const contextMenuItems = useMemo(() => {
|
|
62
|
+
if ((message === null || message === void 0 ? void 0 : message.contentType) === MessageType.RevokeMessage)
|
|
63
|
+
return [];
|
|
64
|
+
return [
|
|
65
|
+
...(isReplyable
|
|
66
|
+
? [
|
|
67
|
+
{
|
|
68
|
+
key: "TB01",
|
|
69
|
+
label: t("context_menu_reply"),
|
|
70
|
+
icon: (_jsx(Icon, { icon: "arrow-reply-alt-o", size: 18, color: ICON_COLOR })),
|
|
71
|
+
onClick: () => onQuoteMessage === null || onQuoteMessage === void 0 ? void 0 : onQuoteMessage(message),
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
: []),
|
|
75
|
+
...(isRevocable
|
|
76
|
+
? [
|
|
77
|
+
{
|
|
78
|
+
key: "TB05",
|
|
79
|
+
label: t("context_menu_revoke"),
|
|
80
|
+
icon: _jsx(Icon, { icon: "arrow-reload-o", size: 18, color: ICON_COLOR }),
|
|
81
|
+
onClick: () => onRevokeMessage === null || onRevokeMessage === void 0 ? void 0 : onRevokeMessage((message === null || message === void 0 ? void 0 : message.clientMsgID) || ""),
|
|
82
|
+
},
|
|
83
|
+
]
|
|
84
|
+
: []),
|
|
85
|
+
];
|
|
86
|
+
}, [
|
|
87
|
+
isReplyable,
|
|
88
|
+
isRevocable,
|
|
89
|
+
t,
|
|
90
|
+
onRevokeMessage,
|
|
91
|
+
message === null || message === void 0 ? void 0 : message.contentType,
|
|
92
|
+
message === null || message === void 0 ? void 0 : message.clientMsgID,
|
|
93
|
+
onQuoteMessage,
|
|
94
|
+
]);
|
|
95
|
+
const showSenderInfo = useMemo(() => {
|
|
96
|
+
var _a, _b, _c;
|
|
97
|
+
try {
|
|
98
|
+
const isChatSupport = (_c = (_b = (_a = JSON.parse((conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex) || "{}")) === null || _a === void 0 ? void 0 : _a.sessionInfo) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.botId;
|
|
99
|
+
return isChatSupport && isCrm && !isMine;
|
|
100
|
+
}
|
|
101
|
+
catch (_d) {
|
|
102
|
+
console.log("Failed to parse conversationData.ex");
|
|
103
|
+
}
|
|
104
|
+
}, [conversationData === null || conversationData === void 0 ? void 0 : conversationData.ex, isCrm, isMine]);
|
|
105
|
+
const hasContextMenu = contextMenuItems.length > 0;
|
|
106
|
+
const isLatestMine = ((_a = allMessages.find((m) => m.sendID === userID)) === null || _a === void 0 ? void 0 : _a.clientMsgID) ===
|
|
107
|
+
message.clientMsgID;
|
|
52
108
|
const previousMessage = getVisibleNeighbor(allMessages, message, "prev");
|
|
53
109
|
const nextMessage = getVisibleNeighbor(allMessages, message, "next");
|
|
54
110
|
const prevSameUser = (previousMessage === null || previousMessage === void 0 ? void 0 : previousMessage.sendID) === (message === null || message === void 0 ? void 0 : message.sendID);
|
|
@@ -58,13 +114,20 @@ const MessageItem = ({ message, allMessages }) => {
|
|
|
58
114
|
const showTimeBreak = prevTimeBreak;
|
|
59
115
|
const showSenderAvatar = !nextSameUser;
|
|
60
116
|
const showSenderName = !prevSameUser && !isMine;
|
|
61
|
-
if (!isCrm &&
|
|
117
|
+
if (!isCrm &&
|
|
118
|
+
(MessageType.CustomMessage === (message === null || message === void 0 ? void 0 : message.contentType) ||
|
|
119
|
+
!visibleTypeMessage.includes(message === null || message === void 0 ? void 0 : message.contentType))) {
|
|
62
120
|
return null;
|
|
63
121
|
}
|
|
64
122
|
return (_jsxs("div", { className: "flex flex-col gap-2 py-1 px-3 sm:px-4 min-w-0", id: `${MSG_ITEM_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, children: [showTimeBreak && (_jsx("div", { className: "flex justify-center", children: _jsx("span", { className: "text-xs text-gray-600 text-center bg-neutral-100 px-2 py-1 rounded-full", children: formatTimestamp(message.sendTime, {
|
|
65
123
|
dateMonthFormat: "DD MMMM",
|
|
66
|
-
}) }) })), _jsx("div", { className: clsx("flex min-w-0", isMine ? "justify-end" : "justify-start"), children: _jsxs("div", { className: clsx("flex flex-1 items-end gap-2 min-w-0", isMine ? "justify-end" : "justify-start"), children: [
|
|
67
|
-
|
|
68
|
-
|
|
124
|
+
}) }) })), _jsx("div", { className: clsx("flex min-w-0", isMine ? "justify-end" : "justify-start"), children: _jsxs("div", { className: clsx("flex flex-1 items-end gap-2 min-w-0", isMine ? "justify-end" : "justify-start"), children: [showSenderInfo && (_jsx("div", { className: "flex items-center justify-center w-[32px] h-[32px]", children: showSenderAvatar && (_jsx(Avatar, { src: message === null || message === void 0 ? void 0 : message.senderFaceUrl, children: ((_c = (_b = message === null || message === void 0 ? void 0 : message.senderNickname) === null || _b === void 0 ? void 0 : _b.charAt) === null || _c === void 0 ? void 0 : _c.call(_b, 0)) || "A" })) })), _jsxs("div", { className: clsx("flex flex-col flex-[0.8] min-w-0", isMine ? "items-end" : "items-start"), children: [showSenderName && showSenderInfo && (_jsx("span", { className: "text-xs font-bold mb-1 px-3 mt-2", children: message === null || message === void 0 ? void 0 : message.senderNickname })), _jsxs("div", { className: clsx("flex flex-col flex-1", isMine ? "items-end" : "items-start"), children: [(message === null || message === void 0 ? void 0 : message.quoteElem) && (_jsx(QuoteMessageItem, { message: message, isMine: isMine, onPressQuoteMessage: onPressQuoteMessage })), _jsxs("div", { className: "flex items-end gap-1.5", children: [isMine && (_jsx(MessageStatusIndicator, { message: message, isLatest: isLatestMine })), _jsx(Dropdown, { menu: { items: contextMenuItems }, trigger: hasContextMenu ? ["contextMenu"] : [], open: contextMenuOpen, onOpenChange: onContextMenuOpenChange, children: _jsxs("div", { className: clsx("px-3 py-2 rounded-2xl max-w-full min-w-0 break-normal flex flex-col flex-1 text-gray-900 gap-1 w-fit", isMine ? "bg-blue-100" : "bg-white"), style: {
|
|
125
|
+
wordBreak: "break-word",
|
|
126
|
+
overflowWrap: "anywhere",
|
|
127
|
+
}, id: `${MSG_ITEM_CONTENT_PREFIX}${message === null || message === void 0 ? void 0 : message.clientMsgID}`, children: [(message === null || message === void 0 ? void 0 : message.contentType) === MessageType.MergeMessage ? (_jsxs("div", { children: [(_e = (_d = message === null || message === void 0 ? void 0 : message.mergeElem) === null || _d === void 0 ? void 0 : _d.multiMessage) === null || _e === void 0 ? void 0 : _e.map((item) => {
|
|
128
|
+
return renderMessageByType(item);
|
|
129
|
+
}), (message === null || message === void 0 ? void 0 : message.textElem) && (_jsx(TextMessageItem, { message: message }))] })) : (renderMessageByType(message)), _jsx("span", { className: clsx("text-xs text-gray-500 text-right"), children: dayjs(message === null || message === void 0 ? void 0 : message.sendTime).format("HH:mm") })] }) })] })] }), isMine && message.status === MessageStatus.Failed && (_jsx("span", { className: "text-red-500 text-xs mt-1", children: isMediaResendable(message) ? (_jsx(Trans, { i18nKey: "message_send_failed", components: {
|
|
130
|
+
bold: (_jsx("strong", { className: "cursor-pointer", onClick: () => resendMessage(message) })),
|
|
131
|
+
} })) : (t("message_send_failed_no_retry")) }))] })] }) })] }, message === null || message === void 0 ? void 0 : message.clientMsgID));
|
|
69
132
|
};
|
|
70
133
|
export default MessageItem;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { UploadFile } from "antd";
|
|
2
|
+
interface RichTextEditorProps {
|
|
3
|
+
initialHtml?: string;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
onChange?: (html: string, plainText: string) => void;
|
|
6
|
+
onFilesChange?: (files: UploadFile[]) => void;
|
|
7
|
+
minHeight?: string;
|
|
8
|
+
showMediaUpload?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export default function RichTextEditor({ initialHtml, placeholder, onChange, onFilesChange, minHeight, showMediaUpload, }: RichTextEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=RichTextEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RichTextEditor.d.ts","sourceRoot":"","sources":["../../../src/components/richTextEditor/RichTextEditor.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AA0ClC,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EACrC,WAAW,EACX,WAAW,EACX,QAAQ,EACR,aAAa,EACb,SAAmB,EACnB,eAAsB,GACvB,EAAE,mBAAmB,2CA6DrB"}
|