消息滚动; 修复错误

dev/mobile
Lei OT 2 years ago
parent 944038f1f9
commit ba10f21641

@ -375,6 +375,7 @@ export const whatsappError = {
* 系统弹窗通知 * 系统弹窗通知
*/ */
export const handleNotification = (title, _options) => { export const handleNotification = (title, _options) => {
var notification;
const options = { const options = {
requireInteraction: true, // 设置手动关闭 requireInteraction: true, // 设置手动关闭
tag: 'global-sales-notification', // 通知ID同类通知建议设置相同ID避免通知过多遮挡桌面 tag: 'global-sales-notification', // 通知ID同类通知建议设置相同ID避免通知过多遮挡桌面
@ -384,11 +385,11 @@ export const handleNotification = (title, _options) => {
// 检查用户是否同意接受通知 // 检查用户是否同意接受通知
if (Notification.permission === 'granted') { if (Notification.permission === 'granted') {
var notification = new Notification(title, options); notification = new Notification(title, options);
} else if (Notification.permission !== 'denied') { } else if (Notification.permission !== 'denied') {
Notification.requestPermission().then(function (permission) { Notification.requestPermission().then(function (permission) {
if (permission === 'granted') { if (permission === 'granted') {
var notification = new Notification(title, options); notification = new Notification(title, options);
} }
}); });
} else { } else {

@ -16,7 +16,7 @@ const InputTemplate = ({ disabled = false, inputEmoji }) => {
placement={'right'} placement={'right'}
overlayInnerStyle={{ padding: 0, borderRadius: '8px' }} overlayInnerStyle={{ padding: 0, borderRadius: '8px' }}
// fresh // fresh
content={<EmojiPicker skinTonesDisabled={true} emojiStyle='facebook' onEmojiClick={handlePickEmoji} />} content={<EmojiPicker skinTonesDisabled={true} emojiStyle='apple' onEmojiClick={handlePickEmoji} />}
// title='😀' // title='😀'
trigger='click' trigger='click'
open={openPopup} open={openPopup}

@ -67,7 +67,13 @@ const InputComposer = () => {
}; };
const focusInput = () => { const focusInput = () => {
textInputRef.current.focus({ cursor: 'end' }); textInputRef.current.focus({ cursor: 'end', preventScroll: true, });
};
const addEmoji = emoji => {
setTextContent(prevValue => {
return prevValue + emoji;
});
}; };
const handleSendText = () => { const handleSendText = () => {
@ -129,7 +135,7 @@ const InputComposer = () => {
<Flex justify={'space-between'} className=' bg-gray-200 p-1 rounded-b'> <Flex justify={'space-between'} className=' bg-gray-200 p-1 rounded-b'>
<Flex gap={4} className='*:text-primary *:rounded-none'> <Flex gap={4} className='*:text-primary *:rounded-none'>
<InputTemplate key='templates' disabled={textabled} invokeSendMessage={invokeSendMessage} /> <InputTemplate key='templates' disabled={textabled} invokeSendMessage={invokeSendMessage} />
<InputEmoji key='emoji' disabled={!textabled} inputEmoji={(s) => setTextContent(`${textContent}${s}`)} /> <InputEmoji key='emoji' disabled={!textabled} inputEmoji={addEmoji} />
{/* <InputImageUpload key={'addNewPic'} disabled={!textabled} invokeSendMessage={invokeSendMessage} /> */} {/* <InputImageUpload key={'addNewPic'} disabled={!textabled} invokeSendMessage={invokeSendMessage} /> */}
{/* <Button type='text' className='' icon={<YoutubeOutlined />} size={'middle'} /> {/* <Button type='text' className='' icon={<YoutubeOutlined />} size={'middle'} />
<Button type='text' className='' icon={<AudioOutlined />} size={'middle'} /> <Button type='text' className='' icon={<AudioOutlined />} size={'middle'} />

@ -1,4 +1,4 @@
import { useEffect, useState, useRef, useMemo, memo } from 'react'; import { useEffect, useState, useRef, useMemo, memo, createRef, forwardRef } from 'react';
import { Image, Spin, Dropdown } from 'antd'; import { Image, Spin, Dropdown } from 'antd';
import { DownOutlined } from '@ant-design/icons'; import { DownOutlined } from '@ant-design/icons';
import { MessageBox } from 'react-chat-elements'; import { MessageBox } from 'react-chat-elements';
@ -8,16 +8,27 @@ import { Emoji } from 'emoji-picker-react';
import { olog } from '@/utils/utils'; import { olog } from '@/utils/utils';
const Messages = () => { const Messages = () => {
const currentConversation = useConversationStore(useShallow((state) => state.currentConversation)); // const currentConversation = useConversationStore(useShallow((state) => state.currentConversation));
const setReferenceMsg = useConversationStore(useShallow((state) => state.setReferenceMsg)); const setReferenceMsg = useConversationStore(useShallow((state) => state.setReferenceMsg));
const msgListLoading = useConversationStore(useShallow((state) => state.msgListLoading)); const msgListLoading = useConversationStore(useShallow((state) => state.msgListLoading));
const activeMessages = useConversationStore(useShallow((state) => (state.currentConversation.sn ? state.activeConversations[state.currentConversation.sn] : []))); const activeMessages = useConversationStore(useShallow((state) => (state.currentConversation.sn ? state.activeConversations[state.currentConversation.sn] : [])));
olog('invoke msg list'); olog('invoke msg list');
const messagesEndRef = useRef(null); const scrollToMessage = (id, index) => {
const _i = index || activeMessages.findIndex((msg) => msg.id === id);
if (_i >= 0) {
messageRefs.current[_i].current.scrollIntoView({ behavior: "smooth", block: "start" });
}
}
useEffect(() => { useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); if (activeMessages.length > 0) {
}, [currentConversation.last_received_time]); scrollToMessage(null, activeMessages.length - 1);
}
}, [activeMessages]);
const messageRefs = useRef([]);
messageRefs.current = activeMessages.map((_, i) => messageRefs.current[i] ?? createRef());
const [previewVisible, setPreviewVisible] = useState(false); const [previewVisible, setPreviewVisible] = useState(false);
const [previewSrc, setPreviewSrc] = useState(); const [previewSrc, setPreviewSrc] = useState();
@ -42,7 +53,7 @@ const Messages = () => {
// if (/\p{Emoji}\uFE0F?/u.test(part)) { // if (/\p{Emoji}\uFE0F?/u.test(part)) {
if (/\p{Emoji_Presentation}/u.test(part)) { if (/\p{Emoji_Presentation}/u.test(part)) {
const code = [...part].map((e) => e.codePointAt(0).toString(16)).join(`-`); const code = [...part].map((e) => e.codePointAt(0).toString(16)).join(`-`);
return <Emoji key={`${part}${index}${code}`} unified={code} size={24} emojiStyle='facebook' />; return <Emoji key={`${part}${index}${code}`} unified={code} size={24} emojiStyle={'apple'} />;
} else } else
if (/https?:\/\/[\S]+/gi.test(part)) { if (/https?:\/\/[\S]+/gi.test(part)) {
return ( return (
@ -59,32 +70,40 @@ const Messages = () => {
</> </>
); );
}); });
// eslint-disable-next-line react/display-name
const MessageBoxWithRef = forwardRef((props, ref) => (
<div ref={ref}>
<MessageBox {...props} />
</div>
));
return ( return (
<div> <div>
<Spin spinning={msgListLoading} tip={'正在读取...'} wrapperClassName='pt-8 '> <Spin spinning={msgListLoading} tip={'正在读取...'} wrapperClassName='pt-8 '>
{activeMessages.map((message, index) => ( {activeMessages.map((message, index) => (
<Dropdown // <Dropdown
key={message.id} // key={message.id}
menu={{ // menu={{
items: [{ label: '回复', key: 'reply', disabled: !['text'].includes(message.whatsapp_msg_type) }], // items: [{ label: '', key: 'reply', disabled: !['text'].includes(message.whatsapp_msg_type) }],
onClick: ({ key, domEvent }) => { // onClick: ({ key, domEvent }) => {
domEvent.stopPropagation(); // domEvent.stopPropagation();
switch (key) { // switch (key) {
case 'reply': // case 'reply':
return setReferenceMsg(message); // return setReferenceMsg(message);
default: // default:
return; // return;
} // }
}, // },
}} // }}
trigger={['contextMenu']}> // trigger={['contextMenu']}>
<MessageBox <MessageBoxWithRef
ref={messageRefs.current[index]}
key={message.id} key={message.id}
{...message} {...message}
position={message.sender === 'me' ? 'right' : 'left'} position={message.sender === 'me' ? 'right' : 'left'}
onReplyClick={() => setReferenceMsg(message)} onReplyClick={() => setReferenceMsg(message)}
onReplyMessageClick={() => scrollToMessage(message.reply.id)}
onOpen={() => handlePreview(message)} onOpen={() => handlePreview(message)}
text={<RenderText str={message?.text || ''} />} text={<RenderText str={message?.text || ''} />}
{...(message.sender === 'me' {...(message.sender === 'me'
@ -98,11 +117,10 @@ const Messages = () => {
replyButton: ['text'].includes(message.whatsapp_msg_type) ? true : false, replyButton: ['text'].includes(message.whatsapp_msg_type) ? true : false,
})} })}
/> />
</Dropdown> // </Dropdown>
))} ))}
<Image src={previewSrc} preview={{ visible: previewVisible, src: previewSrc, onClose: onPreviewClose }} /> <Image src={previewSrc} preview={{ visible: previewVisible, src: previewSrc, onClose: onPreviewClose }} />
<div ref={messagesEndRef}></div>
</Spin> </Spin>
</div> </div>
); );

@ -1,6 +1,6 @@
import useConversationStore from '@/stores/ConversationStore'; import useConversationStore from '@/stores/ConversationStore';
import useAuthStore from '@/stores/AuthStore' import useAuthStore from '@/stores/AuthStore'
import { Flex, Typography, Avatar, Alert, Button, Tooltip } from 'antd'; import { Flex, Typography, Avatar, Alert, Button, Tooltip, Spin } from 'antd';
import { ReloadOutlined, ApiOutlined } from '@ant-design/icons'; import { ReloadOutlined, ApiOutlined } from '@ant-design/icons';
import { LoadingOutlined } from '@ant-design/icons'; import { LoadingOutlined } from '@ant-design/icons';
@ -11,6 +11,7 @@ const MessagesHeader = () => {
const websocketRetrytimes = useConversationStore(state => state.websocketRetrytimes); const websocketRetrytimes = useConversationStore(state => state.websocketRetrytimes);
const currentConversation = useConversationStore(state => state.currentConversation); const currentConversation = useConversationStore(state => state.currentConversation);
const connectWebsocket = useConversationStore(state => state.connectWebsocket); const connectWebsocket = useConversationStore(state => state.connectWebsocket);
const msgListLoading = useConversationStore((state) => state.msgListLoading);
return ( return (
<> <>
@ -43,6 +44,7 @@ const MessagesHeader = () => {
没有WhatsApp号码 没有WhatsApp号码
</Typography.Text> </Typography.Text>
)} )}
<Spin spinning={msgListLoading} />
</Flex> </Flex>
<Flex vertical={true} justify='space-between'> <Flex vertical={true} justify='space-between'>
<Typography.Text>{/* <LocalTimeClock /> <Typography.Text strong>{order?.location} </Typography.Text> */}</Typography.Text> <Typography.Text>{/* <LocalTimeClock /> <Typography.Text strong>{order?.location} </Typography.Text> */}</Typography.Text>

@ -51,3 +51,15 @@
word-wrap: break-word; word-wrap: break-word;
height: 100%; height: 100%;
} }
.chatwindow-wrapper .whatsappme-container .rce-mbox{
background-color: #ccd5ae;
}
.chatwindow-wrapper .whatsappme-container .rce-mbox-right-notch{
fill: #ccd5ae;
}
.chatwindow-wrapper .rce-mbox .rce-mbox-reply {
background-color: rgba(236, 236, 236, 0.7);
}
.chatwindow-wrapper .rce-mbox .epr-emoji-img{
display: inline-block;
}

Loading…
Cancel
Save