import { type UIEventHandler, useCallback, useContext, useEffect, useRef, useState, createContext, } from "react"; const PerformerContext = createContext({ isGenerating: false }); export const useScroll = () => { const { isGenerating } = useContext(PerformerContext); const messagesStartRef = useRef(null); const messagesEndRef = useRef(null); const isAutoScrolling = useRef(false); const [isAtTop, setIsAtTop] = useState(false); const [isAtBottom, setIsAtBottom] = useState(true); const [userScrolled, setUserScrolled] = useState(false); const [isOverflowing, setIsOverflowing] = useState(false); useEffect(() => { setUserScrolled(false); if (!isGenerating && userScrolled) { setUserScrolled(false); } }, [isGenerating]); // useEffect(() => { // if (isGenerating && !userScrolled) { // scrollToBottom(); // } // }, [chatMessages]); const handleScroll: UIEventHandler = useCallback((e) => { const target = e.target as HTMLDivElement; const bottom = Math.round(target.scrollHeight) - Math.round(target.scrollTop) === Math.round(target.clientHeight); setIsAtBottom(bottom); const top = target.scrollTop === 0; setIsAtTop(top); if (!bottom && !isAutoScrolling.current) { setUserScrolled(true); } else { setUserScrolled(false); } const isOverflow = target.scrollHeight > target.clientHeight; setIsOverflowing(isOverflow); }, []); const scrollToTop = useCallback(() => { if (messagesStartRef.current) { messagesStartRef.current.scrollIntoView({ behavior: "instant" }); } }, []); const scrollToBottom = useCallback(() => { isAutoScrolling.current = true; setTimeout(() => { if (messagesEndRef.current) { messagesEndRef.current.scrollIntoView({ behavior: "instant" }); } isAutoScrolling.current = false; }, 0); }, []); return { messagesStartRef, messagesEndRef, isAtTop, isAtBottom, userScrolled, isOverflowing, handleScroll, scrollToTop, scrollToBottom, setIsAtBottom, }; };