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