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.

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