Fix auto-scroll to only trigger during streaming (#1593)
Previously, the chat auto-scrolled whenever messages changed, even when not streaming. This caused unwanted scrolling when switching chats or loading messages from the database. Now auto-scroll only triggers when: - Messages are actively streaming (isStreaming is true) - User hasn't manually scrolled away - User is near the bottom of the chat Changes: - Added isStreamingByIdAtom to track streaming state - Modified auto-scroll useEffect to check isStreaming before scrolling - Preserved streamCount effect for initial scroll on stream start 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Fixes chat auto-scroll so it only runs during active streaming, preventing jumps when switching chats or loading message history. - **Bug Fixes** - Added isStreamingByIdAtom and gated the auto-scroll effect by per-chat streaming state (updated effect deps). - Preserved the initial scroll on stream start via streamCount. <!-- End of auto-generated description by cubic. --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Limits chat auto-scroll to when a conversation is actively streaming and the user is near the bottom. > > - **Frontend** > - **Chat auto-scroll behavior**: Only auto-scrolls during active streaming. > - Adds `isStreamingByIdAtom` and reads per-chat `isStreaming` state. > - Updates auto-scroll `useEffect` to require `isStreaming` and adds it to dependencies. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 6580601cd974c2c01ddffdef78ed0ddbb2b2fa8d. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { useAtomValue, useSetAtom } from "jotai";
|
|||||||
import {
|
import {
|
||||||
chatMessagesByIdAtom,
|
chatMessagesByIdAtom,
|
||||||
chatStreamCountByIdAtom,
|
chatStreamCountByIdAtom,
|
||||||
|
isStreamingByIdAtom,
|
||||||
} from "../atoms/chatAtoms";
|
} from "../atoms/chatAtoms";
|
||||||
import { IpcClient } from "@/ipc/ipc_client";
|
import { IpcClient } from "@/ipc/ipc_client";
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ export function ChatPanel({
|
|||||||
const [isVersionPaneOpen, setIsVersionPaneOpen] = useState(false);
|
const [isVersionPaneOpen, setIsVersionPaneOpen] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const streamCountById = useAtomValue(chatStreamCountByIdAtom);
|
const streamCountById = useAtomValue(chatStreamCountByIdAtom);
|
||||||
|
const isStreamingById = useAtomValue(isStreamingByIdAtom);
|
||||||
// Reference to store the processed prompt so we don't submit it twice
|
// Reference to store the processed prompt so we don't submit it twice
|
||||||
|
|
||||||
const messagesEndRef = useRef<HTMLDivElement | null>(null);
|
const messagesEndRef = useRef<HTMLDivElement | null>(null);
|
||||||
@@ -131,10 +133,13 @@ export function ChatPanel({
|
|||||||
}, [fetchChatMessages]);
|
}, [fetchChatMessages]);
|
||||||
|
|
||||||
const messages = chatId ? (messagesById.get(chatId) ?? []) : [];
|
const messages = chatId ? (messagesById.get(chatId) ?? []) : [];
|
||||||
// Auto-scroll effect when messages change
|
const isStreaming = chatId ? (isStreamingById.get(chatId) ?? false) : false;
|
||||||
|
|
||||||
|
// Auto-scroll effect when messages change during streaming
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
!isUserScrolling &&
|
!isUserScrolling &&
|
||||||
|
isStreaming &&
|
||||||
messagesContainerRef.current &&
|
messagesContainerRef.current &&
|
||||||
messages.length > 0
|
messages.length > 0
|
||||||
) {
|
) {
|
||||||
@@ -145,7 +150,7 @@ export function ChatPanel({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [messages, isUserScrolling]);
|
}, [messages, isUserScrolling, isStreaming]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full">
|
<div className="flex flex-col h-full">
|
||||||
|
|||||||
Reference in New Issue
Block a user