You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Global-sales/src/views/Conversations/Components/InputComposer.jsx

191 lines
8.4 KiB
JavaScript

import React, { useState, useRef, useEffect } from 'react';
import { Input, Flex, Button, Image } from 'antd';
// import { Input } from 'react-chat-elements';
import useAuthStore from '@/stores/AuthStore';
import useConversationStore from '@/stores/ConversationStore';
import {
SendOutlined,
MessageOutlined,
SmileOutlined,
PictureOutlined,
CommentOutlined,
UploadOutlined,
CloudUploadOutlined,
FolderAddOutlined,
FilePdfOutlined,
CloseCircleOutlined,
YoutubeOutlined,
AudioOutlined, PlayCircleOutlined, LoadingOutlined, CheckCircleOutlined, FileOutlined
} from '@ant-design/icons';
import { isEmpty, olog } from '@/utils/utils';
import { v4 as uuid } from 'uuid';
import { sentMsgTypeMapped } from '@/lib/msgUtils';
import InputTemplate from './Input/Template';
import InputEmoji from './Input/Emoji';
import InputMediaUpload from './Input/MediaUpload';
import dayjs from 'dayjs';
const InputComposer = () => {
const userId = useAuthStore(state => state.loginUser.userId);
const websocket = useConversationStore(state => state.websocket);
const websocketOpened = useConversationStore(state => state.websocketOpened);
const currentConversation = useConversationStore(state => state.currentConversation);
const referenceMsg = useConversationStore(state => state.referenceMsg);
const setReferenceMsg = useConversationStore(state => state.setReferenceMsg);
const complexMsg = useConversationStore(state => state.complexMsg);
const setComplexMsg = useConversationStore(state => state.setComplexMsg);
const sentOrReceivedNewMessage = useConversationStore(state => state.sentOrReceivedNewMessage);
const talkabled = !isEmpty(currentConversation.sn) && websocketOpened;
const gt24h = currentConversation.last_received_time ? dayjs().diff(dayjs(currentConversation.last_received_time), 'hour') > 24 : true;
const textabled = talkabled && !gt24h;
const textInputRef = useRef(null);
const [textContent, setTextContent] = useState('');
const invokeSendMessage = (msgObj) => {
const msgObjMerge = {
sender: 'me',
senderName: 'me',
to: currentConversation.whatsapp_phone_number,
date: new Date(),
status: 'waiting',
...(referenceMsg.id ? { context: { message_id: referenceMsg.id }, message_origin: referenceMsg } : {}),
...msgObj,
id: `${currentConversation.sn}.${uuid()}`,
};
olog('sendMessage------------------', msgObjMerge)
const contentToSend = sentMsgTypeMapped[msgObjMerge.type].contentToSend(msgObjMerge);
console.log('content to send-------------------------------------', contentToSend);
websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn });
const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge);
console.log(contentToRender, 'contentToRender sendMessage------------------');
sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender);
setTextContent('');
setReferenceMsg({});
setComplexMsg({});
};
/**
* 先推到消息记录上面, 再发送
*/
const invokeUploadFileMessage = (msgObj) => {
const msgObjMerge = {
sender: 'me',
senderName: 'me',
to: currentConversation.whatsapp_phone_number,
date: new Date(),
status: 'waiting',
...(referenceMsg.id ? { context: { message_id: referenceMsg.id }, message_origin: referenceMsg } : {}),
...msgObj,
id: `${currentConversation.sn}.${msgObj.id}`,
};
const contentToRender = sentMsgTypeMapped[msgObjMerge.type].contentToRender(msgObjMerge);
sentOrReceivedNewMessage(contentToRender.conversationid, contentToRender);
};
const invokeSendUploadMessage = (msgObj) => {
const msgObjMerge = {
sender: 'me',
senderName: 'me',
to: currentConversation.whatsapp_phone_number,
date: new Date(),
status: 'waiting',
...(referenceMsg.id ? { context: { message_id: referenceMsg.id }, message_origin: referenceMsg } : {}),
...msgObj,
id: `${currentConversation.sn}.${msgObj.id}`,
};
const contentToSend = sentMsgTypeMapped[msgObjMerge.type].contentToSend(msgObjMerge);
websocket.sendMessage({ ...contentToSend, opi_sn: userId, coli_sn: currentConversation.coli_sn });
}
const focusInput = () => {
textInputRef.current.focus({ cursor: 'end', preventScroll: true, });
};
const addEmoji = emoji => {
setTextContent(prevValue => {
return prevValue + emoji;
});
};
const handleSendText = () => {
if (textContent.trim() !== '' || !isEmpty(complexMsg)) {
const msgObj = {
type: 'text',
text: textContent,
...complexMsg,
};
invokeSendMessage(msgObj);
}
};
useEffect(() => {
focusInput();
return () => {};
}, [referenceMsg, complexMsg]);
return (
<div>
{referenceMsg.id && (
<Flex justify='space-between' className='reply-to bg-gray-100 p-1 rounded-none text-slate-500'>
<div className='referrer-msg border-l-3 border-y-0 border-r-0 border-slate-300 border-solid pl-2 pr-1 py-1'>
<span className=' text-primary pr-1 italic align-top'>{referenceMsg.senderName}</span>
{referenceMsg.type === 'photo' && <Image width={100} src={referenceMsg.data.uri} />}
<span className='px-1'>{referenceMsg.originText}</span>
</div>
<Button type='text' title='取消引用' className=' rounded-none text-slate-500' icon={<CloseCircleOutlined />} size={'middle'} onClick={() => setReferenceMsg({})} />
</Flex>
)}
{complexMsg.id && (
<Flex justify='space-between' className='reply-to bg-gray-100 p-1 rounded-none text-slate-500'>
<div className='pl-2 pr-1 py-1'>
{(complexMsg.type === 'photo' && complexMsg.data.uri) && <Image width={100} src={complexMsg.data.uri} />}
{complexMsg.type === 'video' && <FileOutlined className=' text-red-400' />}
{complexMsg.type !== 'photo' && <span className='px-1'>{complexMsg.name}</span>}
{complexMsg.status === 'loading' && <LoadingOutlined className='px-1' />}
{complexMsg.status === 'done' && <CheckCircleOutlined className='px-1 text-primary' />}
{complexMsg.status === 'error' && <><CloseCircleOutlined className='px-1 text-red-400' /> <span>添加失败</span> </>}
</div>
<Button type='text' title='删除' className=' rounded-none text-slate-500' icon={<CloseCircleOutlined />} size={'middle'} onClick={() => setComplexMsg({})} />
</Flex>
)}
<Input.TextArea
ref={textInputRef}
size='large'
placeholder={gt24h ? 'This session has expired. Please send a template message to activate the session' : 'Enter for Send, Shift+Enter for new line'}
rows={2}
disabled={!textabled}
value={textContent}
onChange={(e) => setTextContent(e.target.value)}
className='rounded-b-none emoji'
onPressEnter={(e) => {
if (!e.shiftKey) {
e.preventDefault();
handleSendText();
}
}}
autoSize={{ minRows: 2, maxRows: 6 }}
/>
<Flex justify={'space-between'} className=' bg-gray-200 p-1 rounded-b'>
<Flex gap={4} className='*:text-primary *:rounded-none'>
<InputTemplate key='templates' disabled={!talkabled || textabled} invokeSendMessage={invokeSendMessage} />
<InputEmoji key='emoji' disabled={!textabled} inputEmoji={addEmoji} />
<InputMediaUpload key={'addNewMedia'} disabled={!textabled} {...{invokeUploadFileMessage, invokeSendUploadMessage}} />
{/* <Button type='text' className='' icon={<YoutubeOutlined />} size={'middle'} />
<Button type='text' className='' icon={<AudioOutlined />} size={'middle'} />
<Button type='text' className='' icon={<FolderAddOutlined />} size={'middle'} />
<Button type='text' className='' icon={<CloudUploadOutlined />} size={'middle'} />
<Button type='text' className='' icon={<FilePdfOutlined />} size={'middle'} /> */}
</Flex>
<Button key={'send-btn'} onClick={handleSendText} type='primary' size='middle' icon={<SendOutlined />} disabled={!textabled}>
Send
</Button>
</Flex>
</div>
);
};
export default InputComposer;