import 'quill-mention/dist/quill.mention.css'; import 'react-quill/dist/quill.snow.css'; import 'react-quill-emoji/dist/quill-emoji.css'; import ImageUploader from '@writergate/quill-image-uploader-nextjs'; import { Image, Modal, Space } from 'antd'; import _ from 'lodash'; import React, { useRef, useState } from 'react'; import ReactQuill, { Quill } from 'react-quill'; import { postMessage } from '../services/chat'; import styles from '../style.module.css'; import { qiniuUploadMD5 } from '../utils/qiniu'; import { fileSize, qiniuUrl } from '../utils/utils'; import Button from './Button'; import IconFont from './IconFonts'; import Qiniu from './ReactQiniu'; type PropType = { roomId: string; username: string; members: any[]; qiniu_url: string; }; let record: string[] = []; Quill.register('modules/imageUploader', ImageUploader); const ChatEditor: React.FC = ({ roomId, username, members, qiniu_url }) => { let message: Chat.Message[] = []; const [previewModalVisible, setPreviewModalVisible] = useState(false); const [pastedModalVisible, setPastedModalVisible] = useState(false); const [pastedFiles, setPastedFiles] = useState([]); const [uploadedFiles, setUploadedFiles] = useState([]); const [filePreview, setFilePreview] = useState([]); const quillRef = useRef(); const quill = quillRef?.current; const userList = members.map((v) => ({ user_id: v.user_id, avatar: v.avatar, value: v.user_name, })); const sendMessage = () => { const scrollDiv = document.getElementById('chatlist'); const blocks = quill.editor.editor.delta; if (pastedFiles.length > 0) { message = pastedFiles.map((f: any) => ({ type: 'attachment', sub_type: 'image', text: '', source_url: f.source_url, })); } else if (uploadedFiles.length > 0) { message = uploadedFiles.map((f: string) => ({ type: 'attachment', sub_type: 'image', text: '', source_url: f, })); } else { message = blocks.map((v) => { if (v.insert.mention) { return { type: 'mention', text: `@${v.insert.mention.value}`, user_id: Number(userList.filter((u) => u.value === v.insert.mention.value).map((s) => s.user_id)), }; } if (v.attributes && !v.attributes.imageBlot) { return { type: 'task_mention', text: v.insert, card_id: v.attributes.link, }; } if (v.insert.emoji) { return { type: 'emoicon', text: `:${v.insert.emoji}:`, }; } return { type: 'text', text: v.insert }; }); } if ( uploadedFiles.length > 0 || pastedFiles.length > 0 || message.filter((m) => m.text.replace(/[\r\n]/g, '') !== '').length > 0 ) { postMessage(username, roomId, message, [ ...new Set(message.filter((v) => v.type === 'mention').map((v) => v.user_id!)), ]).then(() => { if (scrollDiv) { scrollDiv.scrollIntoView({ block: 'end' }); } setUploadedFiles([]); setPastedFiles([]); record = []; quill.editor.focus(); quill.editor.setSelection(quill.editor.getLength(), 0); }); } }; const onDrop = (droppedFiles: any[]) => { setFilePreview(droppedFiles); setPreviewModalVisible(true); Promise.all(droppedFiles.map((v) => v.uploadPromise)) .then((values) => setUploadedFiles(values.map((s) => qiniuUrl(s.body.key, qiniu_url)))) .catch((e) => console.error(e)); }; const EditorToolbar = () => ( ); const modules = { toolbar: { container: '#toolbar', }, // 'emoji-toolbar': true, keyboard: { bindings: { tab: { key: 13, handler() { sendMessage(); quill.editor.setContents([{ insert: '\n' }]); }, }, }, }, imageUploader: { upload: (fileToUpload) => { const blocks = quill.editor.editor.delta; return new Promise(() => { qiniuUploadMD5( fileToUpload, undefined, [], (res) => { record = record.concat( Object.assign(fileToUpload, { source_url: qiniuUrl(res.key, qiniu_url), }) ); setPastedFiles(record); setPastedModalVisible(true); quill.editor.setContents(blocks.filter((v) => v.insert.image === undefined)); }, () => {} ); }); }, }, }; return ( <>
{ setPreviewModalVisible(false); setUploadedFiles([]); quill.editor.setSelection(quill.editor.getLength(), 0); }} onOk={() => { sendMessage(); setPreviewModalVisible(false); setFilePreview([]); }} okText="发送" > {filePreview.length > 1 ? filePreview.map((v: any) => (
{v.name}
{fileSize(v.size)}
{ setFilePreview(filePreview.filter((a) => a !== v)); Promise.all(filePreview.filter((a) => a !== v).map((m) => m.uploadPromise)) .then((values) => setUploadedFiles(values.map((s) => qiniuUrl(s.body.key, qiniu_url)))) .catch((e) => console.error(e)); }} />
)) : filePreview.map((v) => (
{v.name}
))}
{ setPastedModalVisible(false); setPastedFiles([]); record = []; quill.editor.setSelection(quill.editor.getLength(), 0); }} onOk={() => { sendMessage(); setPastedModalVisible(false); }} okText="发送" > {pastedFiles.length > 1 ? pastedFiles.map((v: any) => (
{v.name}
{fileSize(v.size)}
{ setPastedFiles(pastedFiles.filter((a) => a !== v)); Promise.all(filePreview.filter((a) => a !== v).map((m) => m.uploadPromise)) .then((values) => setUploadedFiles(values.map((s) => qiniuUrl(s.body.key, qiniu_url)))) .catch((e) => console.error(e)); }} />
)) : pastedFiles.map((v) => (
{v.name}
))}
); }; export default ChatEditor;