diff options
Diffstat (limited to 'app/javascript/mastodon/components/status_list.js')
-rw-r--r-- | app/javascript/mastodon/components/status_list.js | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/app/javascript/mastodon/components/status_list.js b/app/javascript/mastodon/components/status_list.js index 87a95fd12..b82c63a84 100644 --- a/app/javascript/mastodon/components/status_list.js +++ b/app/javascript/mastodon/components/status_list.js @@ -26,6 +26,12 @@ class StatusList extends ImmutablePureComponent { trackScroll: true, }; + state = { + isIntersecting: [{ }], + } + + statusRefQueue = [] + handleScroll = (e) => { const { scrollTop, scrollHeight, clientHeight } = e.target; const offset = scrollHeight - scrollTop - clientHeight; @@ -42,6 +48,7 @@ class StatusList extends ImmutablePureComponent { componentDidMount () { this.attachScrollListener(); + this.attachIntersectionObserver(); } componentDidUpdate (prevProps) { @@ -52,6 +59,39 @@ class StatusList extends ImmutablePureComponent { componentWillUnmount () { this.detachScrollListener(); + this.detachIntersectionObserver(); + } + + attachIntersectionObserver () { + const onIntersection = (entries) => { + this.setState(state => { + const isIntersecting = { }; + + entries.forEach(entry => { + const statusId = entry.target.getAttribute('data-id'); + + state.isIntersecting[0][statusId] = entry.isIntersecting; + }); + + return { isIntersecting: [state.isIntersecting[0]] }; + }); + }; + + const options = { + root: this.node, + rootMargin: '300% 0px', + }; + + this.intersectionObserver = new IntersectionObserver(onIntersection, options); + + if (this.statusRefQueue.length) { + this.statusRefQueue.forEach(node => this.intersectionObserver.observe(node)); + this.statusRefQueue = []; + } + } + + detachIntersectionObserver () { + this.intersectionObserver.disconnect(); } attachScrollListener () { @@ -66,6 +106,15 @@ class StatusList extends ImmutablePureComponent { this.node = c; } + handleStatusRef = (node) => { + if (node && this.intersectionObserver) { + const statusId = node.getAttribute('data-id'); + this.intersectionObserver.observe(node); + } else { + this.statusRefQueue.push(node); + } + } + handleLoadMore = (e) => { e.preventDefault(); this.props.onScrollToBottom(); @@ -73,10 +122,11 @@ class StatusList extends ImmutablePureComponent { render () { const { statusIds, onScrollToBottom, scrollKey, shouldUpdateScroll, isLoading, isUnread, hasMore, prepend, emptyMessage } = this.props; + const isIntersecting = this.state.isIntersecting[0]; - let loadMore = ''; - let scrollableArea = ''; - let unread = ''; + let loadMore = null; + let scrollableArea = null; + let unread = null; if (!isLoading && statusIds.size > 0 && hasMore) { loadMore = <LoadMore onClick={this.handleLoadMore} />; @@ -95,7 +145,7 @@ class StatusList extends ImmutablePureComponent { {prepend} {statusIds.map((statusId) => { - return <StatusContainer key={statusId} id={statusId} />; + return <StatusContainer key={statusId} id={statusId} isIntersecting={isIntersecting[statusId]} onRef={this.handleStatusRef} />; })} {loadMore} |