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.

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