chat/app/src/MessageList.js

50 lines
1.8 KiB
JavaScript

import { useEffect, useState, useCallback, memo } from 'react';
import { SERVER_BASE_URL } from './App';
import { Message } from './Message';
export var MessageList = memo(function MessageList({ messages, setMessages, userSecret }) {
var [atBottom, setAtBottom] = useState(true);
var [atTop, setAtTop] = useState(false);
var onScroll = useCallback(event => {
var { scrollTop, scrollHeight, clientHeight } = event.target;
setAtBottom(scrollHeight - (scrollTop + clientHeight) < 32);
setAtTop(scrollTop < 32);
}, [setAtBottom, setAtTop]);
var loadOlderMessages = useCallback(async () => {
var olderMessages = await fetch(SERVER_BASE_URL + "/messages?secret=" + userSecret + "&before=" + messages[0].timestamp).then(res => res.json());
console.debug("loadOlderMessages", olderMessages);
setMessages(messages => [...olderMessages, ...messages]);
// why don't either of these work on ios (webkit) ?
//document.getElementById(messages[0]._id).scrollIntoView();
setTimeout(() => document.getElementById(olderMessages.at(-1)._id).scrollIntoView(), 0);
}, [setMessages, messages, userSecret]);
var scrollToBottom = () => document.getElementById(messages.at(-1)?._id)?.scrollIntoView();
useEffect(() => {
if (atBottom) scrollToBottom();
});
var observer = new ResizeObserver(() => atBottom && scrollToBottom());
useEffect(() => {
console.debug("atTop", atTop);
if (atTop) loadOlderMessages();
}, [atTop, loadOlderMessages]);
useEffect(() => {
console.debug("atBottom", atBottom);
if (atBottom) setMessages(messages => messages.slice(-100));
}, [atBottom, setMessages]);
return <ul className="py-4 w-full flex-1 overflow-auto break-words" onScroll={onScroll} onLoad={e => observer.observe(e.target)}>
{messages.map(message => <Message message={message} key={message._id} />)}
</ul>;
});