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.

102 lines
3.9 KiB

  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import ImmutablePropTypes from 'react-immutable-proptypes';
  4. import { connect } from 'react-redux';
  5. import { FormattedMessage } from 'react-intl';
  6. import { closeModal } from 'flavours/glitch/actions/modal';
  7. import emojify from 'flavours/glitch/features/emoji/emoji';
  8. import escapeTextContentForBrowser from 'escape-html';
  9. import InlineAccount from 'flavours/glitch/components/inline_account';
  10. import IconButton from 'flavours/glitch/components/icon_button';
  11. import RelativeTimestamp from 'flavours/glitch/components/relative_timestamp';
  12. import MediaAttachments from 'flavours/glitch/components/media_attachments';
  13. const mapStateToProps = (state, { statusId }) => ({
  14. language: state.getIn(['statuses', statusId, 'language']),
  15. versions: state.getIn(['history', statusId, 'items']),
  16. });
  17. const mapDispatchToProps = dispatch => ({
  18. onClose() {
  19. dispatch(closeModal());
  20. },
  21. });
  22. export default @connect(mapStateToProps, mapDispatchToProps)
  23. class CompareHistoryModal extends React.PureComponent {
  24. static propTypes = {
  25. onClose: PropTypes.func.isRequired,
  26. index: PropTypes.number.isRequired,
  27. statusId: PropTypes.string.isRequired,
  28. language: PropTypes.string.isRequired,
  29. versions: ImmutablePropTypes.list.isRequired,
  30. };
  31. render () {
  32. const { index, versions, language, onClose } = this.props;
  33. const currentVersion = versions.get(index);
  34. const emojiMap = currentVersion.get('emojis').reduce((obj, emoji) => {
  35. obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
  36. return obj;
  37. }, {});
  38. const content = { __html: emojify(currentVersion.get('content'), emojiMap) };
  39. const spoilerContent = { __html: emojify(escapeTextContentForBrowser(currentVersion.get('spoiler_text')), emojiMap) };
  40. const formattedDate = <RelativeTimestamp timestamp={currentVersion.get('created_at')} short={false} />;
  41. const formattedName = <InlineAccount accountId={currentVersion.get('account')} />;
  42. const label = currentVersion.get('original') ? (
  43. <FormattedMessage id='status.history.created' defaultMessage='{name} created {date}' values={{ name: formattedName, date: formattedDate }} />
  44. ) : (
  45. <FormattedMessage id='status.history.edited' defaultMessage='{name} edited {date}' values={{ name: formattedName, date: formattedDate }} />
  46. );
  47. return (
  48. <div className='modal-root__modal compare-history-modal'>
  49. <div className='report-modal__target'>
  50. <IconButton className='report-modal__close' icon='times' onClick={onClose} size={20} />
  51. {label}
  52. </div>
  53. <div className='compare-history-modal__container'>
  54. <div className='status__content'>
  55. {currentVersion.get('spoiler_text').length > 0 && (
  56. <React.Fragment>
  57. <div className='translate' dangerouslySetInnerHTML={spoilerContent} lang={language} />
  58. <hr />
  59. </React.Fragment>
  60. )}
  61. <div className='status__content__text status__content__text--visible translate' dangerouslySetInnerHTML={content} lang={language} />
  62. {!!currentVersion.get('poll') && (
  63. <div className='poll'>
  64. <ul>
  65. {currentVersion.getIn(['poll', 'options']).map(option => (
  66. <li key={option.get('title')}>
  67. <span className='poll__input disabled' />
  68. <span
  69. className='poll__option__text translate'
  70. dangerouslySetInnerHTML={{ __html: emojify(escapeTextContentForBrowser(option.get('title')), emojiMap) }}
  71. lang={language}
  72. />
  73. </li>
  74. ))}
  75. </ul>
  76. </div>
  77. )}
  78. <MediaAttachments status={currentVersion} lang={language} />
  79. </div>
  80. </div>
  81. </div>
  82. );
  83. }
  84. }