diff --git a/packages/call/todo.md b/packages/call/todo.md index 61d70ed..4db4db0 100644 --- a/packages/call/todo.md +++ b/packages/call/todo.md @@ -11,4 +11,3 @@ - Desktop-App screenshares - Context menus - Popout Window -- If micGated=true & isSpeaking=false for 5 seconds show banner with mic detection diff --git a/packages/chat/src/screen.tsx b/packages/chat/src/screen.tsx index 30344a5..f72580d 100644 --- a/packages/chat/src/screen.tsx +++ b/packages/chat/src/screen.tsx @@ -8,6 +8,7 @@ import Message from "./components/message"; import { PAGE_SIZE } from "./values"; import { useIsMobile } from "@tensamin/ui"; +import { Loader2 } from "lucide-react"; function getDistanceFromBottom(element: HTMLDivElement) { return element.scrollHeight - (element.scrollTop + element.clientHeight); @@ -360,9 +361,38 @@ export default function Screen() { return; } - scrollRef.current.scrollTop = scrollRef.current.scrollHeight; - isAtBottomRef.current = true; - setHasScrolledToBottomInitially(true); + let rafId: number; + let stableFrames = 0; + let lastScrollHeight = 0; + + const settleToBottom = () => { + if (!scrollRef.current || hasScrolledToBottomInitially) { + return; + } + + scrollRef.current.scrollTop = scrollRef.current.scrollHeight; + const currentScrollHeight = scrollRef.current.scrollHeight; + + if (currentScrollHeight === lastScrollHeight) { + stableFrames++; + } else { + stableFrames = 0; + lastScrollHeight = currentScrollHeight; + } + + if (stableFrames >= 2) { + isAtBottomRef.current = true; + setHasScrolledToBottomInitially(true); + } else { + rafId = requestAnimationFrame(settleToBottom); + } + }; + + settleToBottom(); + + return () => { + cancelAnimationFrame(rafId); + }; }, [hasScrolledToBottomInitially, virtualRowCount]); React.useLayoutEffect(() => { @@ -442,6 +472,19 @@ export default function Screen() { }} onScroll={handleContainerScroll} > + {messagesQuery.isPending && ( +
+