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.

86 lines
3.0 KiB

  1. import { connect } from 'react-redux';
  2. import PureRenderMixin from 'react-addons-pure-render-mixin';
  3. import ImmutablePropTypes from 'react-immutable-proptypes';
  4. import { fetchStatus } from '../../actions/statuses';
  5. import Immutable from 'immutable';
  6. import EmbeddedStatus from '../../components/status';
  7. import LoadingIndicator from '../../components/loading_indicator';
  8. import DetailedStatus from './components/detailed_status';
  9. import ActionBar from './components/action_bar';
  10. import { favourite, reblog } from '../../actions/interactions';
  11. import { replyCompose } from '../../actions/compose';
  12. import { selectStatus } from '../../reducers/timelines';
  13. function selectStatuses(state, ids) {
  14. return ids.map(id => selectStatus(state, id)).filterNot(status => status === null);
  15. };
  16. const mapStateToProps = (state, props) => ({
  17. status: selectStatus(state, Number(props.params.statusId)),
  18. ancestors: selectStatuses(state, state.getIn(['timelines', 'ancestors', Number(props.params.statusId)], Immutable.OrderedSet())),
  19. descendants: selectStatuses(state, state.getIn(['timelines', 'descendants', Number(props.params.statusId)], Immutable.OrderedSet())),
  20. me: state.getIn(['timelines', 'me'])
  21. });
  22. const Status = React.createClass({
  23. propTypes: {
  24. params: React.PropTypes.object.isRequired,
  25. dispatch: React.PropTypes.func.isRequired,
  26. status: ImmutablePropTypes.map,
  27. ancestors: ImmutablePropTypes.orderedSet.isRequired,
  28. descendants: ImmutablePropTypes.orderedSet.isRequired
  29. },
  30. mixins: [PureRenderMixin],
  31. componentWillMount () {
  32. this.props.dispatch(fetchStatus(Number(this.props.params.statusId)));
  33. },
  34. componentWillReceiveProps (nextProps) {
  35. if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
  36. this.props.dispatch(fetchStatus(Number(nextProps.params.statusId)));
  37. }
  38. },
  39. handleFavouriteClick (status) {
  40. this.props.dispatch(favourite(status));
  41. },
  42. handleReplyClick (status) {
  43. this.props.dispatch(replyCompose(status));
  44. },
  45. handleReblogClick (status) {
  46. this.props.dispatch(reblog(status));
  47. },
  48. renderChildren (list) {
  49. return list.map(s => <EmbeddedStatus status={s} me={this.props.me} key={s.get('id')} onReply={this.handleReplyClick} onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} />);
  50. },
  51. render () {
  52. const { status, ancestors, descendants, me } = this.props;
  53. if (status === null) {
  54. return <LoadingIndicator />;
  55. }
  56. const account = status.get('account');
  57. return (
  58. <div style={{ overflowY: 'scroll', flex: '1 1 auto' }} className='scrollable'>
  59. <div>{this.renderChildren(ancestors)}</div>
  60. <DetailedStatus status={status} me={me} />
  61. <ActionBar status={status} onReply={this.handleReplyClick} onFavourite={this.handleFavouriteClick} onReblog={this.handleReblogClick} />
  62. <div>{this.renderChildren(descendants)}</div>
  63. </div>
  64. );
  65. }
  66. });
  67. export default connect(mapStateToProps)(Status);