The code powering m.abunchtell.com https://m.abunchtell.com
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

129 linhas
3.4 KiB

  1. import Status from './status';
  2. import ImmutablePropTypes from 'react-immutable-proptypes';
  3. import { ScrollContainer } from 'react-router-scroll';
  4. import PropTypes from 'prop-types';
  5. import StatusContainer from '../containers/status_container';
  6. import LoadMore from './load_more';
  7. class StatusList extends React.PureComponent {
  8. constructor (props, context) {
  9. super(props, context);
  10. this.handleScroll = this.handleScroll.bind(this);
  11. this.setRef = this.setRef.bind(this);
  12. this.handleLoadMore = this.handleLoadMore.bind(this);
  13. }
  14. handleScroll (e) {
  15. const { scrollTop, scrollHeight, clientHeight } = e.target;
  16. const offset = scrollHeight - scrollTop - clientHeight;
  17. this._oldScrollPosition = scrollHeight - scrollTop;
  18. if (250 > offset && this.props.onScrollToBottom && !this.props.isLoading) {
  19. this.props.onScrollToBottom();
  20. } else if (scrollTop < 100 && this.props.onScrollToTop) {
  21. this.props.onScrollToTop();
  22. } else if (this.props.onScroll) {
  23. this.props.onScroll();
  24. }
  25. }
  26. componentDidMount () {
  27. this.attachScrollListener();
  28. }
  29. componentDidUpdate (prevProps) {
  30. if (this.node.scrollTop > 0 && (prevProps.statusIds.size < this.props.statusIds.size && prevProps.statusIds.first() !== this.props.statusIds.first() && !!this._oldScrollPosition)) {
  31. this.node.scrollTop = this.node.scrollHeight - this._oldScrollPosition;
  32. }
  33. }
  34. componentWillUnmount () {
  35. this.detachScrollListener();
  36. }
  37. attachScrollListener () {
  38. this.node.addEventListener('scroll', this.handleScroll);
  39. }
  40. detachScrollListener () {
  41. this.node.removeEventListener('scroll', this.handleScroll);
  42. }
  43. setRef (c) {
  44. this.node = c;
  45. }
  46. handleLoadMore (e) {
  47. e.preventDefault();
  48. this.props.onScrollToBottom();
  49. }
  50. render () {
  51. const { statusIds, onScrollToBottom, scrollKey, shouldUpdateScroll, isLoading, isUnread, hasMore, prepend, emptyMessage } = this.props;
  52. let loadMore = '';
  53. let scrollableArea = '';
  54. let unread = '';
  55. if (!isLoading && statusIds.size > 0 && hasMore) {
  56. loadMore = <LoadMore onClick={this.handleLoadMore} />;
  57. }
  58. if (isUnread) {
  59. unread = <div className='status-list__unread-indicator' />;
  60. }
  61. if (isLoading || statusIds.size > 0 || !emptyMessage) {
  62. scrollableArea = (
  63. <div className='scrollable' ref={this.setRef}>
  64. {unread}
  65. <div className='status-list'>
  66. {prepend}
  67. {statusIds.map((statusId) => {
  68. return <StatusContainer key={statusId} id={statusId} />;
  69. })}
  70. {loadMore}
  71. </div>
  72. </div>
  73. );
  74. } else {
  75. scrollableArea = (
  76. <div className='empty-column-indicator' ref={this.setRef}>
  77. {emptyMessage}
  78. </div>
  79. );
  80. }
  81. return (
  82. <ScrollContainer scrollKey={scrollKey} shouldUpdateScroll={shouldUpdateScroll}>
  83. {scrollableArea}
  84. </ScrollContainer>
  85. );
  86. }
  87. }
  88. StatusList.propTypes = {
  89. scrollKey: PropTypes.string.isRequired,
  90. statusIds: ImmutablePropTypes.list.isRequired,
  91. onScrollToBottom: PropTypes.func,
  92. onScrollToTop: PropTypes.func,
  93. onScroll: PropTypes.func,
  94. shouldUpdateScroll: PropTypes.func,
  95. isLoading: PropTypes.bool,
  96. isUnread: PropTypes.bool,
  97. hasMore: PropTypes.bool,
  98. prepend: PropTypes.node,
  99. emptyMessage: PropTypes.node
  100. };
  101. StatusList.defaultProps = {
  102. trackScroll: true
  103. };
  104. export default StatusList;