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.

92 lines
2.8 KiB

  1. import React, { PureComponent, Fragment } from 'react';
  2. import ReactDOM from 'react-dom';
  3. import PropTypes from 'prop-types';
  4. import { IntlProvider, addLocaleData } from 'react-intl';
  5. import { getLocale } from '../locales';
  6. import MediaGallery from '../components/media_gallery';
  7. import Video from '../features/video';
  8. import Card from '../features/status/components/card';
  9. import Poll from 'mastodon/components/poll';
  10. import ModalRoot from '../components/modal_root';
  11. import MediaModal from '../features/ui/components/media_modal';
  12. import { List as ImmutableList, fromJS } from 'immutable';
  13. const { localeData, messages } = getLocale();
  14. addLocaleData(localeData);
  15. const MEDIA_COMPONENTS = { MediaGallery, Video, Card, Poll };
  16. export default class MediaContainer extends PureComponent {
  17. static propTypes = {
  18. locale: PropTypes.string.isRequired,
  19. components: PropTypes.object.isRequired,
  20. };
  21. state = {
  22. media: null,
  23. index: null,
  24. time: null,
  25. };
  26. handleOpenMedia = (media, index) => {
  27. document.body.classList.add('with-modals--active');
  28. this.setState({ media, index });
  29. }
  30. handleOpenVideo = (video, time) => {
  31. const media = ImmutableList([video]);
  32. document.body.classList.add('with-modals--active');
  33. this.setState({ media, time });
  34. }
  35. handleCloseMedia = () => {
  36. document.body.classList.remove('with-modals--active');
  37. this.setState({ media: null, index: null, time: null });
  38. }
  39. render () {
  40. const { locale, components } = this.props;
  41. return (
  42. <IntlProvider locale={locale} messages={messages}>
  43. <Fragment>
  44. {[].map.call(components, (component, i) => {
  45. const componentName = component.getAttribute('data-component');
  46. const Component = MEDIA_COMPONENTS[componentName];
  47. const { media, card, poll, ...props } = JSON.parse(component.getAttribute('data-props'));
  48. Object.assign(props, {
  49. ...(media ? { media: fromJS(media) } : {}),
  50. ...(card ? { card: fromJS(card) } : {}),
  51. ...(poll ? { poll: fromJS(poll) } : {}),
  52. ...(componentName === 'Video' ? {
  53. onOpenVideo: this.handleOpenVideo,
  54. } : {
  55. onOpenMedia: this.handleOpenMedia,
  56. }),
  57. });
  58. return ReactDOM.createPortal(
  59. <Component {...props} key={`media-${i}`} />,
  60. component,
  61. );
  62. })}
  63. <ModalRoot onClose={this.handleCloseMedia}>
  64. {this.state.media && (
  65. <MediaModal
  66. media={this.state.media}
  67. index={this.state.index || 0}
  68. time={this.state.time}
  69. onClose={this.handleCloseMedia}
  70. />
  71. )}
  72. </ModalRoot>
  73. </Fragment>
  74. </IntlProvider>
  75. );
  76. }
  77. }