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.

119 lines
3.7 KiB

  1. import React from 'react';
  2. import { connect } from 'react-redux';
  3. import ImmutablePropTypes from 'react-immutable-proptypes';
  4. import PropTypes from 'prop-types';
  5. import {
  6. fetchAccount,
  7. fetchAccountMediaTimeline,
  8. expandAccountMediaTimeline,
  9. } from '../../actions/accounts';
  10. import LoadingIndicator from '../../components/loading_indicator';
  11. import Column from '../ui/components/column';
  12. import ColumnBackButton from '../../components/column_back_button';
  13. import Immutable from 'immutable';
  14. import ImmutablePureComponent from 'react-immutable-pure-component';
  15. import { getAccountGallery } from '../../selectors';
  16. import MediaItem from './components/media_item';
  17. import HeaderContainer from '../account_timeline/containers/header_container';
  18. import { FormattedMessage } from 'react-intl';
  19. import { ScrollContainer } from 'react-router-scroll';
  20. import LoadMore from '../../components/load_more';
  21. const mapStateToProps = (state, props) => ({
  22. medias: getAccountGallery(state, Number(props.params.accountId)),
  23. isLoading: state.getIn(['timelines', 'accounts_media_timelines', Number(props.params.accountId), 'isLoading']),
  24. hasMore: !!state.getIn(['timelines', 'accounts_media_timelines', Number(props.params.accountId), 'next']),
  25. autoPlayGif: state.getIn(['meta', 'auto_play_gif']),
  26. });
  27. class AccountGallery extends ImmutablePureComponent {
  28. static propTypes = {
  29. params: PropTypes.object.isRequired,
  30. dispatch: PropTypes.func.isRequired,
  31. medias: ImmutablePropTypes.list.isRequired,
  32. isLoading: PropTypes.bool,
  33. hasMore: PropTypes.bool,
  34. autoPlayGif: PropTypes.bool,
  35. };
  36. componentDidMount () {
  37. this.props.dispatch(fetchAccount(Number(this.props.params.accountId)));
  38. this.props.dispatch(fetchAccountMediaTimeline(Number(this.props.params.accountId)));
  39. }
  40. componentWillReceiveProps (nextProps) {
  41. if (nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) {
  42. this.props.dispatch(fetchAccount(Number(nextProps.params.accountId)));
  43. this.props.dispatch(fetchAccountMediaTimeline(Number(this.props.params.accountId)));
  44. }
  45. }
  46. handleScrollToBottom = () => {
  47. if (this.props.hasMore) {
  48. this.props.dispatch(expandAccountMediaTimeline(Number(this.props.params.accountId)));
  49. }
  50. }
  51. handleScroll = (e) => {
  52. const { scrollTop, scrollHeight, clientHeight } = e.target;
  53. const offset = scrollHeight - scrollTop - clientHeight;
  54. if (150 > offset && !this.props.isLoading) {
  55. this.handleScrollToBottom();
  56. }
  57. }
  58. handleLoadMore = (e) => {
  59. e.preventDefault();
  60. this.handleScrollToBottom();
  61. }
  62. render () {
  63. const { medias, autoPlayGif, isLoading, hasMore } = this.props;
  64. let loadMore = null;
  65. if (!medias && isLoading) {
  66. return (
  67. <Column>
  68. <LoadingIndicator />
  69. </Column>
  70. );
  71. }
  72. if (!isLoading && medias.size > 0 && hasMore) {
  73. loadMore = <LoadMore onClick={this.handleLoadMore} />;
  74. }
  75. return (
  76. <Column>
  77. <ColumnBackButton />
  78. <ScrollContainer scrollKey='account_gallery'>
  79. <div className='scrollable' onScroll={this.handleScroll}>
  80. <HeaderContainer accountId={this.props.params.accountId} />
  81. <div className='account-section-headline'>
  82. <FormattedMessage id='account.media' defaultMessage='Media' />
  83. </div>
  84. <div className='account-gallery__container'>
  85. {medias.map(media =>
  86. <MediaItem
  87. key={media.get('id')}
  88. media={media}
  89. autoPlayGif={autoPlayGif}
  90. />
  91. )}
  92. {loadMore}
  93. </div>
  94. </div>
  95. </ScrollContainer>
  96. </Column>
  97. );
  98. }
  99. }
  100. export default connect(mapStateToProps)(AccountGallery);