fix: chat session scroll to bottom error even when scrolled up

This commit is contained in:
Haileyesus
2026-02-11 17:12:41 +03:00
parent 8bc3c17793
commit 9524313363

View File

@@ -59,7 +59,6 @@ export function useChatSessionState({
const [sessionMessages, setSessionMessages] = useState<any[]>([]); const [sessionMessages, setSessionMessages] = useState<any[]>([]);
const [isLoadingSessionMessages, setIsLoadingSessionMessages] = useState(false); const [isLoadingSessionMessages, setIsLoadingSessionMessages] = useState(false);
const [isLoadingMoreMessages, setIsLoadingMoreMessages] = useState(false); const [isLoadingMoreMessages, setIsLoadingMoreMessages] = useState(false);
const [messagesOffset, setMessagesOffset] = useState(0);
const [hasMoreMessages, setHasMoreMessages] = useState(false); const [hasMoreMessages, setHasMoreMessages] = useState(false);
const [totalMessages, setTotalMessages] = useState(0); const [totalMessages, setTotalMessages] = useState(0);
const [isSystemSessionChange, setIsSystemSessionChange] = useState(false); const [isSystemSessionChange, setIsSystemSessionChange] = useState(false);
@@ -74,6 +73,8 @@ export function useChatSessionState({
const isLoadingMoreRef = useRef(false); const isLoadingMoreRef = useRef(false);
const topLoadLockRef = useRef(false); const topLoadLockRef = useRef(false);
const pendingScrollRestoreRef = useRef<ScrollRestoreState | null>(null); const pendingScrollRestoreRef = useRef<ScrollRestoreState | null>(null);
const pendingInitialScrollRef = useRef(true);
const messagesOffsetRef = useRef(0);
const scrollPositionRef = useRef({ height: 0, top: 0 }); const scrollPositionRef = useRef({ height: 0, top: 0 });
const createDiff = useMemo<DiffCalculator>(() => createCachedDiffCalculator(), []); const createDiff = useMemo<DiffCalculator>(() => createCachedDiffCalculator(), []);
@@ -92,7 +93,7 @@ export function useChatSessionState({
} }
try { try {
const currentOffset = loadMore ? messagesOffset : 0; const currentOffset = loadMore ? messagesOffsetRef.current : 0;
const response = await (api.sessionMessages as any)( const response = await (api.sessionMessages as any)(
projectName, projectName,
sessionId, sessionId,
@@ -110,15 +111,17 @@ export function useChatSessionState({
} }
if (data.hasMore !== undefined) { if (data.hasMore !== undefined) {
const loadedCount = data.messages?.length || 0;
setHasMoreMessages(Boolean(data.hasMore)); setHasMoreMessages(Boolean(data.hasMore));
setTotalMessages(Number(data.total || 0)); setTotalMessages(Number(data.total || 0));
setMessagesOffset(currentOffset + (data.messages?.length || 0)); messagesOffsetRef.current = currentOffset + loadedCount;
return data.messages || []; return data.messages || [];
} }
const messages = data.messages || []; const messages = data.messages || [];
setHasMoreMessages(false); setHasMoreMessages(false);
setTotalMessages(messages.length); setTotalMessages(messages.length);
messagesOffsetRef.current = messages.length;
return messages; return messages;
} catch (error) { } catch (error) {
console.error('Error loading session messages:', error); console.error('Error loading session messages:', error);
@@ -131,7 +134,7 @@ export function useChatSessionState({
} }
} }
}, },
[messagesOffset], [],
); );
const loadCursorSessionMessages = useCallback(async (projectPath: string, sessionId: string) => { const loadCursorSessionMessages = useCallback(async (projectPath: string, sessionId: string) => {
@@ -258,6 +261,27 @@ export function useChatSessionState({
pendingScrollRestoreRef.current = null; pendingScrollRestoreRef.current = null;
}, [chatMessages.length]); }, [chatMessages.length]);
useEffect(() => {
pendingInitialScrollRef.current = true;
setIsUserScrolledUp(false);
}, [selectedProject?.name, selectedSession?.id]);
useEffect(() => {
if (!pendingInitialScrollRef.current || !scrollContainerRef.current || isLoadingSessionMessages) {
return;
}
if (chatMessages.length === 0) {
pendingInitialScrollRef.current = false;
return;
}
pendingInitialScrollRef.current = false;
setTimeout(() => {
scrollToBottom();
}, 200);
}, [chatMessages.length, isLoadingSessionMessages, scrollToBottom]);
useEffect(() => { useEffect(() => {
const loadMessages = async () => { const loadMessages = async () => {
if (selectedSession && selectedProject) { if (selectedSession && selectedProject) {
@@ -275,7 +299,7 @@ export function useChatSessionState({
setCanAbortSession(false); setCanAbortSession(false);
} }
setMessagesOffset(0); messagesOffsetRef.current = 0;
setHasMoreMessages(false); setHasMoreMessages(false);
setTotalMessages(0); setTotalMessages(0);
setTokenBudget(null); setTokenBudget(null);
@@ -289,7 +313,7 @@ export function useChatSessionState({
}); });
} }
} else if (currentSessionId === null) { } else if (currentSessionId === null) {
setMessagesOffset(0); messagesOffsetRef.current = 0;
setHasMoreMessages(false); setHasMoreMessages(false);
setTotalMessages(0); setTotalMessages(0);
@@ -342,7 +366,7 @@ export function useChatSessionState({
setCurrentSessionId(null); setCurrentSessionId(null);
sessionStorage.removeItem('cursorSessionId'); sessionStorage.removeItem('cursorSessionId');
setMessagesOffset(0); messagesOffsetRef.current = 0;
setHasMoreMessages(false); setHasMoreMessages(false);
setTotalMessages(0); setTotalMessages(0);
setTokenBudget(null); setTokenBudget(null);
@@ -482,6 +506,10 @@ export function useChatSessionState({
return; return;
} }
if (isLoadingMoreRef.current || isLoadingMoreMessages || pendingScrollRestoreRef.current) {
return;
}
if (autoScrollToBottom) { if (autoScrollToBottom) {
if (!isUserScrolledUp) { if (!isUserScrolledUp) {
setTimeout(() => scrollToBottom(), 50); setTimeout(() => scrollToBottom(), 50);
@@ -498,18 +526,7 @@ export function useChatSessionState({
if (heightDiff > 0 && prevTop > 0) { if (heightDiff > 0 && prevTop > 0) {
container.scrollTop = prevTop + heightDiff; container.scrollTop = prevTop + heightDiff;
} }
}, [autoScrollToBottom, chatMessages.length, isUserScrolledUp, scrollToBottom]); }, [autoScrollToBottom, chatMessages.length, isLoadingMoreMessages, isUserScrolledUp, scrollToBottom]);
useEffect(() => {
if (!scrollContainerRef.current || chatMessages.length === 0 || isLoadingSessionRef.current) {
return;
}
setIsUserScrolledUp(false);
setTimeout(() => {
scrollToBottom();
}, 200);
}, [chatMessages.length, scrollToBottom, selectedProject?.name, selectedSession?.id]);
useEffect(() => { useEffect(() => {
const container = scrollContainerRef.current; const container = scrollContainerRef.current;