2020-09-28 14:29:43 +03:00
import PropTypes from 'prop-types' ;
2023-05-23 18:15:17 +03:00
2020-09-28 14:29:43 +03:00
import { defineMessages , injectIntl } from 'react-intl' ;
2023-05-23 18:15:17 +03:00
import classNames from 'classnames' ;
import ImmutablePropTypes from 'react-immutable-proptypes' ;
import ImmutablePureComponent from 'react-immutable-pure-component' ;
import { connect } from 'react-redux' ;
import { initBoostModal } from 'mastodon/actions/boosts' ;
2020-09-28 14:29:43 +03:00
import { replyCompose } from 'mastodon/actions/compose' ;
import { reblog , favourite , unreblog , unfavourite } from 'mastodon/actions/interactions' ;
import { openModal } from 'mastodon/actions/modal' ;
2023-05-23 18:15:17 +03:00
import { IconButton } from 'mastodon/components/icon_button' ;
import { me , boostModal } from 'mastodon/initial_state' ;
import { makeGetStatus } from 'mastodon/selectors' ;
2020-09-28 14:29:43 +03:00
const messages = defineMessages ( {
reply : { id : 'status.reply' , defaultMessage : 'Reply' } ,
replyAll : { id : 'status.replyAll' , defaultMessage : 'Reply to thread' } ,
reblog : { id : 'status.reblog' , defaultMessage : 'Boost' } ,
reblog _private : { id : 'status.reblog_private' , defaultMessage : 'Boost with original visibility' } ,
cancel _reblog _private : { id : 'status.cancel_reblog_private' , defaultMessage : 'Unboost' } ,
cannot _reblog : { id : 'status.cannot_reblog' , defaultMessage : 'This post cannot be boosted' } ,
2023-07-21 20:09:13 +03:00
favourite : { id : 'status.favourite' , defaultMessage : 'Favorite' } ,
2020-09-28 14:29:43 +03:00
replyConfirm : { id : 'confirmations.reply.confirm' , defaultMessage : 'Reply' } ,
replyMessage : { id : 'confirmations.reply.message' , defaultMessage : 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' } ,
2020-11-27 04:24:11 +02:00
open : { id : 'status.open' , defaultMessage : 'Expand this status' } ,
2020-09-28 14:29:43 +03:00
} ) ;
const makeMapStateToProps = ( ) => {
const getStatus = makeGetStatus ( ) ;
const mapStateToProps = ( state , { statusId } ) => ( {
status : getStatus ( state , { id : statusId } ) ,
askReplyConfirmation : state . getIn ( [ 'compose' , 'text' ] ) . trim ( ) . length !== 0 ,
} ) ;
return mapStateToProps ;
} ;
class Footer extends ImmutablePureComponent {
static contextTypes = {
router : PropTypes . object ,
2022-10-07 11:14:31 +03:00
identity : PropTypes . object ,
2020-09-28 14:29:43 +03:00
} ;
static propTypes = {
statusId : PropTypes . string . isRequired ,
status : ImmutablePropTypes . map . isRequired ,
intl : PropTypes . object . isRequired ,
dispatch : PropTypes . func . isRequired ,
askReplyConfirmation : PropTypes . bool ,
2020-11-27 04:24:11 +02:00
withOpenButton : PropTypes . bool ,
onClose : PropTypes . func ,
2020-09-28 14:29:43 +03:00
} ;
_performReply = ( ) => {
2020-11-27 04:24:11 +02:00
const { dispatch , status , onClose } = this . props ;
const { router } = this . context ;
if ( onClose ) {
2022-02-25 01:51:01 +02:00
onClose ( true ) ;
2020-11-27 04:24:11 +02:00
}
dispatch ( replyCompose ( status , router . history ) ) ;
2020-09-28 14:29:43 +03:00
} ;
handleReplyClick = ( ) => {
2022-10-07 11:14:31 +03:00
const { dispatch , askReplyConfirmation , status , intl } = this . props ;
const { signedIn } = this . context . identity ;
if ( signedIn ) {
if ( askReplyConfirmation ) {
2023-05-25 16:42:37 +03:00
dispatch ( openModal ( {
modalType : 'CONFIRM' ,
modalProps : {
message : intl . formatMessage ( messages . replyMessage ) ,
confirm : intl . formatMessage ( messages . replyConfirm ) ,
onConfirm : this . _performReply ,
} ,
2022-10-07 11:14:31 +03:00
} ) ) ;
} else {
this . _performReply ( ) ;
}
2020-09-28 14:29:43 +03:00
} else {
2023-05-25 16:42:37 +03:00
dispatch ( openModal ( {
modalType : 'INTERACTION' ,
modalProps : {
type : 'reply' ,
accountId : status . getIn ( [ 'account' , 'id' ] ) ,
2023-07-27 17:11:17 +03:00
url : status . get ( 'uri' ) ,
2023-05-25 16:42:37 +03:00
} ,
2022-10-07 11:14:31 +03:00
} ) ) ;
2020-09-28 14:29:43 +03:00
}
} ;
handleFavouriteClick = ( ) => {
const { dispatch , status } = this . props ;
2022-10-07 11:14:31 +03:00
const { signedIn } = this . context . identity ;
if ( signedIn ) {
if ( status . get ( 'favourited' ) ) {
dispatch ( unfavourite ( status ) ) ;
} else {
dispatch ( favourite ( status ) ) ;
}
2020-09-28 14:29:43 +03:00
} else {
2023-05-25 16:42:37 +03:00
dispatch ( openModal ( {
modalType : 'INTERACTION' ,
modalProps : {
type : 'favourite' ,
accountId : status . getIn ( [ 'account' , 'id' ] ) ,
2023-07-27 17:11:17 +03:00
url : status . get ( 'uri' ) ,
2023-05-25 16:42:37 +03:00
} ,
2022-10-07 11:14:31 +03:00
} ) ) ;
2020-09-28 14:29:43 +03:00
}
} ;
2021-02-11 01:53:12 +02:00
_performReblog = ( status , privacy ) => {
const { dispatch } = this . props ;
dispatch ( reblog ( status , privacy ) ) ;
2023-01-30 02:45:35 +02:00
} ;
2020-09-28 14:29:43 +03:00
handleReblogClick = e => {
const { dispatch , status } = this . props ;
2022-10-07 11:14:31 +03:00
const { signedIn } = this . context . identity ;
if ( signedIn ) {
if ( status . get ( 'reblogged' ) ) {
dispatch ( unreblog ( status ) ) ;
} else if ( ( e && e . shiftKey ) || ! boostModal ) {
this . _performReblog ( status ) ;
} else {
dispatch ( initBoostModal ( { status , onReblog : this . _performReblog } ) ) ;
}
2020-09-28 14:29:43 +03:00
} else {
2023-05-25 16:42:37 +03:00
dispatch ( openModal ( {
modalType : 'INTERACTION' ,
modalProps : {
type : 'reblog' ,
accountId : status . getIn ( [ 'account' , 'id' ] ) ,
2023-07-27 17:11:17 +03:00
url : status . get ( 'uri' ) ,
2023-05-25 16:42:37 +03:00
} ,
2022-10-07 11:14:31 +03:00
} ) ) ;
2020-09-28 14:29:43 +03:00
}
} ;
2020-11-27 04:24:11 +02:00
handleOpenClick = e => {
const { router } = this . context ;
if ( e . button !== 0 || ! router ) {
return ;
}
2021-07-25 02:13:46 +03:00
const { status , onClose } = this . props ;
if ( onClose ) {
onClose ( ) ;
}
2020-11-27 04:24:11 +02:00
2021-09-26 06:46:13 +03:00
router . history . push ( ` /@ ${ status . getIn ( [ 'account' , 'acct' ] ) } / ${ status . get ( 'id' ) } ` ) ;
2023-01-30 02:45:35 +02:00
} ;
2020-11-27 04:24:11 +02:00
2020-09-28 14:29:43 +03:00
render ( ) {
2020-11-27 04:24:11 +02:00
const { status , intl , withOpenButton } = this . props ;
2020-09-28 14:29:43 +03:00
const publicStatus = [ 'public' , 'unlisted' ] . includes ( status . get ( 'visibility' ) ) ;
const reblogPrivate = status . getIn ( [ 'account' , 'id' ] ) === me && status . get ( 'visibility' ) === 'private' ;
let replyIcon , replyTitle ;
if ( status . get ( 'in_reply_to_id' , null ) === null ) {
replyIcon = 'reply' ;
replyTitle = intl . formatMessage ( messages . reply ) ;
} else {
replyIcon = 'reply-all' ;
replyTitle = intl . formatMessage ( messages . replyAll ) ;
}
let reblogTitle = '' ;
if ( status . get ( 'reblogged' ) ) {
reblogTitle = intl . formatMessage ( messages . cancel _reblog _private ) ;
} else if ( publicStatus ) {
reblogTitle = intl . formatMessage ( messages . reblog ) ;
} else if ( reblogPrivate ) {
reblogTitle = intl . formatMessage ( messages . reblog _private ) ;
} else {
reblogTitle = intl . formatMessage ( messages . cannot _reblog ) ;
}
return (
< div className = 'picture-in-picture__footer' >
< IconButton className = 'status__action-bar-button' title = { replyTitle } icon = { status . get ( 'in_reply_to_account_id' ) === status . getIn ( [ 'account' , 'id' ] ) ? 'reply' : replyIcon } onClick = { this . handleReplyClick } counter = { status . get ( 'replies_count' ) } obfuscateCount / >
2022-11-08 18:31:32 +02:00
< IconButton className = { classNames ( 'status__action-bar-button' , { reblogPrivate } ) } disabled = { ! publicStatus && ! reblogPrivate } active = { status . get ( 'reblogged' ) } title = { reblogTitle } icon = 'retweet' onClick = { this . handleReblogClick } counter = { status . get ( 'reblogs_count' ) } / >
< IconButton className = 'status__action-bar-button star-icon' animate active = { status . get ( 'favourited' ) } title = { intl . formatMessage ( messages . favourite ) } icon = 'star' onClick = { this . handleFavouriteClick } counter = { status . get ( 'favourites_count' ) } / >
2023-02-13 16:12:14 +02:00
{ withOpenButton && < IconButton className = 'status__action-bar-button' title = { intl . formatMessage ( messages . open ) } icon = 'external-link' onClick = { this . handleOpenClick } href = { ` /@ ${ status . getIn ( [ 'account' , 'acct' ] ) } / ${ status . get ( 'id' ) } ` } / > }
2020-09-28 14:29:43 +03:00
< / div >
) ;
}
}
2023-03-24 04:17:53 +02:00
export default connect ( makeMapStateToProps ) ( injectIntl ( Footer ) ) ;