diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2018-11-08 21:35:06 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-08 21:35:06 +0100 |
commit | dd00cd19d2536ce70442d74d72986721427691a5 (patch) | |
tree | 17e81f1ccb7081765169dc3a9c1cbc7214d65629 /app/javascript/mastodon/components/scrollable_list.js | |
parent | f055907857dd0ecf7b1780b4ec770c0073de7466 (diff) |
Use local instead of global loading indicator for timelines, account timelines (#9224)
So that opening a profile feels faster. Also, pinned toots are not shown before other toots have loaded. Also, if no toots are loaded, added empty message
Diffstat (limited to 'app/javascript/mastodon/components/scrollable_list.js')
-rw-r--r-- | app/javascript/mastodon/components/scrollable_list.js | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/app/javascript/mastodon/components/scrollable_list.js b/app/javascript/mastodon/components/scrollable_list.js index 94e157acf..91a895bce 100644 --- a/app/javascript/mastodon/components/scrollable_list.js +++ b/app/javascript/mastodon/components/scrollable_list.js @@ -8,6 +8,7 @@ import { throttle } from 'lodash'; import { List as ImmutableList } from 'immutable'; import classNames from 'classnames'; import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../features/ui/util/fullscreen'; +import LoadingIndicator from './loading_indicator'; const MOUSE_IDLE_DELAY = 300; @@ -25,6 +26,7 @@ export default class ScrollableList extends PureComponent { trackScroll: PropTypes.bool, shouldUpdateScroll: PropTypes.func, isLoading: PropTypes.bool, + showLoading: PropTypes.bool, hasMore: PropTypes.bool, prepend: PropTypes.node, alwaysPrepend: PropTypes.bool, @@ -70,6 +72,7 @@ export default class ScrollableList extends PureComponent { if (this.mouseIdleTimer === null) { return; } + clearTimeout(this.mouseIdleTimer); this.mouseIdleTimer = null; }; @@ -77,13 +80,13 @@ export default class ScrollableList extends PureComponent { handleMouseMove = throttle(() => { // As long as the mouse keeps moving, clear and restart the idle timer. this.clearMouseIdleTimer(); - this.mouseIdleTimer = - setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY); + this.mouseIdleTimer = setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY); 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); @@ -98,6 +101,7 @@ export default class ScrollableList extends PureComponent { if (this.scrollToTopOnMouseIdle) { this.node.scrollTop = 0; } + this.mouseMovedRecently = false; this.scrollToTopOnMouseIdle = false; } @@ -105,6 +109,7 @@ export default class ScrollableList extends PureComponent { componentDidMount () { this.attachScrollListener(); this.attachIntersectionObserver(); + attachFullscreenListener(this.onFullScreenChange); // Handle initial scroll posiiton @@ -115,6 +120,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.mouseMovedRecently) { return this.node.scrollHeight - this.node.scrollTop; } else { @@ -168,12 +174,14 @@ export default class ScrollableList extends PureComponent { getFirstChildKey (props) { const { children } = props; - let firstChild = children; + let firstChild = children; + if (children instanceof ImmutableList) { firstChild = children.get(0); } else if (Array.isArray(children)) { firstChild = children[0]; } + return firstChild && firstChild.key; } @@ -181,20 +189,32 @@ export default class ScrollableList extends PureComponent { this.node = c; } - handleLoadMore = (e) => { + handleLoadMore = e => { e.preventDefault(); this.props.onLoadMore(); } render () { - const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, alwaysPrepend, alwaysShowScrollbar, emptyMessage, onLoadMore } = this.props; + const { children, scrollKey, trackScroll, shouldUpdateScroll, showLoading, isLoading, hasMore, prepend, alwaysPrepend, alwaysShowScrollbar, emptyMessage, onLoadMore } = this.props; const { fullscreen } = this.state; const childrenCount = React.Children.count(children); const loadMore = (hasMore && childrenCount > 0 && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null; let scrollableArea = null; - if (isLoading || childrenCount > 0 || !emptyMessage) { + if (showLoading) { + scrollableArea = ( + <div className='scrollable scrollable--flex' ref={this.setRef}> + <div role='feed' className='item-list'> + {prepend} + </div> + + <div className='scrollable__append'> + <LoadingIndicator /> + </div> + </div> + ); + } else if (isLoading || childrenCount > 0 || !emptyMessage) { scrollableArea = ( <div className={classNames('scrollable', { fullscreen })} ref={this.setRef} onMouseMove={this.handleMouseMove}> <div role='feed' className='item-list'> |