From 8bd0e53bfe57fbfde19bc7b07dec006acdaa665e Mon Sep 17 00:00:00 2001 From: syc0123 Date: Tue, 31 Mar 2026 16:25:51 +0900 Subject: [PATCH] =?UTF-8?q?[RAPID-fix]=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20Res?= =?UTF-8?q?izeObserver=20=EC=B6=94=EA=B0=80:=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EB=A1=9C=EB=93=9C=20=ED=9B=84=20=EB=86=92=EC=9D=B4=20?= =?UTF-8?q?=EB=B3=80=ED=99=94=20=EA=B0=90=EC=A7=80=ED=95=B4=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=ED=95=98=EB=8B=A8=20=EC=8A=A4=ED=81=AC=EB=A1=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/components/messenger/ChatPanel.tsx | 29 ++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/frontend/components/messenger/ChatPanel.tsx b/frontend/components/messenger/ChatPanel.tsx index 8b7543ec..b223ba3a 100644 --- a/frontend/components/messenger/ChatPanel.tsx +++ b/frontend/components/messenger/ChatPanel.tsx @@ -37,23 +37,40 @@ export function ChatPanel({ room }: ChatPanelProps) { const lastMessageId = messages?.[messages.length - 1]?.id; // Scroll to bottom: sentinel scrollIntoView before paint (no visible jump) + // Scroll to bottom on room open / new message useLayoutEffect(() => { if (isOpen) bottomRef.current?.scrollIntoView(); }, [selectedRoomId, lastMessageId, isOpen]); - // Second pass for async image loads + // ResizeObserver: re-scroll whenever content height changes (images loading, etc.) + const shouldAutoScrollRef = useRef(true); useEffect(() => { - if (!isOpen) return; - const t = setTimeout(() => { bottomRef.current?.scrollIntoView(); }, 600); - return () => clearTimeout(t); - }, [lastMessageId, selectedRoomId, isOpen]); + const el = scrollRef.current; + if (!el) return; + const inner = el.firstElementChild as HTMLElement | null; + if (!inner) return; + const ro = new ResizeObserver(() => { + if (shouldAutoScrollRef.current) { + bottomRef.current?.scrollIntoView(); + } + }); + ro.observe(inner); + return () => ro.disconnect(); + }, [selectedRoomId]); + + // Track whether user has scrolled up (disable auto-scroll while reading old messages) + useEffect(() => { + shouldAutoScrollRef.current = true; + }, [selectedRoomId, lastMessageId]); // Re-attach scroll listener whenever room changes (scrollRef mounts after room is set) useEffect(() => { const el = scrollRef.current; if (!el) return; const onScroll = () => { - setIsAtBottom(el.scrollHeight - el.scrollTop - el.clientHeight < 60); + const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 60; + setIsAtBottom(atBottom); + shouldAutoScrollRef.current = atBottom; }; el.addEventListener("scroll", onScroll); return () => el.removeEventListener("scroll", onScroll);