增强MessageRecord组件以管理消息加载期间的滚动行为。为消息容器和加载状态引入引用,通过在加载更多消息时保留滚动位置来确保平滑的用户体验。
This commit is contained in:
@@ -150,6 +150,7 @@ type GroupRenderItem = {
|
||||
|
||||
const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const messagesContainerRef = useRef<HTMLDivElement>(null);
|
||||
// 右键菜单状态
|
||||
const [contextMenu, setContextMenu] = useState({
|
||||
visible: false,
|
||||
@@ -171,6 +172,8 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
const isLoadingData = useWeChatStore(state => state.isLoadingData);
|
||||
const showCheckbox = useWeChatStore(state => state.showCheckbox);
|
||||
const prevMessagesRef = useRef(currentMessages);
|
||||
const isLoadingMoreRef = useRef(false);
|
||||
const scrollPositionRef = useRef<number>(0);
|
||||
const updateShowCheckbox = useWeChatStore(state => state.updateShowCheckbox);
|
||||
const updateEnterModule = useWeChatStore(state => state.updateEnterModule);
|
||||
const currentCustomer = useCustomerStore(state =>
|
||||
@@ -460,7 +463,10 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
}
|
||||
});
|
||||
|
||||
if (currentMessages.length > prevLength && !hasVideoStateChange) {
|
||||
// 如果正在加载更早的消息,不自动滚动到底部
|
||||
if (isLoadingMoreRef.current && currentMessages.length > prevLength) {
|
||||
// 不滚动,等待加载完成后在另一个 useEffect 中恢复滚动位置
|
||||
} else if (currentMessages.length > prevLength && !hasVideoStateChange) {
|
||||
scrollToBottom();
|
||||
} else if (isLoadingData && !hasVideoStateChange) {
|
||||
scrollToBottom();
|
||||
@@ -470,6 +476,22 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
prevMessagesRef.current = currentMessages;
|
||||
}, [currentMessages, isLoadingData]);
|
||||
|
||||
// 监听加载状态,当加载完成时恢复滚动位置
|
||||
useEffect(() => {
|
||||
if (!messagesLoading && isLoadingMoreRef.current) {
|
||||
// 等待DOM更新后恢复滚动位置
|
||||
requestAnimationFrame(() => {
|
||||
const container = messagesContainerRef.current;
|
||||
if (container) {
|
||||
const scrollHeight = container.scrollHeight;
|
||||
const newScrollTop = scrollHeight - scrollPositionRef.current;
|
||||
container.scrollTop = newScrollTop;
|
||||
}
|
||||
isLoadingMoreRef.current = false;
|
||||
});
|
||||
}
|
||||
}, [messagesLoading]);
|
||||
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
};
|
||||
@@ -762,6 +784,12 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
if (messagesLoading || !currentMessagesHasMore) {
|
||||
return;
|
||||
}
|
||||
// 保存当前滚动位置(距离底部的距离)
|
||||
const container = messagesContainerRef.current;
|
||||
if (container) {
|
||||
scrollPositionRef.current = container.scrollHeight - container.scrollTop;
|
||||
isLoadingMoreRef.current = true;
|
||||
}
|
||||
loadChatMessages(false);
|
||||
};
|
||||
|
||||
@@ -840,7 +868,7 @@ const MessageRecord: React.FC<MessageRecordProps> = ({ contract }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.messagesContainer}>
|
||||
<div ref={messagesContainerRef} className={styles.messagesContainer}>
|
||||
<div
|
||||
className={styles.loadMore}
|
||||
onClick={() => loadMoreMessages()}
|
||||
|
||||
Reference in New Issue
Block a user