feat: add active turn anchor management for improved scroll position handling

This commit is contained in:
Bohdan Triapitsyn
2025-12-29 12:12:52 +02:00
parent 66428cbded
commit 9b4283d618
7 changed files with 127 additions and 16 deletions
@@ -22,6 +22,8 @@ export const ChatContainer: React.FC = () => {
loadMessages,
loadMoreMessages,
updateViewportAnchor,
updateActiveTurnAnchor,
getActiveTurnAnchor,
sessionMemoryState,
openNewSessionDraft,
isSyncing,
@@ -69,6 +71,8 @@ export const ChatContainer: React.FC = () => {
streamingMessageId,
sessionMemoryState,
updateViewportAnchor,
updateActiveTurnAnchor,
getActiveTurnAnchor,
isSyncing,
isMobile,
messageStreamStates,
@@ -96,11 +100,14 @@ export const ChatContainer: React.FC = () => {
}
lastScrolledSessionRef.current = currentSessionId;
const container = scrollRef.current;
if (container) {
container.scrollTop = container.scrollHeight - container.clientHeight;
// Only scroll to bottom if there's no active anchor (anchor handles its own scroll)
if (!hasActiveAnchor) {
const container = scrollRef.current;
if (container) {
container.scrollTop = container.scrollHeight - container.clientHeight;
}
}
}, [currentSessionId, scrollRef]);
}, [currentSessionId, scrollRef, hasActiveAnchor]);
const handleLoadOlder = React.useCallback(async () => {
if (!currentSessionId || isLoadingOlder) {
@@ -495,7 +495,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
// Normal mode: Enter sends, Ctrl+Enter queues
// Note: Queueing only works when there's an existing session (currentSessionId)
// For new sessions (draft), always send immediately
const canQueue = hasContent && currentSessionId;
const canQueue = hasContent && currentSessionId && sessionPhase !== 'idle';
if (queueModeEnabled) {
if (isCtrlEnter || !canQueue) {