jump to bottom of list when the DOM observes that a new message node has been added (#369)

This commit is contained in:
gingervitis 2020-11-17 16:59:27 -08:00 committed by GitHub
parent 31e0382a87
commit f8d94c2dc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -33,12 +33,17 @@ export default class Chat extends Component {
this.submitChat = this.submitChat.bind(this);
this.scrollToBottom = this.scrollToBottom.bind(this);
this.handleWindowResize = debounce(this.handleWindowResize.bind(this), 500);
this.messageListCallback = this.messageListCallback.bind(this);
}
componentDidMount() {
this.setupWebSocketCallbacks();
this.getChatHistory();
window.addEventListener('resize', this.handleWindowResize);
this.messageListObserver = new MutationObserver(this.messageListCallback);
this.messageListObserver.observe(this.scrollableMessagesContainer.current, { childList: true });
}
componentDidUpdate(prevProps, prevState) {
@ -52,15 +57,15 @@ export default class Chat extends Component {
if (prevName !== username) {
this.sendUsernameChange(prevName, username);
}
// scroll to bottom of messages list when new ones come in
if (messages.length > prevMessages.length) {
if (!prevMessages.length || this.checkShouldScroll()) {
this.scrollToBottom();
}
this.newMessagesReceived = true;
}
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleWindowResize);
this.messageListObserver.disconnect();
}
setupWebSocketCallbacks() {
@ -139,7 +144,6 @@ export default class Chat extends Component {
});
}
submitChat(content) {
if (!content) {
return;
@ -177,14 +181,28 @@ export default class Chat extends Component {
checkShouldScroll() {
const { scrollTop, scrollHeight, clientHeight } = this.scrollableMessagesContainer.current;
const fullyScrolled = scrollHeight - clientHeight;
return scrollHeight >= clientHeight && fullyScrolled - scrollTop < MESSAGE_JUMPTOBOTTOM_BUFFER;
const shoudlScroll = scrollHeight >= clientHeight && fullyScrolled - scrollTop < MESSAGE_JUMPTOBOTTOM_BUFFER;
return shoudlScroll;
}
handleWindowResize() {
this.scrollToBottom();
}
// if the messages list grows in number of child message nodes due to new messages received, scroll to bottom.
messageListCallback(mutations) {
const numMutations = mutations.length;
if (numMutations) {
const item = mutations[numMutations - 1];
if (item.type === 'childList' && item.addedNodes.length) {
if (this.newMessagesReceived || this.checkShouldScroll()) {
this.scrollToBottom();
this.newMessagesReceived = false;
}
}
}
};
render(props, state) {
const { username, messagesOnly, chatInputEnabled } = props;
const { messages, chatUserNames, webSocketConnected } = state;