diff --git a/client-web/src/modules/chats/presentation/components/ChatView.tsx b/client-web/src/modules/chats/presentation/components/ChatView.tsx index 07f0610..7b22494 100644 --- a/client-web/src/modules/chats/presentation/components/ChatView.tsx +++ b/client-web/src/modules/chats/presentation/components/ChatView.tsx @@ -90,6 +90,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal const pinnedMsg = activeChat ? pinnedMessages[activeChat] : null; const [importStatus, setImportStatus] = useState<{ processed: number, total: number, status: string } | null>(null); + const isAtBottomRef = useRef(false); useEffect(() => { if (!chat?.isImporting || !chat?.importJobId) { @@ -232,7 +233,8 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal // Проверка: сообщения в стейте должны быть от целевого чата if (chatMessages.length > 0 && chatMessages[0].chatId !== chatId) return; - const isAtBottomNow = container.scrollHeight - container.scrollTop - container.clientHeight < 150; + const isAtBottomNow = container.scrollHeight - container.scrollTop - container.clientHeight < 100; + isAtBottomRef.current = isAtBottomNow; if (isAtBottomNow) { localStorage.setItem(`chat_at_bottom_${chatId}`, 'true'); @@ -275,6 +277,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal // ПРИОРИТЕТ 1: Если чат внизу (после второго клика или скролла) if (localStorage.getItem(`chat_at_bottom_${activeChat}`) === 'true') { container.scrollTop = container.scrollHeight; + isAtBottomRef.current = true; return true; } @@ -314,6 +317,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal } container.scrollTop = container.scrollHeight; + isAtBottomRef.current = true; return true; }, [activeChat, chatMessages, user?.id]); @@ -330,7 +334,7 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal setScrollReady(true); isInitializingRef.current = false; } - } else if (localStorage.getItem(`chat_at_bottom_${activeChat}`) === 'true') { + } else if (isAtBottomRef.current) { // Удержание внизу при росте контента container.scrollTop = container.scrollHeight; } @@ -390,6 +394,10 @@ export default function ChatView({ onStartCall, onStartGroupCall }: { onStartCal checkScrollPosition(); const container = messagesContainerRef.current; if (container && activeChat) { + // Synchronous "at bottom" check to prevent ResizeObserver from fighting the user + const isAtBottomNow = container.scrollHeight - container.scrollTop - container.clientHeight < 100; + isAtBottomRef.current = isAtBottomNow; + if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current); scrollTimeoutRef.current = setTimeout(() => saveScrollPosition(), 150);