You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.4 KiB

  1. import Status from './status';
  2. import ImmutablePropTypes from 'react-immutable-proptypes';
  3. import PureRenderMixin from 'react-addons-pure-render-mixin';
  4. import { ScrollContainer } from 'react-router-scroll';
  5. import StatusContainer from '../containers/status_container';
  6. const StatusList = React.createClass({
  7. propTypes: {
  8. statusIds: ImmutablePropTypes.list.isRequired,
  9. onScrollToBottom: React.PropTypes.func,
  10. onScrollToTop: React.PropTypes.func,
  11. onScroll: React.PropTypes.func,
  12. trackScroll: React.PropTypes.bool,
  13. isLoading: React.PropTypes.bool
  14. },
  15. getDefaultProps () {
  16. return {
  17. trackScroll: true
  18. };
  19. },
  20. mixins: [PureRenderMixin],
  21. handleScroll (e) {
  22. const { scrollTop, scrollHeight, clientHeight } = e.target;
  23. const offset = scrollHeight - scrollTop - clientHeight;
  24. this._oldScrollPosition = scrollHeight - scrollTop;
  25. if (250 > offset && this.props.onScrollToBottom && !this.props.isLoading) {
  26. this.props.onScrollToBottom();
  27. } else if (scrollTop < 100 && this.props.onScrollToTop) {
  28. this.props.onScrollToTop();
  29. } else if (this.props.onScroll) {
  30. this.props.onScroll();
  31. }
  32. },
  33. componentDidMount () {
  34. this.attachScrollListener();
  35. },
  36. componentDidUpdate (prevProps) {
  37. if (this.node.scrollTop > 0 && (prevProps.statusIds.size < this.props.statusIds.size && prevProps.statusIds.first() !== this.props.statusIds.first() && !!this._oldScrollPosition)) {
  38. this.node.scrollTop = this.node.scrollHeight - this._oldScrollPosition;
  39. }
  40. },
  41. componentWillUnmount () {
  42. this.detachScrollListener();
  43. },
  44. attachScrollListener () {
  45. this.node.addEventListener('scroll', this.handleScroll);
  46. },
  47. detachScrollListener () {
  48. this.node.removeEventListener('scroll', this.handleScroll);
  49. },
  50. setRef (c) {
  51. this.node = c;
  52. },
  53. render () {
  54. const { statusIds, onScrollToBottom, trackScroll } = this.props;
  55. const scrollableArea = (
  56. <div className='scrollable' ref={this.setRef}>
  57. <div>
  58. {statusIds.map((statusId) => {
  59. return <StatusContainer key={statusId} id={statusId} />;
  60. })}
  61. </div>
  62. </div>
  63. );
  64. if (trackScroll) {
  65. return (
  66. <ScrollContainer scrollKey='status-list'>
  67. {scrollableArea}
  68. </ScrollContainer>
  69. );
  70. } else {
  71. return scrollableArea;
  72. }
  73. }
  74. });
  75. export default StatusList;