From 92d5c716beb0de2a57fedec512d5a34cf84c153d Mon Sep 17 00:00:00 2001 From: Alexander Skvortsov <38059171+askvortsov1@users.noreply.github.com> Date: Sun, 24 Jan 2021 12:12:42 -0500 Subject: [PATCH] Fix notification panel infinite scroll (#2524) Improves calculations for determining whether we are at the bottom of the notifications panel (which would trigger infinite scroll). This should be particularly effective in fixing issues on smaller screens. --- js/src/forum/components/NotificationList.js | 22 +++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/js/src/forum/components/NotificationList.js b/js/src/forum/components/NotificationList.js index 4eb7fea0d..2db7bbbf3 100644 --- a/js/src/forum/components/NotificationList.js +++ b/js/src/forum/components/NotificationList.js @@ -99,7 +99,9 @@ export default class NotificationList extends Component { super.oncreate(vnode); this.$notifications = this.$('.NotificationList-content'); - this.$scrollParent = this.$notifications.css('overflow') === 'auto' ? this.$notifications : $(window); + + // If we are on the notifications page, the window will be scrolling and not the $notifications element. + this.$scrollParent = this.inPanel() ? this.$notifications : $(window); this.boundScrollHandler = this.scrollHandler.bind(this); this.$scrollParent.on('scroll', this.boundScrollHandler); @@ -112,14 +114,22 @@ export default class NotificationList extends Component { scrollHandler() { const state = this.attrs.state; - const scrollTop = this.$scrollParent.scrollTop(); - const viewportHeight = this.$scrollParent.height(); + const notificationsElement = this.inPanel() ? this.$scrollParent[0] : document.querySelector('body'); - const contentTop = this.$scrollParent === this.$notifications ? 0 : this.$notifications.offset().top; - const contentHeight = this.$notifications[0].scrollHeight; + // On very short screens, the scrollHeight + scrollTop might not reach the clientHeight + // by a fraction of a pixel, so we compensate for that. + const atBottom = Math.abs(notificationsElement.scrollHeight - notificationsElement.scrollTop - notificationsElement.clientHeight) <= 1; - if (state.hasMoreResults() && !state.isLoading() && scrollTop + viewportHeight >= contentTop + contentHeight) { + if (state.hasMoreResults() && !state.isLoading() && atBottom) { state.loadMore(); } } + + /** + * If the NotificationList component isn't in a panel (e.g. on NotificationPage when mobile), + * we need to listen to scroll events on the window, and get scroll state from the body. + */ + inPanel() { + return this.$notifications.css('overflow') === 'auto'; + } }