2022-08-31 02:35:06 -07:00
import classNames from 'clsx' ;
2022-06-07 13:21:18 -07:00
import { Map as ImmutableMap , is } from 'immutable' ;
2022-01-10 14:17:52 -08:00
import PropTypes from 'prop-types' ;
2020-03-27 13:59:38 -07:00
import React from 'react' ;
import ImmutablePropTypes from 'react-immutable-proptypes' ;
import { defineMessages , injectIntl , FormattedMessage } from 'react-intl' ;
2022-01-10 14:17:52 -08:00
import { connect } from 'react-redux' ;
2022-01-10 14:25:06 -08:00
2020-05-28 15:52:07 -07:00
import { getSettings } from 'soapbox/actions/settings' ;
2022-08-22 10:23:37 -07:00
import { getSoapboxConfig } from 'soapbox/actions/soapbox' ;
2022-01-10 14:17:52 -08:00
import Blurhash from 'soapbox/components/blurhash' ;
2020-06-29 21:30:13 -07:00
import Icon from 'soapbox/components/icon' ;
2020-06-09 14:24:31 -07:00
import StillImage from 'soapbox/components/still_image' ;
2022-05-06 05:33:14 -07:00
import { MIMETYPE _ICONS } from 'soapbox/features/compose/components/upload' ;
2022-01-10 14:17:52 -08:00
import { truncateFilename } from 'soapbox/utils/media' ;
2022-01-10 14:25:06 -08:00
2022-01-10 14:01:24 -08:00
import { isIOS } from '../is_mobile' ;
2022-01-10 14:17:52 -08:00
import { isPanoramic , isPortrait , isNonConformingRatio , minimumAspectRatio , maximumAspectRatio } from '../utils/media_aspect_ratio' ;
2022-01-10 14:25:06 -08:00
2022-03-22 08:13:42 -07:00
import { Button , Text } from './ui' ;
2020-03-27 13:59:38 -07:00
2021-05-17 15:38:36 -07:00
const ATTACHMENT _LIMIT = 4 ;
2020-09-06 14:44:19 -07:00
const MAX _FILENAME _LENGTH = 45 ;
2020-03-27 13:59:38 -07:00
const messages = defineMessages ( {
2022-04-25 15:33:29 -07:00
toggle _visible : { id : 'media_gallery.toggle_visible' , defaultMessage : 'Hide' } ,
2020-03-27 13:59:38 -07:00
} ) ;
2020-05-28 18:36:39 -07:00
const mapStateToItemProps = state => ( {
2020-04-28 11:49:39 -07:00
autoPlayGif : getSettings ( state ) . get ( 'autoPlayGif' ) ,
2020-04-17 15:00:25 -07:00
} ) ;
2021-05-30 12:21:52 -07:00
const withinLimits = aspectRatio => {
return aspectRatio >= minimumAspectRatio && aspectRatio <= maximumAspectRatio ;
} ;
const shouldLetterbox = attachment => {
const aspectRatio = attachment . getIn ( [ 'meta' , 'original' , 'aspect' ] ) ;
if ( ! aspectRatio ) return true ;
return ! withinLimits ( aspectRatio ) ;
} ;
2020-05-28 18:36:39 -07:00
@ connect ( mapStateToItemProps )
2020-03-27 13:59:38 -07:00
class Item extends React . PureComponent {
static propTypes = {
2022-03-23 10:14:42 -07:00
attachment : ImmutablePropTypes . record . isRequired ,
2020-03-27 13:59:38 -07:00
standalone : PropTypes . bool ,
index : PropTypes . number . isRequired ,
size : PropTypes . number . isRequired ,
onClick : PropTypes . func . isRequired ,
displayWidth : PropTypes . number ,
visible : PropTypes . bool . isRequired ,
dimensions : PropTypes . object ,
2020-04-17 15:00:25 -07:00
autoPlayGif : PropTypes . bool ,
2021-05-17 15:38:36 -07:00
last : PropTypes . bool ,
total : PropTypes . number ,
2020-03-27 13:59:38 -07:00
} ;
static defaultProps = {
standalone : false ,
index : 0 ,
size : 1 ,
} ;
state = {
loaded : false ,
} ;
handleMouseEnter = ( e ) => {
if ( this . hoverToPlay ( ) ) {
e . target . play ( ) ;
}
}
handleMouseLeave = ( e ) => {
if ( this . hoverToPlay ( ) ) {
e . target . pause ( ) ;
e . target . currentTime = 0 ;
}
}
2020-04-14 14:47:35 -07:00
hoverToPlay ( ) {
2020-04-17 15:00:25 -07:00
const { attachment , autoPlayGif } = this . props ;
2020-06-09 14:24:31 -07:00
return ! autoPlayGif && attachment . get ( 'type' ) === 'gifv' ;
2020-03-27 13:59:38 -07:00
}
handleClick = ( e ) => {
const { index , onClick } = this . props ;
if ( isIOS ( ) && ! e . target . autoPlay ) {
e . target . autoPlay = true ;
e . preventDefault ( ) ;
} else {
if ( e . button === 0 && ! ( e . ctrlKey || e . metaKey ) ) {
2020-06-09 14:24:31 -07:00
if ( this . hoverToPlay ( ) ) {
2020-03-27 13:59:38 -07:00
e . target . pause ( ) ;
e . target . currentTime = 0 ;
}
e . preventDefault ( ) ;
onClick ( index ) ;
}
}
e . stopPropagation ( ) ;
}
handleImageLoad = ( ) => {
this . setState ( { loaded : true } ) ;
}
2021-05-17 20:17:10 -07:00
handleVideoHover = ( { target : video } ) => {
video . playbackRate = 3.0 ;
video . play ( ) ;
}
handleVideoLeave = ( { target : video } ) => {
video . pause ( ) ;
video . currentTime = 0 ;
}
2020-04-14 14:47:35 -07:00
render ( ) {
2021-05-17 15:38:36 -07:00
const { attachment , standalone , visible , dimensions , autoPlayGif , last , total } = this . props ;
2020-03-27 13:59:38 -07:00
2022-08-18 11:23:34 -07:00
let width = 100 ;
2020-03-27 13:59:38 -07:00
let height = '100%' ;
2022-08-18 11:23:34 -07:00
let top = 'auto' ;
let left = 'auto' ;
2020-03-27 13:59:38 -07:00
let bottom = 'auto' ;
2022-08-18 11:23:34 -07:00
let right = 'auto' ;
2020-03-27 13:59:38 -07:00
let float = 'left' ;
let position = 'relative' ;
if ( dimensions ) {
width = dimensions . w ;
height = dimensions . h ;
top = dimensions . t || 'auto' ;
right = dimensions . r || 'auto' ;
bottom = dimensions . b || 'auto' ;
left = dimensions . l || 'auto' ;
float = dimensions . float || 'left' ;
position = dimensions . pos || 'relative' ;
}
let thumbnail = '' ;
if ( attachment . get ( 'type' ) === 'unknown' ) {
2020-09-06 14:44:19 -07:00
const filename = truncateFilename ( attachment . get ( 'remote_url' ) , MAX _FILENAME _LENGTH ) ;
2022-05-06 05:33:14 -07:00
const attachmentIcon = (
< Icon
className = 'h-16 w-16 text-gray-800 dark:text-gray-200'
2022-07-09 09:20:02 -07:00
src = { MIMETYPE _ICONS [ attachment . getIn ( [ 'pleroma' , 'mime_type' ] ) ] || require ( '@tabler/icons/paperclip.svg' ) }
2022-05-06 05:33:14 -07:00
/ >
) ;
2020-03-27 13:59:38 -07:00
return (
< div className = { classNames ( 'media-gallery__item' , { standalone } ) } key = { attachment . get ( 'id' ) } style = { { position , float , left , top , right , bottom , height , width : ` ${ width } % ` } } >
< a className = 'media-gallery__item-thumbnail' href = { attachment . get ( 'remote_url' ) } target = '_blank' style = { { cursor : 'pointer' } } >
2021-07-01 19:50:53 -07:00
< Blurhash hash = { attachment . get ( 'blurhash' ) } className = 'media-gallery__preview' / >
2022-05-06 05:33:14 -07:00
< span className = 'media-gallery__item__icons' > { attachmentIcon } < / s p a n >
2020-09-06 12:08:09 -07:00
< span className = 'media-gallery__filename__label' > { filename } < / s p a n >
2020-03-27 13:59:38 -07:00
< / a >
< / d i v >
) ;
} else if ( attachment . get ( 'type' ) === 'image' ) {
2021-05-12 18:07:59 -07:00
const originalUrl = attachment . get ( 'url' ) ;
2021-05-30 12:21:52 -07:00
const letterboxed = shouldLetterbox ( attachment ) ;
2020-03-27 13:59:38 -07:00
thumbnail = (
< a
2021-05-12 18:07:59 -07:00
className = { classNames ( 'media-gallery__item-thumbnail' , { letterboxed } ) }
2020-03-27 13:59:38 -07:00
href = { attachment . get ( 'remote_url' ) || originalUrl }
onClick = { this . handleClick }
target = '_blank'
>
2022-03-28 16:00:21 -07:00
< StillImage src = { originalUrl } alt = { attachment . get ( 'description' ) } / >
2020-03-27 13:59:38 -07:00
< / a >
) ;
} else if ( attachment . get ( 'type' ) === 'gifv' ) {
2021-08-03 10:10:42 -07:00
const conditionalAttributes = { } ;
2020-03-27 13:59:38 -07:00
if ( isIOS ( ) ) {
2020-04-14 11:44:40 -07:00
conditionalAttributes . playsInline = '1' ;
2020-03-27 13:59:38 -07:00
}
if ( autoPlayGif ) {
2020-04-14 11:44:40 -07:00
conditionalAttributes . autoPlay = '1' ;
2020-03-27 13:59:38 -07:00
}
thumbnail = (
< div className = { classNames ( 'media-gallery__gifv' , { autoplay : autoPlayGif } ) } >
< video
className = 'media-gallery__item-gifv-thumbnail'
aria - label = { attachment . get ( 'description' ) }
title = { attachment . get ( 'description' ) }
role = 'application'
src = { attachment . get ( 'url' ) }
onClick = { this . handleClick }
onMouseEnter = { this . handleMouseEnter }
onMouseLeave = { this . handleMouseLeave }
loop
muted
{ ... conditionalAttributes }
/ >
< span className = 'media-gallery__gifv__label' > GIF < / s p a n >
< / d i v >
) ;
2020-06-29 21:30:13 -07:00
} else if ( attachment . get ( 'type' ) === 'audio' ) {
2021-10-12 11:46:09 -07:00
const ext = attachment . get ( 'url' ) . split ( '.' ) . pop ( ) . toUpperCase ( ) ;
2020-06-29 21:30:13 -07:00
thumbnail = (
< a
className = { classNames ( 'media-gallery__item-thumbnail' ) }
2021-10-12 11:46:09 -07:00
href = { attachment . get ( 'url' ) }
2020-06-29 21:30:13 -07:00
onClick = { this . handleClick }
target = '_blank'
alt = { attachment . get ( 'description' ) }
title = { attachment . get ( 'description' ) }
>
2022-07-26 03:30:51 -07:00
< span className = 'media-gallery__item__icons' > < Icon src = { require ( '@tabler/icons/volume.svg' ) } / > < / s p a n >
2021-10-12 11:46:09 -07:00
< span className = 'media-gallery__file-extension__label' > { ext } < / s p a n >
2020-06-29 21:30:13 -07:00
< / a >
) ;
2021-05-17 20:17:10 -07:00
} else if ( attachment . get ( 'type' ) === 'video' ) {
const ext = attachment . get ( 'url' ) . split ( '.' ) . pop ( ) . toUpperCase ( ) ;
thumbnail = (
< a
className = { classNames ( 'media-gallery__item-thumbnail' ) }
href = { attachment . get ( 'url' ) }
onClick = { this . handleClick }
target = '_blank'
alt = { attachment . get ( 'description' ) }
title = { attachment . get ( 'description' ) }
>
< video
muted
loop
onMouseOver = { this . handleVideoHover }
onMouseOut = { this . handleVideoLeave }
>
< source src = { attachment . get ( 'url' ) } / >
< / v i d e o >
< span className = 'media-gallery__file-extension__label' > { ext } < / s p a n >
< / a >
) ;
2020-03-27 13:59:38 -07:00
}
return (
2020-09-06 15:20:26 -07:00
< div className = { classNames ( 'media-gallery__item' , ` media-gallery__item-- ${ attachment . get ( 'type' ) } ` , { standalone } ) } key = { attachment . get ( 'id' ) } style = { { position , float , left , top , right , bottom , height , width : ` ${ width } % ` } } >
2021-05-17 15:38:36 -07:00
{ last && total > ATTACHMENT _LIMIT && (
< div className = 'media-gallery__item-overflow' >
+ { total - ATTACHMENT _LIMIT + 1 }
< / d i v >
) }
2021-07-01 19:50:53 -07:00
< Blurhash
hash = { attachment . get ( 'blurhash' ) }
className = { classNames ( 'media-gallery__preview' , {
'media-gallery__preview--hidden' : visible && this . state . loaded ,
} ) }
/ >
2020-03-27 13:59:38 -07:00
{ visible && thumbnail }
< / d i v >
) ;
}
}
2022-08-22 10:23:37 -07:00
const mapStateToMediaGalleryProps = state => {
const { links } = getSoapboxConfig ( state ) ;
return {
displayMedia : getSettings ( state ) . get ( 'displayMedia' ) ,
links ,
} ;
} ;
2020-05-28 18:36:39 -07:00
export default @ connect ( mapStateToMediaGalleryProps )
@ injectIntl
2020-03-27 13:59:38 -07:00
class MediaGallery extends React . PureComponent {
static propTypes = {
sensitive : PropTypes . bool ,
standalone : PropTypes . bool ,
media : ImmutablePropTypes . list . isRequired ,
size : PropTypes . object ,
height : PropTypes . number . isRequired ,
onOpenMedia : PropTypes . func . isRequired ,
intl : PropTypes . object . isRequired ,
defaultWidth : PropTypes . number ,
cacheWidth : PropTypes . func ,
visible : PropTypes . bool ,
onToggleVisibility : PropTypes . func ,
2020-05-28 18:36:39 -07:00
displayMedia : PropTypes . string ,
2021-10-08 11:12:38 -07:00
compact : PropTypes . bool ,
2022-08-22 10:23:37 -07:00
links : ImmutablePropTypes . map ,
2020-03-27 13:59:38 -07:00
} ;
static defaultProps = {
standalone : false ,
} ;
state = {
2020-05-28 18:36:39 -07:00
visible : this . props . visible !== undefined ? this . props . visible : ( this . props . displayMedia !== 'hide_all' && ! this . props . sensitive || this . props . displayMedia === 'show_all' ) ,
2020-03-27 13:59:38 -07:00
width : this . props . defaultWidth ,
} ;
2020-07-04 16:41:41 -07:00
componentDidUpdate ( prevProps ) {
const { media , visible , sensitive } = this . props ;
if ( ! is ( media , prevProps . media ) && visible === undefined ) {
this . setState ( { visible : prevProps . displayMedia !== 'hide_all' && ! sensitive || prevProps . displayMedia === 'show_all' } ) ;
} else if ( ! is ( visible , prevProps . visible ) && visible !== undefined ) {
this . setState ( { visible } ) ;
2020-03-27 13:59:38 -07:00
}
}
2022-03-21 11:09:01 -07:00
handleOpen = ( e ) => {
e . stopPropagation ( ) ;
2020-03-27 13:59:38 -07:00
if ( this . props . onToggleVisibility ) {
this . props . onToggleVisibility ( ) ;
} else {
this . setState ( { visible : ! this . state . visible } ) ;
}
}
handleClick = ( index ) => {
this . props . onOpenMedia ( this . props . media , index ) ;
}
handleRef = ( node ) => {
if ( node ) {
// offsetWidth triggers a layout, so only calculate when we need to
if ( this . props . cacheWidth ) this . props . cacheWidth ( node . offsetWidth ) ;
this . setState ( {
width : node . offsetWidth ,
} ) ;
}
}
2020-04-23 10:12:03 -07:00
getSizeDataSingle = ( ) => {
const { media , defaultWidth } = this . props ;
2020-03-27 13:59:38 -07:00
const width = this . state . width || defaultWidth ;
2021-05-12 13:04:31 -07:00
const aspectRatio = media . getIn ( [ 0 , 'meta' , 'original' , 'aspect' ] ) ;
2020-03-27 13:59:38 -07:00
2020-04-23 12:59:43 -07:00
const getHeight = ( ) => {
2022-05-11 10:40:34 -07:00
if ( ! aspectRatio ) return width * 9 / 16 ;
2020-04-23 12:59:43 -07:00
if ( isPanoramic ( aspectRatio ) ) return Math . floor ( width / maximumAspectRatio ) ;
2022-08-18 11:23:34 -07:00
if ( isPortrait ( aspectRatio ) ) return Math . floor ( width / minimumAspectRatio ) ;
2020-04-23 12:59:43 -07:00
return Math . floor ( width / aspectRatio ) ;
} ;
2020-04-23 10:12:03 -07:00
return ImmutableMap ( {
2020-04-23 12:59:43 -07:00
style : { height : getHeight ( ) } ,
2020-04-23 10:12:03 -07:00
itemsDimensions : [ ] ,
size : 1 ,
width ,
} ) ;
}
getSizeDataMultiple = size => {
const { media , defaultWidth } = this . props ;
const width = this . state . width || defaultWidth ;
2020-03-27 13:59:38 -07:00
const panoSize = Math . floor ( width / maximumAspectRatio ) ;
const panoSize _px = ` ${ Math . floor ( width / maximumAspectRatio ) } px ` ;
2020-04-23 10:12:03 -07:00
const style = { } ;
2020-03-27 13:59:38 -07:00
let itemsDimensions = [ ] ;
2020-04-23 10:12:03 -07:00
const ratios = Array ( size ) . fill ( ) . map ( ( _ , i ) =>
2021-05-12 13:04:31 -07:00
media . getIn ( [ i , 'meta' , 'original' , 'aspect' ] ) ,
2020-04-23 10:12:03 -07:00
) ;
2020-03-27 13:59:38 -07:00
2020-04-23 10:12:03 -07:00
const [ ar1 , ar2 , ar3 , ar4 ] = ratios ;
if ( size === 2 ) {
if ( isPortrait ( ar1 ) && isPortrait ( ar2 ) ) {
style . height = width - ( width / maximumAspectRatio ) ;
} else if ( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) ) {
style . height = panoSize * 2 ;
} else if (
( isPanoramic ( ar1 ) && isPortrait ( ar2 ) ) ||
( isPortrait ( ar1 ) && isPanoramic ( ar2 ) ) ||
( isPanoramic ( ar1 ) && isNonConformingRatio ( ar2 ) ) ||
( isNonConformingRatio ( ar1 ) && isPanoramic ( ar2 ) )
) {
style . height = ( width * 0.6 ) + ( width / maximumAspectRatio ) ;
2020-03-27 13:59:38 -07:00
} else {
2020-04-23 10:12:03 -07:00
style . height = width / 2 ;
2020-03-27 13:59:38 -07:00
}
2020-04-23 10:12:03 -07:00
//
if ( isPortrait ( ar1 ) && isPortrait ( ar2 ) ) {
itemsDimensions = [
{ w : 50 , h : '100%' , r : '2px' } ,
{ w : 50 , h : '100%' , l : '2px' } ,
] ;
} else if ( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) ) {
itemsDimensions = [
{ w : 100 , h : panoSize _px , b : '2px' } ,
{ w : 100 , h : panoSize _px , t : '2px' } ,
] ;
} else if (
( isPanoramic ( ar1 ) && isPortrait ( ar2 ) ) ||
( isPanoramic ( ar1 ) && isNonConformingRatio ( ar2 ) )
) {
itemsDimensions = [
{ w : 100 , h : ` ${ ( width / maximumAspectRatio ) } px ` , b : '2px' } ,
{ w : 100 , h : ` ${ ( width * 0.6 ) } px ` , t : '2px' } ,
] ;
} else if (
( isPortrait ( ar1 ) && isPanoramic ( ar2 ) ) ||
( isNonConformingRatio ( ar1 ) && isPanoramic ( ar2 ) )
) {
itemsDimensions = [
{ w : 100 , h : ` ${ ( width * 0.6 ) } px ` , b : '2px' } ,
{ w : 100 , h : ` ${ ( width / maximumAspectRatio ) } px ` , t : '2px' } ,
] ;
} else {
itemsDimensions = [
{ w : 50 , h : '100%' , r : '2px' } ,
{ w : 50 , h : '100%' , l : '2px' } ,
] ;
}
} else if ( size === 3 ) {
if ( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isPanoramic ( ar3 ) ) {
style . height = panoSize * 3 ;
} else if ( isPortrait ( ar1 ) && isPortrait ( ar2 ) && isPortrait ( ar3 ) ) {
style . height = Math . floor ( width / minimumAspectRatio ) ;
} else {
style . height = width ;
}
2020-03-27 13:59:38 -07:00
2020-04-23 10:12:03 -07:00
//
if ( isPanoramic ( ar1 ) && isNonConformingRatio ( ar2 ) && isNonConformingRatio ( ar3 ) ) {
itemsDimensions = [
{ w : 100 , h : '50%' , b : '2px' } ,
{ w : 50 , h : '50%' , t : '2px' , r : '2px' } ,
{ w : 50 , h : '50%' , t : '2px' , l : '2px' } ,
] ;
} else if ( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isPanoramic ( ar3 ) ) {
itemsDimensions = [
{ w : 100 , h : panoSize _px , b : '4px' } ,
{ w : 100 , h : panoSize _px } ,
{ w : 100 , h : panoSize _px , t : '4px' } ,
] ;
} else if ( isPortrait ( ar1 ) && isNonConformingRatio ( ar2 ) && isNonConformingRatio ( ar3 ) ) {
itemsDimensions = [
{ w : 50 , h : '100%' , r : '2px' } ,
{ w : 50 , h : '50%' , b : '2px' , l : '2px' } ,
{ w : 50 , h : '50%' , t : '2px' , l : '2px' } ,
] ;
} else if ( isNonConformingRatio ( ar1 ) && isNonConformingRatio ( ar2 ) && isPortrait ( ar3 ) ) {
itemsDimensions = [
{ w : 50 , h : '50%' , b : '2px' , r : '2px' } ,
{ w : 50 , h : '50%' , l : '-2px' , b : '-2px' , pos : 'absolute' , float : 'none' } ,
{ w : 50 , h : '100%' , r : '-2px' , t : '0px' , b : '0px' , pos : 'absolute' , float : 'none' } ,
] ;
} else if (
( isNonConformingRatio ( ar1 ) && isPortrait ( ar2 ) && isNonConformingRatio ( ar3 ) ) ||
( isPortrait ( ar1 ) && isPortrait ( ar2 ) && isPortrait ( ar3 ) )
) {
itemsDimensions = [
{ w : 50 , h : '50%' , b : '2px' , r : '2px' } ,
{ w : 50 , h : '100%' , l : '2px' , float : 'right' } ,
{ w : 50 , h : '50%' , t : '2px' , r : '2px' } ,
] ;
} else if (
( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isNonConformingRatio ( ar3 ) ) ||
( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isPortrait ( ar3 ) )
) {
itemsDimensions = [
{ w : 50 , h : panoSize _px , b : '2px' , r : '2px' } ,
{ w : 50 , h : panoSize _px , b : '2px' , l : '2px' } ,
{ w : 100 , h : ` ${ width - panoSize } px ` , t : '2px' } ,
] ;
} else if (
( isNonConformingRatio ( ar1 ) && isPanoramic ( ar2 ) && isPanoramic ( ar3 ) ) ||
( isPortrait ( ar1 ) && isPanoramic ( ar2 ) && isPanoramic ( ar3 ) )
) {
itemsDimensions = [
{ w : 100 , h : ` ${ width - panoSize } px ` , b : '2px' } ,
{ w : 50 , h : panoSize _px , t : '2px' , r : '2px' } ,
{ w : 50 , h : panoSize _px , t : '2px' , l : '2px' } ,
] ;
} else {
itemsDimensions = [
{ w : 50 , h : '50%' , b : '2px' , r : '2px' } ,
{ w : 50 , h : '50%' , b : '2px' , l : '2px' } ,
{ w : 100 , h : '50%' , t : '2px' } ,
] ;
}
2020-06-07 12:40:54 -07:00
} else if ( size >= 4 ) {
2020-04-23 10:12:03 -07:00
if (
( isPortrait ( ar1 ) && isPortrait ( ar2 ) && isPortrait ( ar3 ) && isPortrait ( ar4 ) ) ||
( isPortrait ( ar1 ) && isPortrait ( ar2 ) && isPortrait ( ar3 ) && isNonConformingRatio ( ar4 ) ) ||
( isPortrait ( ar1 ) && isPortrait ( ar2 ) && isNonConformingRatio ( ar3 ) && isPortrait ( ar4 ) ) ||
( isPortrait ( ar1 ) && isNonConformingRatio ( ar2 ) && isPortrait ( ar3 ) && isPortrait ( ar4 ) ) ||
( isNonConformingRatio ( ar1 ) && isPortrait ( ar2 ) && isPortrait ( ar3 ) && isPortrait ( ar4 ) )
) {
style . height = Math . floor ( width / minimumAspectRatio ) ;
} else if ( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isPanoramic ( ar3 ) && isPanoramic ( ar4 ) ) {
style . height = panoSize * 2 ;
} else if (
( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isNonConformingRatio ( ar3 ) && isNonConformingRatio ( ar4 ) ) ||
( isNonConformingRatio ( ar1 ) && isNonConformingRatio ( ar2 ) && isPanoramic ( ar3 ) && isPanoramic ( ar4 ) )
) {
style . height = panoSize + ( width / 2 ) ;
} else {
style . height = width ;
}
2020-03-27 13:59:38 -07:00
2020-04-23 10:12:03 -07:00
//
if ( isPanoramic ( ar1 ) && isPanoramic ( ar2 ) && isNonConformingRatio ( ar3 ) && isNonConformingRatio ( ar4 ) ) {
itemsDimensions = [
{ w : 50 , h : panoSize _px , b : '2px' , r : '2px' } ,
{ w : 50 , h : panoSize _px , b : '2px' , l : '2px' } ,
{ w : 50 , h : ` ${ ( width / 2 ) } px ` , t : '2px' , r : '2px' } ,
{ w : 50 , h : ` ${ ( width / 2 ) } px ` , t : '2px' , l : '2px' } ,
] ;
} else if ( isNonConformingRatio ( ar1 ) && isNonConformingRatio ( ar2 ) && isPanoramic ( ar3 ) && isPanoramic ( ar4 ) ) {
itemsDimensions = [
{ w : 50 , h : ` ${ ( width / 2 ) } px ` , b : '2px' , r : '2px' } ,
{ w : 50 , h : ` ${ ( width / 2 ) } px ` , b : '2px' , l : '2px' } ,
{ w : 50 , h : panoSize _px , t : '2px' , r : '2px' } ,
{ w : 50 , h : panoSize _px , t : '2px' , l : '2px' } ,
] ;
} else if (
( isPortrait ( ar1 ) && isNonConformingRatio ( ar2 ) && isNonConformingRatio ( ar3 ) && isNonConformingRatio ( ar4 ) ) ||
( isPortrait ( ar1 ) && isPanoramic ( ar2 ) && isPanoramic ( ar3 ) && isPanoramic ( ar4 ) )
) {
itemsDimensions = [
{ w : 67 , h : '100%' , r : '2px' } ,
{ w : 33 , h : '33%' , b : '4px' , l : '2px' } ,
{ w : 33 , h : '33%' , l : '2px' } ,
{ w : 33 , h : '33%' , t : '4px' , l : '2px' } ,
] ;
} else {
itemsDimensions = [
{ w : 50 , h : '50%' , b : '2px' , r : '2px' } ,
{ w : 50 , h : '50%' , b : '2px' , l : '2px' } ,
{ w : 50 , h : '50%' , t : '2px' , r : '2px' } ,
{ w : 50 , h : '50%' , t : '2px' , l : '2px' } ,
] ;
2020-03-27 13:59:38 -07:00
}
}
2020-04-23 09:19:12 -07:00
return ImmutableMap ( {
style ,
itemsDimensions ,
2020-04-23 10:12:03 -07:00
size : size ,
width ,
} ) ;
}
getSizeData = size => {
const { height , defaultWidth } = this . props ;
const width = this . state . width || defaultWidth ;
if ( width ) {
if ( size === 1 ) return this . getSizeDataSingle ( ) ;
2022-08-18 11:23:34 -07:00
if ( size > 1 ) return this . getSizeDataMultiple ( size ) ;
2020-04-23 10:12:03 -07:00
}
// Default
return ImmutableMap ( {
style : { height } ,
itemsDimensions : [ ] ,
2020-04-23 09:19:12 -07:00
size ,
width ,
} ) ;
}
render ( ) {
2022-08-22 10:23:37 -07:00
const { media , intl , sensitive , compact , inReview , links } = this . props ;
2020-04-23 09:19:12 -07:00
const { visible } = this . state ;
2020-04-23 10:12:03 -07:00
const sizeData = this . getSizeData ( media . size ) ;
2020-04-23 09:19:12 -07:00
2021-08-03 10:10:42 -07:00
const children = media . take ( ATTACHMENT _LIMIT ) . map ( ( attachment , i ) => (
2020-03-27 13:59:38 -07:00
< Item
key = { attachment . get ( 'id' ) }
onClick = { this . handleClick }
attachment = { attachment }
index = { i }
2020-04-23 09:19:12 -07:00
size = { sizeData . get ( 'size' ) }
displayWidth = { sizeData . get ( 'width' ) }
2020-03-27 13:59:38 -07:00
visible = { visible }
2020-04-23 09:19:12 -07:00
dimensions = { sizeData . get ( 'itemsDimensions' ) [ i ] }
2021-05-17 15:38:36 -07:00
last = { i === ATTACHMENT _LIMIT - 1 }
total = { media . size }
2020-03-27 13:59:38 -07:00
/ >
) ) ;
2022-08-22 10:18:52 -07:00
let warning , summary ;
2021-08-03 10:10:42 -07:00
2021-10-15 16:30:14 -07:00
if ( sensitive ) {
warning = < FormattedMessage id = 'status.sensitive_warning' defaultMessage = 'Sensitive content' / > ;
2022-08-18 11:23:34 -07:00
} else if ( inReview ) {
2022-08-22 10:18:52 -07:00
warning = < FormattedMessage id = 'status.in_review_warning' defaultMessage = 'Content Under Review' / > ;
2020-03-27 13:59:38 -07:00
} else {
2021-10-15 16:30:14 -07:00
warning = < FormattedMessage id = 'status.media_hidden' defaultMessage = 'Media hidden' / > ;
2020-03-27 13:59:38 -07:00
}
2022-08-22 10:18:52 -07:00
if ( inReview ) {
summary = < FormattedMessage id = 'status.in_review_summary.summary' defaultMessage = 'This Truth has been sent to Moderation for review and is only visible to you.' / > ;
} else {
summary = < FormattedMessage id = 'status.sensitive_warning.subtitle' defaultMessage = 'This content may not be suitable for all audiences.' / > ;
}
2020-03-27 13:59:38 -07:00
return (
2021-10-08 11:12:38 -07:00
< div className = { classNames ( 'media-gallery' , { 'media-gallery--compact' : compact } ) } style = { sizeData . get ( 'style' ) } ref = { this . handleRef } >
2022-08-18 11:23:34 -07:00
< div
className = { classNames ( {
'absolute z-40' : true ,
'inset-0' : ! visible && ! compact ,
'left-1 top-1' : visible || compact ,
} ) }
>
2022-08-22 10:58:06 -07:00
{ ( sensitive || inReview ) && (
2022-03-06 14:39:13 -08:00
( visible || compact ) ? (
2022-04-04 13:51:29 -07:00
< Button
text = { intl . formatMessage ( messages . toggle _visible ) }
2022-07-09 09:20:02 -07:00
icon = { visible ? require ( '@tabler/icons/eye-off.svg' ) : require ( '@tabler/icons/eye.svg' ) }
2022-03-06 14:39:13 -08:00
onClick = { this . handleOpen }
2022-04-04 13:51:29 -07:00
theme = 'transparent'
size = 'sm'
2022-03-06 14:39:13 -08:00
/ >
2021-10-15 16:30:14 -07:00
) : (
2022-08-22 10:18:52 -07:00
< div
onClick = { ( e ) => e . stopPropagation ( ) }
2022-08-18 11:23:34 -07:00
className = {
classNames ( {
2022-08-22 10:18:52 -07:00
'cursor-default backdrop-blur-sm rounded-lg w-full h-full border-0 flex items-center justify-center' : true ,
2022-08-18 11:23:34 -07:00
'bg-gray-800/75' : ! inReview ,
'bg-danger-600/75' : inReview ,
} )
}
>
2022-08-22 10:18:52 -07:00
< div className = 'text-center w-3/4 mx-auto space-y-4' >
2022-03-22 08:13:42 -07:00
< div className = 'space-y-1' >
2022-08-18 11:23:34 -07:00
< Text theme = 'white' weight = 'semibold' > { warning } < / T e x t >
2022-08-22 10:18:52 -07:00
< Text theme = 'white' size = 'sm' weight = 'medium' >
{ summary }
2022-08-22 10:23:37 -07:00
{ links . get ( 'support' ) && (
< >
{ ' ' }
< FormattedMessage
id = 'status.in_review_summary.contact'
defaultMessage = 'If you believe this is in error please {link}.'
values = { {
link : (
< a
className = 'underline text-inherit'
href = { links . get ( 'support' ) }
>
< FormattedMessage
id = 'status.in_review_summary.link'
defaultMessage = 'Contact Support'
/ >
< / a >
) ,
} }
/ >
< / >
) }
2022-03-22 08:13:42 -07:00
< / T e x t >
< / d i v >
2022-08-18 11:23:34 -07:00
< Button
type = 'button'
theme = 'outline'
size = 'sm'
icon = { require ( '@tabler/icons/eye.svg' ) }
2022-08-22 10:18:52 -07:00
onClick = { this . handleOpen }
2022-08-18 11:23:34 -07:00
>
2022-05-24 03:24:26 -07:00
< FormattedMessage id = 'status.sensitive_warning.action' defaultMessage = 'Show content' / >
2022-03-22 08:13:42 -07:00
< / B u t t o n >
< / d i v >
2022-08-22 10:18:52 -07:00
< / d i v >
2021-10-15 16:30:14 -07:00
)
) }
2020-03-27 13:59:38 -07:00
< / d i v >
{ children }
< / d i v >
) ;
}
}