| ... | ... | @@ -13,6 +13,7 @@ import { |
| 13 | 13 | type KeyboardEvent, |
| 14 | 14 | useCallback, |
| 15 | 15 | useEffect, |
| 16 | useLayoutEffect, |
| 16 | 17 | useMemo, |
| 17 | 18 | useRef, |
| 18 | 19 | useState, |
| ... | ... | @@ -131,6 +132,7 @@ export default function ChatView() { |
| 131 | 132 | const [expandedWorkGroups, setExpandedWorkGroups] = useState<Record<string, boolean>>({}); |
| 132 | 133 | const [nowTick, setNowTick] = useState(() => Date.now()); |
| 133 | 134 | const [terminalFocusRequestId, setTerminalFocusRequestId] = useState(0); |
| 135 | const messagesScrollRef = useRef<HTMLDivElement>(null); |
| 134 | 136 | const messagesEndRef = useRef<HTMLDivElement>(null); |
| 135 | 137 | const textareaRef = useRef<HTMLTextAreaElement>(null); |
| 136 | 138 | const composerImagesRef = useRef<ComposerImageAttachment[]>([]); |
| ... | ... | @@ -345,6 +347,12 @@ export default function ChatView() { |
| 345 | 347 | // Auto-scroll on new messages |
| 346 | 348 | const messageCount = activeThread?.messages.length ?? 0; |
| 347 | 349 | const workLogCount = workLogEntries.length; |
| 350 | useLayoutEffect(() => { |
| 351 | if (!activeThread?.id) return; |
| 352 | const scrollContainer = messagesScrollRef.current; |
| 353 | if (!scrollContainer) return; |
| 354 | scrollContainer.scrollTop = scrollContainer.scrollHeight; |
| 355 | }, [activeThread?.id]); |
| 348 | 356 | useEffect(() => { |
| 349 | 357 | messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); |
| 350 | 358 | }, [messageCount]); |
| ... | ... | @@ -1014,7 +1022,7 @@ export default function ChatView() { |
| 1014 | 1022 | )} |
| 1015 | 1023 | |
| 1016 | 1024 | {/* Messages */} |
| 1017 | | <div className="min-h-0 flex-1 overflow-y-auto px-5 py-4"> |
| 1025 | <div ref={messagesScrollRef} className="min-h-0 flex-1 overflow-y-auto px-5 py-4"> |
| 1018 | 1026 | {activeThread.messages.length === 0 && !isWorking ? ( |
| 1019 | 1027 | <div className="flex h-full items-center justify-center"> |
| 1020 | 1028 | <p className="text-sm text-muted-foreground/30"> |