fix: scrolling

This commit is contained in:
cha0s 2020-07-25 05:17:04 -05:00
parent d236f23b38
commit 22e6470ab8

View File

@ -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() {
<div className="chat--messagesSmoosh" />
<div
className="chat--messagesList"
onScroll={({target: {scrollTop}}) => setScrollTop(Math.round(scrollTop))}
ref={$messages}
>
{messages && messages.map((message) => {