|
|
|
@ -40,8 +40,6 @@ export default class ScrollableList extends PureComponent { |
|
|
|
|
|
|
|
|
|
state = { |
|
|
|
|
fullscreen: null, |
|
|
|
|
mouseMovedRecently: false, |
|
|
|
|
scrollToTopOnMouseIdle: false, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
intersectionObserverWrapper = new IntersectionObserverWrapper(); |
|
|
|
@ -66,6 +64,8 @@ export default class ScrollableList extends PureComponent { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
mouseIdleTimer = null; |
|
|
|
|
mouseMovedRecently = false; |
|
|
|
|
scrollToTopOnMouseIdle = false; |
|
|
|
|
|
|
|
|
|
clearMouseIdleTimer = () => { |
|
|
|
|
if (this.mouseIdleTimer === null) { |
|
|
|
@ -81,29 +81,26 @@ export default class ScrollableList extends PureComponent { |
|
|
|
|
this.mouseIdleTimer = |
|
|
|
|
setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY); |
|
|
|
|
|
|
|
|
|
this.setState(({ |
|
|
|
|
mouseMovedRecently, |
|
|
|
|
scrollToTopOnMouseIdle, |
|
|
|
|
}) => ({ |
|
|
|
|
mouseMovedRecently: true, |
|
|
|
|
// Only set scrollToTopOnMouseIdle if we just started moving and were
|
|
|
|
|
// scrolled to the top. Otherwise, just retain the previous state.
|
|
|
|
|
scrollToTopOnMouseIdle: |
|
|
|
|
mouseMovedRecently |
|
|
|
|
? scrollToTopOnMouseIdle |
|
|
|
|
: (this.node.scrollTop === 0), |
|
|
|
|
})); |
|
|
|
|
if (!this.mouseMovedRecently && this.node.scrollTop === 0) { |
|
|
|
|
// Only set if we just started moving and are scrolled to the top.
|
|
|
|
|
this.scrollToTopOnMouseIdle = true; |
|
|
|
|
} |
|
|
|
|
// Save setting this flag for last, so we can do the comparison above.
|
|
|
|
|
this.mouseMovedRecently = true; |
|
|
|
|
}, MOUSE_IDLE_DELAY / 2); |
|
|
|
|
|
|
|
|
|
handleWheel = throttle(() => { |
|
|
|
|
this.scrollToTopOnMouseIdle = false; |
|
|
|
|
}, 150, { |
|
|
|
|
trailing: true, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
handleMouseIdle = () => { |
|
|
|
|
if (this.state.scrollToTopOnMouseIdle) { |
|
|
|
|
if (this.scrollToTopOnMouseIdle) { |
|
|
|
|
this.node.scrollTop = 0; |
|
|
|
|
this.props.onScrollToTop(); |
|
|
|
|
} |
|
|
|
|
this.setState({ |
|
|
|
|
mouseMovedRecently: false, |
|
|
|
|
scrollToTopOnMouseIdle: false, |
|
|
|
|
}); |
|
|
|
|
this.mouseMovedRecently = false; |
|
|
|
|
this.scrollToTopOnMouseIdle = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
componentDidMount () { |
|
|
|
@ -135,7 +132,7 @@ export default class ScrollableList extends PureComponent { |
|
|
|
|
const someItemInserted = React.Children.count(prevProps.children) > 0 && |
|
|
|
|
React.Children.count(prevProps.children) < React.Children.count(this.props.children) && |
|
|
|
|
this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); |
|
|
|
|
if ((someItemInserted && this.node.scrollTop > 0) || this.state.mouseMovedRecently) { |
|
|
|
|
if ((someItemInserted && this.node.scrollTop > 0) || this.mouseMovedRecently) { |
|
|
|
|
return this.node.scrollHeight - this.node.scrollTop; |
|
|
|
|
} else { |
|
|
|
|
return null; |
|
|
|
@ -172,10 +169,12 @@ export default class ScrollableList extends PureComponent { |
|
|
|
|
|
|
|
|
|
attachScrollListener () { |
|
|
|
|
this.node.addEventListener('scroll', this.handleScroll); |
|
|
|
|
this.node.addEventListener('wheel', this.handleWheel); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
detachScrollListener () { |
|
|
|
|
this.node.removeEventListener('scroll', this.handleScroll); |
|
|
|
|
this.node.removeEventListener('wheel', this.handleWheel); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getFirstChildKey (props) { |
|
|
|
|