diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2020-07-10 22:09:28 +0200 |
---|---|---|
committer | Thibaut Girka <thib@sitedethib.com> | 2020-07-15 15:48:24 +0200 |
commit | dad313204651dc7aed462b5fc2db314954e9e5e1 (patch) | |
tree | 5735b3cac536cdb68e4fe004d7a282ff89d9dcd2 /app/javascript/flavours/glitch/features | |
parent | 3f60b096b51b000905290d69ea05b874b60fa9e0 (diff) |
[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>
Diffstat (limited to 'app/javascript/flavours/glitch/features')
4 files changed, 76 insertions, 46 deletions
diff --git a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js index b88f23aa4..781bd4e03 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js +++ b/app/javascript/flavours/glitch/features/account_gallery/components/media_item.js @@ -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; - - 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'; - - thumbnail = ( - <div className={classNames('media-gallery__gifv', { autoplay: autoPlay })}> + } 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} + /> + ); + + 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; + + 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> diff --git a/app/javascript/flavours/glitch/features/account_gallery/index.js b/app/javascript/flavours/glitch/features/account_gallery/index.js index f5fe6c930..040741c2a 100644 --- a/app/javascript/flavours/glitch/features/account_gallery/index.js +++ b/app/javascript/flavours/glitch/features/account_gallery/index.js @@ -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')); diff --git a/app/javascript/flavours/glitch/features/audio/index.js b/app/javascript/flavours/glitch/features/audio/index.js index 120a5ce1a..9cb2307fd 100644 --- a/app/javascript/flavours/glitch/features/audio/index.js +++ b/app/javascript/flavours/glitch/features/audio/index.js @@ -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' /> diff --git a/app/javascript/flavours/glitch/features/ui/components/audio_modal.js b/app/javascript/flavours/glitch/features/ui/components/audio_modal.js index f0c3b3bcc..f9d4bb2f3 100644 --- a/app/javascript/flavours/glitch/features/ui/components/audio_modal.js +++ b/app/javascript/flavours/glitch/features/ui/components/audio_modal.js @@ -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> |