about summary refs log blame commit diff
path: root/app/javascript/flavours/glitch/containers/media_container.js
blob: 11c15d7c6f250d3230d3db26f09e185182424856 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                       

                                                         
                                   
                                             
                                                                   
                                                                    
                                                   
                                                                                 
                                                                            

                                                                   


                                             
                                                                             
                                                           

                                        
                                            



                
               
                          
                  

                                       
                                                       
                                                                            

                                    
                                      
                                                                                                
                                    
 
                                                       
                                                                            
                                                 
   
                            
                                                          
                                                   



                            
                    



                                              

             
                                              

                                                        


                                                                           
                                                                                                              
                                  


                                                               
                                               
                                  


                                                  
               
                                         
                                                          
                        
              
 
                                                                                                  
                                  
                                        
                                             

                                                           
                                               
                                                                 

                      
                   



                     
import React, { PureComponent, Fragment } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { IntlProvider, addLocaleData } from 'react-intl';
import { fromJS } from 'immutable';
import { getLocale } from 'mastodon/locales';
import { getScrollbarWidth } from 'flavours/glitch/util/scrollbar';
import MediaGallery from 'flavours/glitch/components/media_gallery';
import Poll from 'flavours/glitch/components/poll';
import { ImmutableHashtag as Hashtag } from 'flavours/glitch/components/hashtag';
import ModalRoot from 'flavours/glitch/components/modal_root';
import MediaModal from 'flavours/glitch/features/ui/components/media_modal';
import Video from 'flavours/glitch/features/video';
import Card from 'flavours/glitch/features/status/components/card';
import Audio from 'flavours/glitch/features/audio';

const { localeData, messages } = getLocale();
addLocaleData(localeData);

const MEDIA_COMPONENTS = { MediaGallery, Video, Card, Poll, Hashtag, Audio };

export default class MediaContainer extends PureComponent {

  static propTypes = {
    locale: PropTypes.string.isRequired,
    components: PropTypes.object.isRequired,
  };

  state = {
    media: null,
    index: null,
    time: null,
    backgroundColor: null,
    options: null,
  };

  handleOpenMedia = (media, index) => {
    document.body.classList.add('with-modals--active');
    document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;

    this.setState({ media, index });
  }

  handleOpenVideo = (options) => {
    const { components } = this.props;
    const { media } = JSON.parse(components[options.componentIndex].getAttribute('data-props'));
    const mediaList = fromJS(media);

    document.body.classList.add('with-modals--active');
    document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;

    this.setState({ media: mediaList, options });
  }

  handleCloseMedia = () => {
    document.body.classList.remove('with-modals--active');
    document.documentElement.style.marginRight = 0;

    this.setState({
      media: null,
      index: null,
      time: null,
      backgroundColor: null,
      options: null,
    });
  }

  setBackgroundColor = color => {
    this.setState({ backgroundColor: color });
  }

  render () {
    const { locale, components } = this.props;

    return (
      <IntlProvider locale={locale} messages={messages}>
        <Fragment>
          {[].map.call(components, (component, i) => {
            const componentName = component.getAttribute('data-component');
            const Component = MEDIA_COMPONENTS[componentName];
            const { media, card, poll, hashtag, ...props } = JSON.parse(component.getAttribute('data-props'));

            Object.assign(props, {
              ...(media   ? { media:   fromJS(media)   } : {}),
              ...(card    ? { card:    fromJS(card)    } : {}),
              ...(poll    ? { poll:    fromJS(poll)    } : {}),
              ...(hashtag ? { hashtag: fromJS(hashtag) } : {}),

              ...(componentName === 'Video' ? {
                componentIndex: i,
                onOpenVideo: this.handleOpenVideo,
              } : {
                onOpenMedia: this.handleOpenMedia,
              }),
            });

            return ReactDOM.createPortal(
              <Component {...props} key={`media-${i}`} />,
              component,
            );
          })}

          <ModalRoot backgroundColor={this.state.backgroundColor} onClose={this.handleCloseMedia}>
            {this.state.media && (
              <MediaModal
                media={this.state.media}
                index={this.state.index || 0}
                currentTime={this.state.options?.startTime}
                autoPlay={this.state.options?.autoPlay}
                volume={this.state.options?.defaultVolume}
                onClose={this.handleCloseMedia}
                onChangeBackgroundColor={this.setBackgroundColor}
              />
            )}
          </ModalRoot>
        </Fragment>
      </IntlProvider>
    );
  }

}