|
1 | | -import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react"; |
| 1 | +import { |
| 2 | + memo, |
| 3 | + useCallback, |
| 4 | + useEffect, |
| 5 | + useLayoutEffect, |
| 6 | + useMemo, |
| 7 | + useRef, |
| 8 | + useState, |
| 9 | +} from "react"; |
2 | 10 | import { createPortal } from "react-dom"; |
3 | 11 | import { convertFileSrc } from "@tauri-apps/api/core"; |
4 | 12 | import Brain from "lucide-react/dist/esm/icons/brain"; |
@@ -1161,19 +1169,20 @@ export const Messages = memo(function Messages({ |
1161 | 1169 | }; |
1162 | 1170 |
|
1163 | 1171 | const requestAutoScroll = useCallback(() => { |
1164 | | - if (!bottomRef.current) { |
1165 | | - return; |
1166 | | - } |
1167 | 1172 | const container = containerRef.current; |
1168 | 1173 | const shouldScroll = |
1169 | 1174 | autoScrollRef.current || (container ? isNearBottom(container) : true); |
1170 | 1175 | if (!shouldScroll) { |
1171 | 1176 | return; |
1172 | 1177 | } |
1173 | | - bottomRef.current.scrollIntoView({ behavior: "smooth", block: "end" }); |
| 1178 | + if (container) { |
| 1179 | + container.scrollTop = container.scrollHeight; |
| 1180 | + return; |
| 1181 | + } |
| 1182 | + bottomRef.current?.scrollIntoView({ block: "end" }); |
1174 | 1183 | }, [isNearBottom]); |
1175 | 1184 |
|
1176 | | - useEffect(() => { |
| 1185 | + useLayoutEffect(() => { |
1177 | 1186 | autoScrollRef.current = true; |
1178 | 1187 | }, [threadId]); |
1179 | 1188 | const toggleExpanded = useCallback((id: string) => { |
@@ -1289,34 +1298,20 @@ export const Messages = memo(function Messages({ |
1289 | 1298 | [], |
1290 | 1299 | ); |
1291 | 1300 |
|
1292 | | - useEffect(() => { |
1293 | | - if (!bottomRef.current) { |
1294 | | - return undefined; |
1295 | | - } |
| 1301 | + useLayoutEffect(() => { |
1296 | 1302 | const container = containerRef.current; |
1297 | 1303 | const shouldScroll = |
1298 | 1304 | autoScrollRef.current || |
1299 | 1305 | (container ? isNearBottom(container) : true); |
1300 | 1306 | if (!shouldScroll) { |
1301 | | - return undefined; |
| 1307 | + return; |
1302 | 1308 | } |
1303 | | - let raf1 = 0; |
1304 | | - let raf2 = 0; |
1305 | | - const target = bottomRef.current; |
1306 | | - raf1 = window.requestAnimationFrame(() => { |
1307 | | - raf2 = window.requestAnimationFrame(() => { |
1308 | | - target.scrollIntoView({ behavior: "smooth", block: "end" }); |
1309 | | - }); |
1310 | | - }); |
1311 | | - return () => { |
1312 | | - if (raf1) { |
1313 | | - window.cancelAnimationFrame(raf1); |
1314 | | - } |
1315 | | - if (raf2) { |
1316 | | - window.cancelAnimationFrame(raf2); |
1317 | | - } |
1318 | | - }; |
1319 | | - }, [scrollKey, isThinking, isNearBottom]); |
| 1309 | + if (container) { |
| 1310 | + container.scrollTop = container.scrollHeight; |
| 1311 | + return; |
| 1312 | + } |
| 1313 | + bottomRef.current?.scrollIntoView({ block: "end" }); |
| 1314 | + }, [scrollKey, isThinking, isNearBottom, threadId]); |
1320 | 1315 |
|
1321 | 1316 | const groupedItems = useMemo(() => buildToolGroups(visibleItems), [visibleItems]); |
1322 | 1317 |
|
|
0 commit comments