按钮: 滚动到底部

dev/chat
Lei OT 2 years ago
parent 39bf2e717b
commit 4852b0067d

@ -50,10 +50,8 @@ const ChatWindow = () => {
{/* <Button type='text' icon={<ReloadOutlined />} onClick={() => setCollapsedRight(!collapsedRight)} className='' title='最新消息记录' /> */} {/* <Button type='text' icon={<ReloadOutlined />} onClick={() => setCollapsedRight(!collapsedRight)} className='' title='最新消息记录' /> */}
<Button type='text' icon={collapsedRight ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />} onClick={() => setCollapsedRight(!collapsedRight)} className=' rounded-none rounded-r' /> <Button type='text' icon={collapsedRight ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />} onClick={() => setCollapsedRight(!collapsedRight)} className=' rounded-none rounded-r' />
</Header> </Header>
<Content className="flex-grow bg-whatsapp-bg" > <Content className="flex-grow bg-whatsapp-bg relative" >
<div className='h-full overflow-y-auto'> <Messages />
<Messages />
</div>
</Content> </Content>
<Footer className='ant-layout-sider-light p-0'> <Footer className='ant-layout-sider-light p-0'>
<InputComposer /> <InputComposer />

@ -1,5 +1,5 @@
import { useEffect, useState, useRef, useMemo, memo, createRef, forwardRef } from 'react'; import { useEffect, useState, useRef, useMemo, memo, createRef, forwardRef } from 'react';
import { Image, Spin, Dropdown, Button } from 'antd'; import { Image, Spin, Dropdown, Button, Affix } 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';
import useConversationStore from '@/stores/ConversationStore'; import useConversationStore from '@/stores/ConversationStore';
@ -7,7 +7,7 @@ import { useShallow } from 'zustand/react/shallow';
import { Emoji } from 'emoji-picker-react'; import { Emoji } from 'emoji-picker-react';
import { olog } from '@/utils/utils'; import { olog } from '@/utils/utils';
const Messages = () => { const Messages = ({ ...props }) => {
// 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));
@ -17,9 +17,9 @@ const Messages = () => {
const scrollToMessage = (id, index) => { const scrollToMessage = (id, index) => {
const _i = index || activeMessages.findIndex((msg) => msg.id === id); const _i = index || activeMessages.findIndex((msg) => msg.id === id);
if (_i >= 0) { if (_i >= 0) {
messageRefs.current[_i].current.scrollIntoView({ behavior: "smooth", block: "center" }); messageRefs.current[_i].current.scrollIntoView({ behavior: 'smooth', block: 'center' });
} }
} };
useEffect(() => { useEffect(() => {
if (activeMessages.length > 0) { if (activeMessages.length > 0) {
@ -30,6 +30,12 @@ const Messages = () => {
const messageRefs = useRef([]); const messageRefs = useRef([]);
messageRefs.current = activeMessages.map((_, i) => messageRefs.current[i] ?? createRef()); messageRefs.current = activeMessages.map((_, i) => messageRefs.current[i] ?? createRef());
const referance = useRef(null);
const toBottom = (e) => {
if (!referance) return;
referance.current.scrollTop = referance.current.scrollHeight;
};
const [previewVisible, setPreviewVisible] = useState(false); const [previewVisible, setPreviewVisible] = useState(false);
const [previewSrc, setPreviewSrc] = useState(); const [previewSrc, setPreviewSrc] = useState();
const onPreviewClose = () => { const onPreviewClose = () => {
@ -44,7 +50,7 @@ const Messages = () => {
return false; return false;
case 'file': case 'file':
window.open(msg.data.uri, "_blank", "noopener,noreferrer") window.open(msg.data.uri, '_blank', 'noopener,noreferrer');
return false; return false;
default: default:
@ -52,8 +58,8 @@ const Messages = () => {
} }
}; };
const RenderText = memo(function renderText({str}) { const RenderText = memo(function renderText({ str }) {
const parts = str.split(/(https?:\/\/[^\s]+|\p{Emoji_Presentation})/gmu).filter(s => s !== ''); const parts = str.split(/(https?:\/\/[^\s]+|\p{Emoji_Presentation})/gmu).filter((s) => s !== '');
// const parts = str.split(/(https?:\/\/[^\s]+|\p{Emoji}\uFE0F?|\b\d+\b)/gu); // const parts = str.split(/(https?:\/\/[^\s]+|\p{Emoji}\uFE0F?|\b\d+\b)/gu);
return ( return (
<> <>
@ -62,8 +68,7 @@ const Messages = () => {
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={'apple'} />; 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 (
<a href={part} target='_blank' key={`${part}${index}`} rel='noreferrer'> <a href={part} target='_blank' key={`${part}${index}`} rel='noreferrer'>
{part} {part}
@ -86,25 +91,26 @@ const Messages = () => {
)); ));
return ( return (
<div> <div className='relative h-full overflow-y-auto flex'>
<Spin spinning={msgListLoading} tip={'正在读取...'} wrapperClassName='pt-8 '> <div className='relative overflow-y-auto block flex-1' ref={referance}>
{activeMessages.map((message, index) => ( <Spin spinning={msgListLoading} tip={'正在读取...'} wrapperClassName='pt-8 relative'>
// <Dropdown {activeMessages.map((message, index) => (
// key={message.id} // <Dropdown
// menu={{ // key={message.id}
// items: [{ label: '', key: 'reply', disabled: !['text'].includes(message.whatsapp_msg_type) }], // menu={{
// onClick: ({ key, domEvent }) => { // items: [{ label: '', key: 'reply', disabled: !['text'].includes(message.whatsapp_msg_type) }],
// domEvent.stopPropagation(); // onClick: ({ key, domEvent }) => {
// switch (key) { // domEvent.stopPropagation();
// case 'reply': // switch (key) {
// return setReferenceMsg(message); // case 'reply':
// return setReferenceMsg(message);
// default: // default:
// return; // return;
// } // }
// }, // },
// }} // }}
// trigger={['contextMenu']}> // trigger={['contextMenu']}>
<MessageBoxWithRef <MessageBoxWithRef
ref={messageRefs.current[index]} ref={messageRefs.current[index]}
key={message.id} key={message.id}
@ -119,20 +125,20 @@ const Messages = () => {
? { ? {
styles: { backgroundColor: '#ccd4ae' }, styles: { backgroundColor: '#ccd4ae' },
notchStyle: { fill: '#ccd4ae' }, notchStyle: { fill: '#ccd4ae' },
replyButton: ['text'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false, replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) && message.status !== 'failed' ? true : false,
className: 'whatsappme-container whitespace-pre-wrap', className: 'whatsappme-container whitespace-pre-wrap',
} }
: { : {
replyButton: ['text'].includes(message.whatsapp_msg_type) ? true : false, replyButton: ['text', 'document', 'image'].includes(message.whatsapp_msg_type) ? true : false,
className: 'whitespace-pre-wrap', className: 'whitespace-pre-wrap',
})} })}
/> />
// </Dropdown> // </Dropdown>
))} ))}
</Spin>
</Spin> <Image src={null} preview={{ visible: previewVisible, src: previewSrc, onClose: onPreviewClose }} />
</div>
<Image src={null} preview={{ visible: previewVisible, src: previewSrc, onClose: onPreviewClose }} /> <Button onClick={toBottom} shape={'circle'} className=' absolute bottom-1 right-4' icon={<DownOutlined />} />
</div> </div>
); );
}; };

Loading…
Cancel
Save