diff options
author | Les Orchard <me@lmorchard.com> | 2018-11-08 12:45:20 -0500 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2018-11-08 18:45:20 +0100 |
commit | 9cfd610484541c14bcde3c368a158b9b5d2a6499 (patch) | |
tree | 76a024746149f0bf511e9f4a71f5f52188362665 /app | |
parent | b22db8162a936884ba17bc89637d5368e6745df0 (diff) |
Cancel list scroll reset after mouse move on wheel scroll (#9233)
- Use object properties rather than component state for mouseMovedRecently and scrollToTopOnMouseIdle flags - Remove redundant scrollToTop prop call, also fixing an attempt to call an undefined prop. Fixes #9217
Diffstat (limited to 'app')
-rw-r--r-- | app/javascript/mastodon/components/scrollable_list.js | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index e51c83c2b..94e157acf 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -39,8 +39,6 @@ export default class ScrollableList extends PureComponent { state = { fullscreen: null, - mouseMovedRecently: false, - scrollToTopOnMouseIdle: false, }; intersectionObserverWrapper = new IntersectionObserverWrapper(); @@ -65,6 +63,8 @@ export default class ScrollableList extends PureComponent { }); mouseIdleTimer = null; + mouseMovedRecently = false; + scrollToTopOnMouseIdle = false; clearMouseIdleTimer = () => { if (this.mouseIdleTimer === null) { @@ -80,29 +80,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 () { @@ -118,7 +115,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; @@ -161,10 +158,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) { |