2020-08-17 21:07:16 +01:00
import React from 'react'
2020-08-17 21:59:29 +01:00
import PropTypes from 'prop-types'
2020-08-17 21:39:25 +01:00
import { connect } from 'react-redux'
2020-03-04 03:45:16 +00:00
import { NavLink } from 'react-router-dom'
2020-05-02 07:25:55 +01:00
import { defineMessages , injectIntl , FormattedMessage } from 'react-intl'
2020-04-24 04:17:27 +01:00
import ImmutablePropTypes from 'react-immutable-proptypes'
2020-03-04 03:45:16 +00:00
import ImmutablePureComponent from 'react-immutable-pure-component'
2020-05-02 07:25:55 +01:00
import {
favorite ,
unfavorite ,
} from '../actions/interactions'
import { replyCompose } from '../actions/compose'
import { openModal } from '../actions/modal'
import { openPopover } from '../actions/popover'
import { makeGetStatus } from '../selectors'
2020-05-05 06:16:01 +01:00
import {
CX ,
} from '../constants'
2020-05-02 07:25:55 +01:00
import { me } from '../initial_state'
2020-03-04 03:45:16 +00:00
import Avatar from './avatar'
import Button from './button'
2020-04-24 04:17:27 +01:00
import CommentHeader from './comment_header'
2020-03-08 23:02:28 +00:00
import StatusContent from './status_content'
2020-05-02 07:25:55 +01:00
import StatusMedia from './status_media'
import { defaultMediaVisibility } from './status'
2020-04-24 04:17:27 +01:00
import Text from './text'
2020-03-04 03:45:16 +00:00
class Comment extends ImmutablePureComponent {
2020-05-15 04:17:31 +01:00
static contextTypes = {
router : PropTypes . object ,
}
2020-05-02 07:25:55 +01:00
state = {
showMedia : defaultMediaVisibility ( this . props . status ) ,
2020-05-04 19:44:37 +01:00
statusId : undefined ,
height : undefined ,
2020-05-02 07:25:55 +01:00
}
2020-05-07 00:40:54 +01:00
handleClick = ( ) => {
//
}
2020-05-02 07:25:55 +01:00
handleOnReply = ( ) => {
2020-05-15 04:17:31 +01:00
this . props . onReply ( this . props . status , this . context . router )
2020-05-02 07:25:55 +01:00
}
handleOnFavorite = ( ) => {
this . props . onFavorite ( this . props . status )
}
handleOnOpenStatusOptions = ( ) => {
2020-05-07 00:40:54 +01:00
this . props . onOpenStatusOptions ( this . moreNode , this . props . status )
}
2020-06-05 14:14:09 +01:00
handleToggleMediaVisibility = ( ) => {
this . setState ( { showMedia : ! this . state . showMedia } )
}
2020-05-07 00:40:54 +01:00
setMoreNode = ( c ) => {
this . moreNode = c
2020-05-02 07:25:55 +01:00
}
2020-03-04 03:45:16 +00:00
render ( ) {
2020-04-24 04:17:27 +01:00
const {
indent ,
intl ,
status ,
2020-05-02 07:25:55 +01:00
isHidden ,
2020-05-05 06:16:01 +01:00
isHighlighted ,
ancestorAccountId ,
2020-04-24 04:17:27 +01:00
} = this . props
2020-03-04 03:45:16 +00:00
2020-05-02 07:25:55 +01:00
if ( isHidden ) {
return (
< div tabIndex = '0' >
{ status . getIn ( [ 'account' , 'display_name' ] ) || status . getIn ( [ 'account' , 'username' ] ) }
{ status . get ( 'content' ) }
< / d i v >
)
}
2020-04-08 02:06:59 +01:00
const style = {
2020-05-04 19:44:37 +01:00
paddingLeft : ` ${ indent * 42 } px ` ,
2020-04-08 02:06:59 +01:00
}
2020-05-05 06:16:01 +01:00
const contentClasses = CX ( {
2020-08-18 21:49:11 +01:00
d : 1 ,
2020-05-05 06:16:01 +01:00
px10 : 1 ,
pt5 : 1 ,
pb10 : 1 ,
radiusSmall : 1 ,
bgSubtle : ! isHighlighted ,
highlightedComment : isHighlighted ,
} )
2020-03-04 03:45:16 +00:00
return (
2020-08-18 21:49:11 +01:00
< div className = { [ _s . d , _s . px15 , _s . mb10 , _s . py5 ] . join ( ' ' ) } data - comment = { status . get ( 'id' ) } >
< div className = { _s . d } style = { style } >
2020-03-08 23:02:28 +00:00
2020-08-18 21:49:11 +01:00
< div className = { [ _s . d , _s . flexRow ] . join ( ' ' ) } >
2020-03-08 23:02:28 +00:00
< NavLink
to = { ` / ${ status . getIn ( [ 'account' , 'acct' ] ) } ` }
title = { status . getIn ( [ 'account' , 'acct' ] ) }
2020-08-18 21:49:11 +01:00
className = { [ _s . d , _s . mr10 , _s . pt5 ] . join ( ' ' ) }
2020-03-08 23:02:28 +00:00
>
< Avatar account = { status . get ( 'account' ) } size = { 32 } / >
< / N a v L i n k >
2020-08-18 21:49:11 +01:00
< div className = { [ _s . d , _s . flexShrink1 , _s . maxW100PC42PX ] . join ( ' ' ) } >
2020-05-05 06:16:01 +01:00
< div className = { contentClasses } >
2020-05-04 19:44:37 +01:00
< CommentHeader
2020-05-05 06:16:01 +01:00
ancestorAccountId = { ancestorAccountId }
2020-05-04 19:44:37 +01:00
status = { status }
2020-05-07 00:40:54 +01:00
onOpenRevisions = { this . props . onOpenStatusRevisionsPopover }
2020-05-04 19:44:37 +01:00
onOpenLikes = { this . props . onOpenLikes }
onOpenReposts = { this . props . onOpenReposts }
/ >
2020-04-24 04:17:27 +01:00
< StatusContent
status = { status }
onClick = { this . handleClick }
isComment
collapsable
/ >
2020-08-18 21:49:11 +01:00
< div className = { [ _s . d , _s . mt5 ] . join ( ' ' ) } >
2020-05-02 07:25:55 +01:00
< StatusMedia
isComment
status = { status }
onOpenMedia = { this . props . onOpenMedia }
cacheWidth = { this . props . cacheMediaWidth }
defaultWidth = { this . props . cachedMediaWidth }
visible = { this . state . showMedia }
onToggleVisibility = { this . handleToggleMediaVisibility }
width = { this . props . cachedMediaWidth }
/ >
< / d i v >
2020-03-08 23:02:28 +00:00
< / d i v >
2020-08-18 21:49:11 +01:00
< div className = { [ _s . d , _s . flexRow , _s . mt5 ] . join ( ' ' ) } >
2020-05-02 07:25:55 +01:00
< CommentButton
2020-05-04 19:44:37 +01:00
title = { intl . formatMessage ( status . get ( 'favourited' ) ? messages . unlike : messages . like ) }
2020-05-02 07:25:55 +01:00
onClick = { this . handleOnFavorite }
/ >
< CommentButton
title = { intl . formatMessage ( messages . reply ) }
onClick = { this . handleOnReply }
/ >
2020-05-07 00:40:54 +01:00
< div ref = { this . setMoreNode } >
< CommentButton
title = '···'
onClick = { this . handleOnOpenStatusOptions }
/ >
< / d i v >
2020-03-08 23:02:28 +00:00
< / d i v >
2020-04-24 04:17:27 +01:00
2020-03-08 23:02:28 +00:00
< / d i v >
< / d i v >
2020-03-04 03:45:16 +00:00
2020-03-08 23:02:28 +00:00
< / d i v >
2020-03-04 03:45:16 +00:00
< / d i v >
)
}
}
2020-04-24 04:17:27 +01:00
2020-08-17 21:07:16 +01:00
class CommentButton extends React . PureComponent {
2020-04-24 04:17:27 +01:00
render ( ) {
const { onClick , title } = this . props
return (
< Button
isText
radiusSmall
backgroundColor = 'none'
color = 'tertiary'
2020-04-29 23:32:49 +01:00
className = { [ _s . px5 , _s . bgSubtle _onHover , _s . py2 , _s . mr5 ] . join ( ' ' ) }
2020-04-24 04:17:27 +01:00
onClick = { onClick }
>
< Text size = 'extraSmall' color = 'inherit' weight = 'bold' >
{ title }
< / T e x t >
< / B u t t o n >
)
}
2020-08-18 01:57:35 +01:00
}
2020-08-19 01:22:15 +01:00
CommentButton . propTypes = {
onClick : PropTypes . func . isRequired ,
title : PropTypes . string . isRequired ,
}
2020-08-18 01:57:35 +01:00
const messages = defineMessages ( {
reply : { id : 'status.reply' , defaultMessage : 'Reply' } ,
like : { id : 'status.like' , defaultMessage : 'Like' } ,
unlike : { id : 'status.unlike' , defaultMessage : 'Unlike' } ,
} )
const makeMapStateToProps = ( state , props ) => ( {
status : makeGetStatus ( ) ( state , props )
} )
const mapDispatchToProps = ( dispatch ) => ( {
onReply ( status , router ) {
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
dispatch ( ( _ , getState ) => {
const state = getState ( ) ;
if ( state . getIn ( [ 'compose' , 'text' ] ) . trim ( ) . length !== 0 ) {
dispatch ( openModal ( 'CONFIRM' , {
message : < FormattedMessage id = 'confirmations.reply.message' defaultMessage = 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' / > ,
confirm : < FormattedMessage id = 'confirmations.reply.confirm' defaultMessage = 'Reply' / > ,
onConfirm : ( ) => dispatch ( replyCompose ( status , router ) ) ,
} ) )
} else {
dispatch ( replyCompose ( status , router , true ) )
}
} )
} ,
onFavorite ( status ) {
if ( ! me ) return dispatch ( openModal ( 'UNAUTHORIZED' ) )
if ( status . get ( 'favourited' ) ) {
dispatch ( unfavorite ( status ) )
} else {
dispatch ( favorite ( status ) )
}
} ,
onOpenStatusOptions ( targetRef , status ) {
dispatch ( openPopover ( 'STATUS_OPTIONS' , {
targetRef ,
status ,
position : 'top' ,
} ) )
} ,
onOpenLikes ( status ) {
dispatch ( openModal ( 'STATUS_LIKES' , { status } ) )
} ,
onOpenReposts ( status ) {
dispatch ( openModal ( 'STATUS_REPOSTS' , { status } ) )
} ,
onOpenStatusRevisionsPopover ( status ) {
dispatch ( openModal ( 'STATUS_REVISIONS' , {
status ,
} ) )
} ,
onOpenMedia ( media , index ) {
dispatch ( openModal ( 'MEDIA' , { media , index } ) ) ;
} ,
} )
Comment . propTypes = {
indent : PropTypes . number ,
intl : PropTypes . object . isRequired ,
ancestorAccountId : PropTypes . string . isRequired ,
status : ImmutablePropTypes . map . isRequired ,
isHidden : PropTypes . bool ,
isIntersecting : PropTypes . bool ,
isHighlighted : PropTypes . bool ,
onReply : PropTypes . func . isRequired ,
onFavorite : PropTypes . func . isRequired ,
onOpenStatusOptions : PropTypes . func . isRequired ,
onOpenLikes : PropTypes . func . isRequired ,
onOpenReposts : PropTypes . func . isRequired ,
onOpenStatusRevisionsPopover : PropTypes . func . isRequired ,
onOpenMedia : PropTypes . func . isRequired
}
export default injectIntl ( connect ( makeMapStateToProps , mapDispatchToProps ) ( Comment ) )