2019-08-30 08:14:36 +10:00
import React from 'react' ;
import ImmutablePureComponent from 'react-immutable-pure-component' ;
import ImmutablePropTypes from 'react-immutable-proptypes' ;
import PropTypes from 'prop-types' ;
import { connect } from 'react-redux' ;
import { makeGetAccount } from 'mastodon/selectors' ;
import Avatar from 'mastodon/components/avatar' ;
import DisplayName from 'mastodon/components/display_name' ;
2022-11-14 07:10:20 +11:00
import { Link } from 'react-router-dom' ;
2022-03-07 21:38:52 +11:00
import Button from 'mastodon/components/button' ;
2019-08-30 08:14:36 +10:00
import { FormattedMessage , injectIntl , defineMessages } from 'react-intl' ;
import { autoPlayGif , me , unfollowModal } from 'mastodon/initial_state' ;
2020-07-06 22:27:32 +10:00
import ShortNumber from 'mastodon/components/short_number' ;
import {
followAccount ,
unfollowAccount ,
unblockAccount ,
unmuteAccount ,
} from 'mastodon/actions/accounts' ;
2019-08-30 08:14:36 +10:00
import { openModal } from 'mastodon/actions/modal' ;
2022-03-07 21:38:52 +11:00
import classNames from 'classnames' ;
2019-08-30 08:14:36 +10:00
const messages = defineMessages ( {
unfollow : { id : 'account.unfollow' , defaultMessage : 'Unfollow' } ,
2022-03-07 21:38:52 +11:00
follow : { id : 'account.follow' , defaultMessage : 'Follow' } ,
2022-10-19 09:12:55 +11:00
cancel _follow _request : { id : 'account.cancel_follow_request' , defaultMessage : 'Withdraw follow request' } ,
2022-11-04 02:05:39 +11:00
cancelFollowRequestConfirm : { id : 'confirmations.cancel_follow_request.confirm' , defaultMessage : 'Withdraw request' } ,
2022-03-07 21:38:52 +11:00
requested : { id : 'account.requested' , defaultMessage : 'Awaiting approval. Click to cancel follow request' } ,
unblock : { id : 'account.unblock_short' , defaultMessage : 'Unblock' } ,
unmute : { id : 'account.unmute_short' , defaultMessage : 'Unmute' } ,
unfollowConfirm : { id : 'confirmations.unfollow.confirm' , defaultMessage : 'Unfollow' } ,
edit _profile : { id : 'account.edit_profile' , defaultMessage : 'Edit profile' } ,
2019-08-30 08:14:36 +10:00
} ) ;
const makeMapStateToProps = ( ) => {
const getAccount = makeGetAccount ( ) ;
const mapStateToProps = ( state , { id } ) => ( {
account : getAccount ( state , id ) ,
} ) ;
return mapStateToProps ;
} ;
const mapDispatchToProps = ( dispatch , { intl } ) => ( {
2020-07-06 22:27:32 +10:00
onFollow ( account ) {
2022-11-04 02:05:39 +11:00
if ( account . getIn ( [ 'relationship' , 'following' ] ) ) {
2019-08-30 08:14:36 +10:00
if ( unfollowModal ) {
2020-07-06 22:27:32 +10:00
dispatch (
openModal ( 'CONFIRM' , {
message : (
< FormattedMessage
id = 'confirmations.unfollow.message'
defaultMessage = 'Are you sure you want to unfollow {name}?'
values = { { name : < strong > @ { account . get ( 'acct' ) } < / strong > } }
/ >
) ,
confirm : intl . formatMessage ( messages . unfollowConfirm ) ,
onConfirm : ( ) => dispatch ( unfollowAccount ( account . get ( 'id' ) ) ) ,
} ) ,
) ;
2019-08-30 08:14:36 +10:00
} else {
dispatch ( unfollowAccount ( account . get ( 'id' ) ) ) ;
}
2022-11-04 02:05:39 +11:00
} else if ( account . getIn ( [ 'relationship' , 'requested' ] ) ) {
if ( unfollowModal ) {
dispatch ( openModal ( 'CONFIRM' , {
message : < FormattedMessage id = 'confirmations.cancel_follow_request.message' defaultMessage = 'Are you sure you want to withdraw your request to follow {name}?' values = { { name : < strong > @ { account . get ( 'acct' ) } < / strong > } } / > ,
confirm : intl . formatMessage ( messages . cancelFollowRequestConfirm ) ,
onConfirm : ( ) => dispatch ( unfollowAccount ( account . get ( 'id' ) ) ) ,
} ) ) ;
} else {
dispatch ( unfollowAccount ( account . get ( 'id' ) ) ) ;
}
2019-08-30 08:14:36 +10:00
} else {
dispatch ( followAccount ( account . get ( 'id' ) ) ) ;
}
} ,
2020-07-06 22:27:32 +10:00
onBlock ( account ) {
2019-08-30 08:14:36 +10:00
if ( account . getIn ( [ 'relationship' , 'blocking' ] ) ) {
dispatch ( unblockAccount ( account . get ( 'id' ) ) ) ;
}
} ,
2020-07-06 22:27:32 +10:00
onMute ( account ) {
2019-08-30 08:14:36 +10:00
if ( account . getIn ( [ 'relationship' , 'muting' ] ) ) {
dispatch ( unmuteAccount ( account . get ( 'id' ) ) ) ;
}
} ,
2022-03-07 21:38:52 +11:00
2019-08-30 08:14:36 +10:00
} ) ;
class AccountCard extends ImmutablePureComponent {
static propTypes = {
account : ImmutablePropTypes . map . isRequired ,
intl : PropTypes . object . isRequired ,
onFollow : PropTypes . func . isRequired ,
onBlock : PropTypes . func . isRequired ,
onMute : PropTypes . func . isRequired ,
} ;
2021-02-01 07:25:31 +11:00
handleMouseEnter = ( { currentTarget } ) => {
if ( autoPlayGif ) {
2019-09-02 04:04:35 +10:00
return ;
}
2021-02-01 07:25:31 +11:00
const emojis = currentTarget . querySelectorAll ( '.custom-emoji' ) ;
2019-09-02 04:04:35 +10:00
for ( var i = 0 ; i < emojis . length ; i ++ ) {
let emoji = emojis [ i ] ;
2021-02-01 07:25:31 +11:00
emoji . src = emoji . getAttribute ( 'data-original' ) ;
2019-09-02 04:04:35 +10:00
}
2023-01-30 11:45:35 +11:00
} ;
2019-09-02 04:04:35 +10:00
2021-02-01 07:25:31 +11:00
handleMouseLeave = ( { currentTarget } ) => {
if ( autoPlayGif ) {
return ;
}
2019-09-02 04:04:35 +10:00
2021-02-01 07:25:31 +11:00
const emojis = currentTarget . querySelectorAll ( '.custom-emoji' ) ;
2019-09-02 04:04:35 +10:00
2021-02-01 07:25:31 +11:00
for ( var i = 0 ; i < emojis . length ; i ++ ) {
let emoji = emojis [ i ] ;
emoji . src = emoji . getAttribute ( 'data-static' ) ;
}
2023-01-30 11:45:35 +11:00
} ;
2019-09-02 04:04:35 +10:00
2019-08-30 08:14:36 +10:00
handleFollow = ( ) => {
this . props . onFollow ( this . props . account ) ;
2020-07-06 22:27:32 +10:00
} ;
2019-08-30 08:14:36 +10:00
handleBlock = ( ) => {
this . props . onBlock ( this . props . account ) ;
2020-07-06 22:27:32 +10:00
} ;
2019-08-30 08:14:36 +10:00
handleMute = ( ) => {
this . props . onMute ( this . props . account ) ;
2023-01-30 11:45:35 +11:00
} ;
2022-03-07 21:38:52 +11:00
handleEditProfile = ( ) => {
window . open ( '/settings/profile' , '_blank' ) ;
2023-01-30 11:45:35 +11:00
} ;
2019-08-30 08:14:36 +10:00
2020-07-06 22:27:32 +10:00
render ( ) {
2019-08-30 08:14:36 +10:00
const { account , intl } = this . props ;
2022-03-07 21:38:52 +11:00
let actionBtn ;
if ( me !== account . get ( 'id' ) ) {
if ( ! account . get ( 'relationship' ) ) { // Wait until the relationship is loaded
actionBtn = '' ;
} else if ( account . getIn ( [ 'relationship' , 'requested' ] ) ) {
actionBtn = < Button className = { classNames ( 'logo-button' ) } text = { intl . formatMessage ( messages . cancel _follow _request ) } title = { intl . formatMessage ( messages . requested ) } onClick = { this . handleFollow } / > ;
} else if ( account . getIn ( [ 'relationship' , 'muting' ] ) ) {
actionBtn = < Button className = 'logo-button' text = { intl . formatMessage ( messages . unmute ) } onClick = { this . handleMute } / > ;
} else if ( ! account . getIn ( [ 'relationship' , 'blocking' ] ) ) {
actionBtn = < Button disabled = { account . getIn ( [ 'relationship' , 'blocked_by' ] ) } className = { classNames ( 'logo-button' , { 'button--destructive' : account . getIn ( [ 'relationship' , 'following' ] ) } ) } text = { intl . formatMessage ( account . getIn ( [ 'relationship' , 'following' ] ) ? messages . unfollow : messages . follow ) } onClick = { this . handleFollow } / > ;
} else if ( account . getIn ( [ 'relationship' , 'blocking' ] ) ) {
actionBtn = < Button className = 'logo-button' text = { intl . formatMessage ( messages . unblock ) } onClick = { this . handleBlock } / > ;
2019-08-30 08:14:36 +10:00
}
2022-03-07 21:38:52 +11:00
} else {
actionBtn = < Button className = 'logo-button' text = { intl . formatMessage ( messages . edit _profile ) } onClick = { this . handleEditProfile } / > ;
2019-08-30 08:14:36 +10:00
}
return (
2022-03-07 21:38:52 +11:00
< div className = 'account-card' >
2022-11-14 07:10:20 +11:00
< Link to = { ` /@ ${ account . get ( 'acct' ) } ` } className = 'account-card__permalink' >
2022-03-07 21:38:52 +11:00
< div className = 'account-card__header' >
< img
src = {
autoPlayGif ? account . get ( 'header' ) : account . get ( 'header_static' )
}
alt = ''
/ >
< / div >
2019-08-30 08:14:36 +10:00
2022-03-07 21:38:52 +11:00
< div className = 'account-card__title' >
< div className = 'account-card__title__avatar' > < Avatar account = { account } size = { 56 } / > < / div >
2019-08-30 08:14:36 +10:00
< DisplayName account = { account } / >
< / div >
2022-11-14 07:10:20 +11:00
< / Link >
2019-08-30 08:14:36 +10:00
2022-03-07 21:38:52 +11:00
{ account . get ( 'note' ) . length > 0 && (
2020-07-06 22:27:32 +10:00
< div
2022-03-07 21:38:52 +11:00
className = 'account-card__bio translate'
onMouseEnter = { this . handleMouseEnter }
onMouseLeave = { this . handleMouseLeave }
2020-07-06 22:27:32 +10:00
dangerouslySetInnerHTML = { { _ _html : account . get ( 'note_emojified' ) } }
/ >
2022-03-07 21:38:52 +11:00
) }
< div className = 'account-card__actions' >
< div className = 'account-card__counters' >
< div className = 'account-card__counters__item' >
< ShortNumber value = { account . get ( 'statuses_count' ) } / >
< small >
2022-04-29 08:24:31 +10:00
< FormattedMessage id = 'account.posts' defaultMessage = 'Posts' / >
2022-03-07 21:38:52 +11:00
< / small >
< / div >
< div className = 'account-card__counters__item' >
< ShortNumber value = { account . get ( 'followers_count' ) } / > { ' ' }
< small >
< FormattedMessage
id = 'account.followers'
defaultMessage = 'Followers'
/ >
< / small >
< / div >
< div className = 'account-card__counters__item' >
< ShortNumber value = { account . get ( 'following_count' ) } / > { ' ' }
< small >
< FormattedMessage
id = 'account.following'
defaultMessage = 'Following'
/ >
< / small >
< / div >
2020-07-06 22:27:32 +10:00
< / div >
2022-03-07 21:38:52 +11:00
< div className = 'account-card__actions__button' >
{ actionBtn }
2020-07-06 22:27:32 +10:00
< / div >
2019-08-30 08:14:36 +10:00
< / div >
< / div >
) ;
}
}
2023-03-24 13:17:53 +11:00
export default injectIntl ( connect ( makeMapStateToProps , mapDispatchToProps ) ( AccountCard ) ) ;