import PropTypes from 'prop-types'; import classNames from 'classnames'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import AudiotrackIcon from 'mastodon/../material-icons/400-24px/music_note.svg?react'; import PlayArrowIcon from 'mastodon/../material-icons/400-24px/play_arrow.svg?react'; import VisibilityOffIcon from 'mastodon/../material-icons/400-24px/visibility_off.svg?react'; import { Blurhash } from 'mastodon/components/blurhash'; import { Icon } from 'mastodon/components/icon'; import { autoPlayGif, displayMedia, useBlurhash } from 'mastodon/initial_state'; export default class MediaItem extends ImmutablePureComponent { static propTypes = { attachment: ImmutablePropTypes.map.isRequired, displayWidth: PropTypes.number.isRequired, onOpenMedia: PropTypes.func.isRequired, }; state = { visible: displayMedia !== 'hide_all' && !this.props.attachment.getIn(['status', 'sensitive']) || displayMedia === 'show_all', loaded: false, }; handleImageLoad = () => { this.setState({ loaded: true }); }; handleMouseEnter = e => { if (this.hoverToPlay()) { e.target.play(); } }; handleMouseLeave = e => { if (this.hoverToPlay()) { e.target.pause(); e.target.currentTime = 0; } }; hoverToPlay () { return !autoPlayGif && ['gifv', 'video'].indexOf(this.props.attachment.get('type')) !== -1; } handleClick = e => { if (e.button === 0 && !(e.ctrlKey || e.metaKey)) { e.preventDefault(); if (this.state.visible) { this.props.onOpenMedia(this.props.attachment); } else { this.setState({ visible: true }); } } }; render () { const { attachment, displayWidth } = this.props; const { visible, loaded } = this.state; 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'); let thumbnail, label, icon, content; if (!visible) { icon = ( ); } else { if (['audio', 'video'].includes(attachment.get('type'))) { content = ( {attachment.get('description')} ); if (attachment.get('type') === 'audio') { label = ; } else { label = ; } } 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 = ( {attachment.get('description')} ); } else if (attachment.get('type') === 'gifv') { content = (