From 22e6470ab8e996ba806e7dc69f2da3260ed88bc5 Mon Sep 17 00:00:00 2001 From: cha0s Date: Sat, 25 Jul 2020 05:17:04 -0500 Subject: [PATCH] fix: scrolling --- src/client/chat--messages.jsx | 46 ++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/client/chat--messages.jsx b/src/client/chat--messages.jsx index 7c92efc..0ef8d3b 100644 --- a/src/client/chat--messages.jsx +++ b/src/client/chat--messages.jsx @@ -1,6 +1,11 @@ import './chat--messages.scss'; -import React, {useLayoutEffect, useRef} from 'react'; +import React, { + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react'; import {useSelector} from 'react-redux'; import {channelMessagesSelector} from '~/common/state/chat'; @@ -16,23 +21,35 @@ export default function ChatMessages() { const channel = useChannel(); const $messages = useRef(null); const {current} = $messages; - const isAtTheBottom = !current - ? true - : 0 === current.scrollTop || ( - current.scrollHeight - === current.scrollTop - + ['margin-top', 'margin-bottom'].reduce((r, property) => ( - r + parseInt(window.getComputedStyle(current).getPropertyValue(property), 10) - ), current.offsetHeight) - ); - const heightWatch = current && current.scrollHeight; + const [, setIsAtBottom] = useState(true); + const [outerHeight, setOuterHeight] = useState(0); + const [scrollTop, setScrollTop] = useState(0); + const [scrollHeight, setScrollHeight] = useState(Infinity); const messages = useSelector((state) => channelMessagesSelector(state, channel)); const messageCount = messages && messages.length; + useEffect(() => { + const onResize = () => { + setOuterHeight( + !current + ? 0 + : ['margin-top', 'margin-bottom'].reduce((r, property) => ( + r + parseInt(window.getComputedStyle(current).getPropertyValue(property), 10) + ), current.offsetHeight), + ); + setScrollHeight(!current ? 0 : current.scrollHeight); + }; + window.addEventListener('resize', onResize); + onResize(); + }); useLayoutEffect(() => { - if (isAtTheBottom) { - current?.scrollTo(0, !current ? 0 : current.scrollHeight); + const isAtBottom = !current + ? true + : 0 === scrollTop || scrollTop + outerHeight >= scrollHeight; + setIsAtBottom(isAtBottom); + if (isAtBottom) { + current?.scrollTo(0, scrollHeight); } - }, [current, heightWatch, messageCount, isAtTheBottom]); + }, [current, messageCount, outerHeight, scrollHeight, scrollTop]); if (!channel) { return null; } @@ -42,6 +59,7 @@ export default function ChatMessages() {
setScrollTop(Math.round(scrollTop))} ref={$messages} > {messages && messages.map((message) => {