[Glitch] Fix audio and video items in account gallery in web UI
Port 6cc5b822f5ca7df9b267ac2b5d24e2aac2dc0325 to glitch-soc Signed-off-by: Thibaut Girka <thib@sitedethib.com>
This commit is contained in:
		
							parent
							
								
									3f60b096b5
								
							
						
					
					
						commit
						dad3132046
					
				@ -61,73 +61,81 @@ export default class MediaItem extends ImmutablePureComponent {
 | 
			
		||||
    const width  = `${Math.floor((displayWidth - 4) / 3) - 4}px`;
 | 
			
		||||
    const height = width;
 | 
			
		||||
    const status = attachment.get('status');
 | 
			
		||||
    const title = status.get('spoiler_text') || attachment.get('description');
 | 
			
		||||
    const title  = status.get('spoiler_text') || attachment.get('description');
 | 
			
		||||
 | 
			
		||||
    let thumbnail = '';
 | 
			
		||||
    let thumbnail, label, icon, content;
 | 
			
		||||
 | 
			
		||||
    if (attachment.get('type') === 'unknown') {
 | 
			
		||||
      // Skip
 | 
			
		||||
    } else if (attachment.get('type') === 'audio') {
 | 
			
		||||
      thumbnail = (
 | 
			
		||||
    if (!visible) {
 | 
			
		||||
      icon = (
 | 
			
		||||
        <span className='account-gallery__item__icons'>
 | 
			
		||||
          <Icon id='music' />
 | 
			
		||||
          <Icon id='eye-slash' />
 | 
			
		||||
        </span>
 | 
			
		||||
      );
 | 
			
		||||
    } else if (attachment.get('type') === 'image') {
 | 
			
		||||
      const focusX = attachment.getIn(['meta', 'focus', 'x']) || 0;
 | 
			
		||||
      const focusY = attachment.getIn(['meta', 'focus', 'y']) || 0;
 | 
			
		||||
      const x      = ((focusX /  2) + .5) * 100;
 | 
			
		||||
      const y      = ((focusY / -2) + .5) * 100;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (['audio', 'video'].includes(attachment.get('type'))) {
 | 
			
		||||
        content = (
 | 
			
		||||
          <img
 | 
			
		||||
            src={attachment.get('preview_url') || attachment.getIn(['account', 'avatar_static'])}
 | 
			
		||||
            alt={attachment.get('description')}
 | 
			
		||||
            onLoad={this.handleImageLoad}
 | 
			
		||||
          />
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
      thumbnail = (
 | 
			
		||||
        <img
 | 
			
		||||
          src={attachment.get('preview_url')}
 | 
			
		||||
          alt={attachment.get('description')}
 | 
			
		||||
          title={attachment.get('description')}
 | 
			
		||||
          style={{ objectPosition: `${x}% ${y}%` }}
 | 
			
		||||
          onLoad={this.handleImageLoad}
 | 
			
		||||
        />
 | 
			
		||||
      );
 | 
			
		||||
    } else if (['gifv', 'video'].indexOf(attachment.get('type')) !== -1) {
 | 
			
		||||
      const autoPlay = !isIOS() && autoPlayGif;
 | 
			
		||||
      const label    = attachment.get('type') === 'video' ? <Icon id='play' /> : 'GIF';
 | 
			
		||||
        if (attachment.get('type') === 'audio') {
 | 
			
		||||
          label = <Icon id='music' />;
 | 
			
		||||
        } else {
 | 
			
		||||
          label = <Icon id='play' />;
 | 
			
		||||
        }
 | 
			
		||||
      } else if (attachment.get('type') === 'image') {
 | 
			
		||||
        const focusX = attachment.getIn(['meta', 'focus', 'x']) || 0;
 | 
			
		||||
        const focusY = attachment.getIn(['meta', 'focus', 'y']) || 0;
 | 
			
		||||
        const x      = ((focusX /  2) + .5) * 100;
 | 
			
		||||
        const y      = ((focusY / -2) + .5) * 100;
 | 
			
		||||
 | 
			
		||||
      thumbnail = (
 | 
			
		||||
        <div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}>
 | 
			
		||||
        content = (
 | 
			
		||||
          <img
 | 
			
		||||
            src={attachment.get('preview_url')}
 | 
			
		||||
            alt={attachment.get('description')}
 | 
			
		||||
            style={{ objectPosition: `${x}% ${y}%` }}
 | 
			
		||||
            onLoad={this.handleImageLoad}
 | 
			
		||||
          />
 | 
			
		||||
        );
 | 
			
		||||
      } else if (attachment.get('type') === 'gifv') {
 | 
			
		||||
        content = (
 | 
			
		||||
          <video
 | 
			
		||||
            className='media-gallery__item-gifv-thumbnail'
 | 
			
		||||
            aria-label={attachment.get('description')}
 | 
			
		||||
            title={attachment.get('description')}
 | 
			
		||||
            role='application'
 | 
			
		||||
            src={attachment.get('url')}
 | 
			
		||||
            onMouseEnter={this.handleMouseEnter}
 | 
			
		||||
            onMouseLeave={this.handleMouseLeave}
 | 
			
		||||
            autoPlay={autoPlay}
 | 
			
		||||
            autoPlay={!isIOS() && autoPlayGif}
 | 
			
		||||
            loop
 | 
			
		||||
            muted
 | 
			
		||||
          />
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        label = 'GIF';
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      thumbnail = (
 | 
			
		||||
        <div className='media-gallery__gifv'>
 | 
			
		||||
          {content}
 | 
			
		||||
 | 
			
		||||
          <span className='media-gallery__gifv__label'>{label}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const icon = (
 | 
			
		||||
      <span className='account-gallery__item__icons'>
 | 
			
		||||
        <Icon id='eye-slash' />
 | 
			
		||||
      </span>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className='account-gallery__item' style={{ width, height }}>
 | 
			
		||||
        <a className='media-gallery__item-thumbnail' href={status.get('url')} onClick={this.handleClick} title={title} target='_blank' rel='noopener noreferrer'>
 | 
			
		||||
          <Blurhash
 | 
			
		||||
            hash={attachment.get('blurhash')}
 | 
			
		||||
            className={classNames('media-gallery__preview', {
 | 
			
		||||
              'media-gallery__preview--hidden': visible && loaded,
 | 
			
		||||
            })}
 | 
			
		||||
            className={classNames('media-gallery__preview', { 'media-gallery__preview--hidden': visible && loaded })}
 | 
			
		||||
            dummy={!useBlurhash}
 | 
			
		||||
          />
 | 
			
		||||
 | 
			
		||||
          {visible ? thumbnail : icon}
 | 
			
		||||
        </a>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
@ -113,9 +113,9 @@ class AccountGallery extends ImmutablePureComponent {
 | 
			
		||||
 | 
			
		||||
  handleOpenMedia = attachment => {
 | 
			
		||||
    if (attachment.get('type') === 'video') {
 | 
			
		||||
      this.props.dispatch(openModal('VIDEO', { media: attachment, status: attachment.get('status') }));
 | 
			
		||||
      this.props.dispatch(openModal('VIDEO', { media: attachment, status: attachment.get('status'), options: { autoPlay: true } }));
 | 
			
		||||
    } else if (attachment.get('type') === 'audio') {
 | 
			
		||||
      this.props.dispatch(openModal('AUDIO', { media: attachment, status: attachment.get('status') }));
 | 
			
		||||
      this.props.dispatch(openModal('AUDIO', { media: attachment, status: attachment.get('status'), options: { autoPlay: true } }));
 | 
			
		||||
    } else {
 | 
			
		||||
      const media = attachment.getIn(['status', 'media_attachments']);
 | 
			
		||||
      const index = media.findIndex(x => x.get('id') === attachment.get('id'));
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,7 @@ class Audio extends React.PureComponent {
 | 
			
		||||
    backgroundColor: PropTypes.string,
 | 
			
		||||
    foregroundColor: PropTypes.string,
 | 
			
		||||
    accentColor: PropTypes.string,
 | 
			
		||||
    autoPlay: PropTypes.bool,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  state = {
 | 
			
		||||
@ -244,6 +245,14 @@ class Audio extends React.PureComponent {
 | 
			
		||||
    this.setState({ hovered: false });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleLoadedData = () => {
 | 
			
		||||
    const { autoPlay } = this.props;
 | 
			
		||||
 | 
			
		||||
    if (autoPlay) {
 | 
			
		||||
      this.audio.play();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _initAudioContext () {
 | 
			
		||||
    const context  = new AudioContext();
 | 
			
		||||
    const source   = context.createMediaElementSource(this.audio);
 | 
			
		||||
@ -321,7 +330,7 @@ class Audio extends React.PureComponent {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { src, intl, alt, editable } = this.props;
 | 
			
		||||
    const { src, intl, alt, editable, autoPlay } = this.props;
 | 
			
		||||
    const { paused, muted, volume, currentTime, duration, buffer, dragging } = this.state;
 | 
			
		||||
    const progress = (currentTime / duration) * 100;
 | 
			
		||||
 | 
			
		||||
@ -330,10 +339,11 @@ class Audio extends React.PureComponent {
 | 
			
		||||
        <audio
 | 
			
		||||
          src={src}
 | 
			
		||||
          ref={this.setAudioRef}
 | 
			
		||||
          preload='none'
 | 
			
		||||
          preload={autoPlay ? 'auto' : 'none'}
 | 
			
		||||
          onPlay={this.handlePlay}
 | 
			
		||||
          onPause={this.handlePause}
 | 
			
		||||
          onProgress={this.handleProgress}
 | 
			
		||||
          onLoadedData={this.handleLoadedData}
 | 
			
		||||
          crossOrigin='anonymous'
 | 
			
		||||
        />
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,16 +2,26 @@ import React from 'react';
 | 
			
		||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import Audio from 'flavours/glitch/features/audio';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import Icon from 'flavours/glitch/components/icon';
 | 
			
		||||
 | 
			
		||||
export default class AudioModal extends ImmutablePureComponent {
 | 
			
		||||
const mapStateToProps = (state, { status }) => ({
 | 
			
		||||
  account: state.getIn(['accounts', status.get('account')]),
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default @connect(mapStateToProps)
 | 
			
		||||
class AudioModal extends ImmutablePureComponent {
 | 
			
		||||
 | 
			
		||||
  static propTypes = {
 | 
			
		||||
    media: ImmutablePropTypes.map.isRequired,
 | 
			
		||||
    status: ImmutablePropTypes.map,
 | 
			
		||||
    options: PropTypes.shape({
 | 
			
		||||
      autoPlay: PropTypes.bool,
 | 
			
		||||
    }),
 | 
			
		||||
    account: ImmutablePropTypes.map,
 | 
			
		||||
    onClose: PropTypes.func.isRequired,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -27,7 +37,8 @@ export default class AudioModal extends ImmutablePureComponent {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { media, status } = this.props;
 | 
			
		||||
    const { media, status, account } = this.props;
 | 
			
		||||
    const options = this.props.options || {};
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className='modal-root__modal audio-modal'>
 | 
			
		||||
@ -37,10 +48,11 @@ export default class AudioModal extends ImmutablePureComponent {
 | 
			
		||||
            alt={media.get('description')}
 | 
			
		||||
            duration={media.getIn(['meta', 'original', 'duration'], 0)}
 | 
			
		||||
            height={150}
 | 
			
		||||
            poster={media.get('preview_url') || status.getIn(['account', 'avatar_static'])}
 | 
			
		||||
            poster={media.get('preview_url') || account.get('avatar_static')}
 | 
			
		||||
            backgroundColor={media.getIn(['meta', 'colors', 'background'])}
 | 
			
		||||
            foregroundColor={media.getIn(['meta', 'colors', 'foreground'])}
 | 
			
		||||
            accentColor={media.getIn(['meta', 'colors', 'accent'])}
 | 
			
		||||
            autoPlay={options.autoPlay}
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -183,12 +183,13 @@ export const makeGetNotification = () => {
 | 
			
		||||
export const getAccountGallery = createSelector([
 | 
			
		||||
  (state, id) => state.getIn(['timelines', `account:${id}:media`, 'items'], ImmutableList()),
 | 
			
		||||
  state       => state.get('statuses'),
 | 
			
		||||
], (statusIds, statuses) => {
 | 
			
		||||
  (state, id) => state.getIn(['accounts', id]),
 | 
			
		||||
], (statusIds, statuses, account) => {
 | 
			
		||||
  let medias = ImmutableList();
 | 
			
		||||
 | 
			
		||||
  statusIds.forEach(statusId => {
 | 
			
		||||
    const status = statuses.get(statusId);
 | 
			
		||||
    medias = medias.concat(status.get('media_attachments').map(media => media.set('status', status)));
 | 
			
		||||
    medias = medias.concat(status.get('media_attachments').map(media => media.set('status', status).set('account', account)));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return medias;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user