diff --git a/app/src/ui/tutor/TutorTab.tsx b/app/src/ui/tutor/TutorTab.tsx index 78dd3f7..234ab9d 100644 --- a/app/src/ui/tutor/TutorTab.tsx +++ b/app/src/ui/tutor/TutorTab.tsx @@ -206,8 +206,9 @@ export function TutorTab() { const log = useRef(null); /** The log follows new text while this is set; see the follow effect. */ const stick = useRef(true); - /** Where the log was last scrolled to; see onLogScroll. */ + /** Where the log was last scrolled to, and how tall it was; see onLogScroll. */ const lastTop = useRef(0); + const lastHeights = useRef({ content: 0, box: 0 }); const menuButton = useRef(null); /* ── the keyboard's field, and answer mode ── */ @@ -716,15 +717,24 @@ export function TutorTab() { stream has added more than STICK_PX below it — judged by distance alone, that read as the learner scrolling away, and the log stopped following mid-reply. Growing content never moves scrollTop up; a - finger does. */ + finger does. + + And a finger does not change the log's height. Leaving answer mode + brings back the earlier messages, the composer and the nav in one + layout, which reset scrollTop to 0 — an upward jump that read as + scrolling away, just as the answer was sent. A move made while the + content or the box changed size is layout, not the learner. */ const onLogScroll = useCallback(() => { const el = log.current; if (!el || !active) return; const top = el.scrollTop; + const resized = + el.scrollHeight !== lastHeights.current.content || el.clientHeight !== lastHeights.current.box; if (el.scrollHeight - top - el.clientHeight < STICK_PX) stick.current = true; - else if (top < lastTop.current - 1) stick.current = false; + else if (top < lastTop.current - 1 && !resized) stick.current = false; lastTop.current = top; + lastHeights.current = { content: el.scrollHeight, box: el.clientHeight }; }, [active]); const follow = useCallback(() => { @@ -732,6 +742,7 @@ export function TutorTab() { if (!el || !stick.current) return; el.scrollTop = el.scrollHeight; lastTop.current = el.scrollTop; + lastHeights.current = { content: el.scrollHeight, box: el.clientHeight }; }, []); useEffect(() => {