index.jsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import PropTypes from 'prop-types';
  2. import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
  3. import { Helmet } from 'react-helmet';
  4. import ImmutablePropTypes from 'react-immutable-proptypes';
  5. import ImmutablePureComponent from 'react-immutable-pure-component';
  6. import { connect } from 'react-redux';
  7. import { debounce } from 'lodash';
  8. import RefreshIcon from '@/material-icons/400-24px/refresh.svg?react';
  9. import { Icon } from 'mastodon/components/icon';
  10. import { fetchReblogs, expandReblogs } from '../../actions/interactions';
  11. import ColumnHeader from '../../components/column_header';
  12. import { LoadingIndicator } from '../../components/loading_indicator';
  13. import ScrollableList from '../../components/scrollable_list';
  14. import AccountContainer from '../../containers/account_container';
  15. import Column from '../ui/components/column';
  16. const messages = defineMessages({
  17. refresh: { id: 'refresh', defaultMessage: 'Refresh' },
  18. });
  19. const mapStateToProps = (state, props) => ({
  20. accountIds: state.getIn(['user_lists', 'reblogged_by', props.params.statusId, 'items']),
  21. hasMore: !!state.getIn(['user_lists', 'reblogged_by', props.params.statusId, 'next']),
  22. isLoading: state.getIn(['user_lists', 'reblogged_by', props.params.statusId, 'isLoading'], true),
  23. });
  24. class Reblogs extends ImmutablePureComponent {
  25. static propTypes = {
  26. params: PropTypes.object.isRequired,
  27. dispatch: PropTypes.func.isRequired,
  28. accountIds: ImmutablePropTypes.list,
  29. hasMore: PropTypes.bool,
  30. isLoading: PropTypes.bool,
  31. multiColumn: PropTypes.bool,
  32. intl: PropTypes.object.isRequired,
  33. };
  34. UNSAFE_componentWillMount () {
  35. if (!this.props.accountIds) {
  36. this.props.dispatch(fetchReblogs(this.props.params.statusId));
  37. }
  38. }
  39. handleRefresh = () => {
  40. this.props.dispatch(fetchReblogs(this.props.params.statusId));
  41. };
  42. handleLoadMore = debounce(() => {
  43. this.props.dispatch(expandReblogs(this.props.params.statusId));
  44. }, 300, { leading: true });
  45. render () {
  46. const { intl, accountIds, hasMore, isLoading, multiColumn } = this.props;
  47. if (!accountIds) {
  48. return (
  49. <Column>
  50. <LoadingIndicator />
  51. </Column>
  52. );
  53. }
  54. const emptyMessage = <FormattedMessage id='status.reblogs.empty' defaultMessage='No one has boosted this post yet. When someone does, they will show up here.' />;
  55. return (
  56. <Column bindToDocument={!multiColumn}>
  57. <ColumnHeader
  58. showBackButton
  59. multiColumn={multiColumn}
  60. extraButton={(
  61. <button type='button' className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' icon={RefreshIcon} /></button>
  62. )}
  63. />
  64. <ScrollableList
  65. scrollKey='reblogs'
  66. onLoadMore={this.handleLoadMore}
  67. hasMore={hasMore}
  68. isLoading={isLoading}
  69. emptyMessage={emptyMessage}
  70. bindToDocument={!multiColumn}
  71. >
  72. {accountIds.map(id =>
  73. <AccountContainer key={id} id={id} withNote={false} />,
  74. )}
  75. </ScrollableList>
  76. <Helmet>
  77. <meta name='robots' content='noindex' />
  78. </Helmet>
  79. </Column>
  80. );
  81. }
  82. }
  83. export default connect(mapStateToProps)(injectIntl(Reblogs));