2020-03-27 13:59:38 -07:00
'use strict' ;
2022-01-10 14:17:52 -08:00
import { List as ImmutableList } from 'immutable' ;
import PropTypes from 'prop-types' ;
2020-03-27 13:59:38 -07:00
import React from 'react' ;
import ImmutablePropTypes from 'react-immutable-proptypes' ;
import ImmutablePureComponent from 'react-immutable-pure-component' ;
2022-01-10 14:17:52 -08:00
import { defineMessages , injectIntl , FormattedMessage } from 'react-intl' ;
import { connect } from 'react-redux' ;
2022-01-10 14:25:06 -08:00
2022-02-26 06:57:09 -08:00
import { initAccountNoteModal } from 'soapbox/actions/account_notes' ;
2022-01-10 14:17:52 -08:00
import Badge from 'soapbox/components/badge' ;
2022-03-21 11:09:01 -07:00
import { Icon , HStack , Stack , Text } from 'soapbox/components/ui' ;
2020-05-28 15:52:07 -07:00
import VerificationBadge from 'soapbox/components/verification_badge' ;
2022-04-01 17:35:57 -07:00
import { isLocal } from 'soapbox/utils/accounts' ;
2021-04-10 12:13:07 -07:00
import { displayFqn } from 'soapbox/utils/state' ;
2022-01-10 14:25:06 -08:00
2021-09-13 11:09:11 -07:00
import ProfileStats from './profile_stats' ;
2021-06-09 18:36:02 -07:00
2022-03-21 11:09:01 -07:00
// Basically ensure the URL isn't `javascript:alert('hi')` or something like that
const isSafeUrl = text => {
try {
const url = new URL ( text ) ;
return [ 'http:' , 'https:' ] . includes ( url . protocol ) ;
} catch ( e ) {
return false ;
}
} ;
2020-03-27 13:59:38 -07:00
const messages = defineMessages ( {
linkVerifiedOn : { id : 'account.link_verified_on' , defaultMessage : 'Ownership of this link was checked on {date}' } ,
account _locked : { id : 'account.locked_info' , defaultMessage : 'This account privacy status is set to locked. The owner manually reviews who can follow them.' } ,
2020-08-12 11:02:20 -07:00
deactivated : { id : 'account.deactivated' , defaultMessage : 'Deactivated' } ,
2021-01-18 10:55:38 -08:00
bot : { id : 'account.badges.bot' , defaultMessage : 'Bot' } ,
2020-03-27 13:59:38 -07:00
} ) ;
class ProfileInfoPanel extends ImmutablePureComponent {
static propTypes = {
2022-03-23 10:14:42 -07:00
account : ImmutablePropTypes . record ,
2020-03-27 13:59:38 -07:00
identity _proofs : ImmutablePropTypes . list ,
intl : PropTypes . object . isRequired ,
username : PropTypes . string ,
2021-04-10 12:13:07 -07:00
displayFqn : PropTypes . bool ,
2022-02-26 06:57:09 -08:00
onShowNote : PropTypes . func ,
2020-03-27 13:59:38 -07:00
} ;
2021-07-13 09:21:37 -07:00
getStaffBadge = ( ) => {
const { account } = this . props ;
2022-04-01 17:35:57 -07:00
if ( account ? . admin ) {
2021-09-13 10:59:44 -07:00
return < Badge slug = 'admin' title = 'Admin' key = 'staff' / > ;
2022-04-01 17:35:57 -07:00
} else if ( account ? . moderator ) {
2021-09-13 10:59:44 -07:00
return < Badge slug = 'moderator' title = 'Moderator' key = 'staff' / > ;
2021-07-13 09:21:37 -07:00
} else {
return null ;
}
}
2021-09-13 10:59:44 -07:00
getBadges = ( ) => {
const { account } = this . props ;
const staffBadge = this . getStaffBadge ( ) ;
const isPatron = account . getIn ( [ 'patron' , 'is_patron' ] ) ;
const badges = [ ] ;
if ( staffBadge ) {
badges . push ( staffBadge ) ;
}
if ( isPatron ) {
badges . push ( < Badge slug = 'patron' title = 'Patron' key = 'patron' / > ) ;
}
return badges ;
}
2022-03-21 11:09:01 -07:00
renderBirthday = ( ) => {
2022-01-21 14:40:39 -08:00
const { account , intl } = this . props ;
2022-02-26 13:49:42 -08:00
const birthday = account . get ( 'birthday' ) ;
2022-01-25 12:09:30 -08:00
if ( ! birthday ) return null ;
2022-01-21 14:40:39 -08:00
2022-01-31 18:18:15 -08:00
const formattedBirthday = intl . formatDate ( birthday , { timeZone : 'UTC' , day : 'numeric' , month : 'long' , year : 'numeric' } ) ;
2022-01-21 14:40:39 -08:00
2022-01-25 12:09:30 -08:00
const date = new Date ( birthday ) ;
2022-01-21 14:40:39 -08:00
const today = new Date ( ) ;
const hasBirthday = date . getDate ( ) === today . getDate ( ) && date . getMonth ( ) === today . getMonth ( ) ;
return (
2022-03-21 11:09:01 -07:00
< HStack alignItems = 'center' space = { 0.5 } >
< Icon
src = { require ( '@tabler/icons/icons/ballon.svg' ) }
2022-04-04 12:58:27 -07:00
className = 'w-4 h-4 text-gray-800 dark:text-gray-200'
2022-01-21 14:40:39 -08:00
/ >
2022-03-21 11:09:01 -07:00
< Text size = 'sm' >
{ hasBirthday ? (
< FormattedMessage id = 'account.birthday_today' defaultMessage = 'Birthday is today!' / >
) : (
< FormattedMessage id = 'account.birthday' defaultMessage = 'Born {date}' values = { { date : formattedBirthday } } / >
) }
< / T e x t >
< / H S t a c k >
2022-01-21 14:40:39 -08:00
) ;
}
2022-02-26 06:57:09 -08:00
handleShowNote = e => {
const { account , onShowNote } = this . props ;
e . preventDefault ( ) ;
onShowNote ( account ) ;
}
2020-04-14 14:47:35 -07:00
render ( ) {
2022-03-21 11:09:01 -07:00
const { account , displayFqn , intl , username } = this . props ;
2020-03-27 13:59:38 -07:00
if ( ! account ) {
return (
2022-03-21 11:09:01 -07:00
< div className = 'mt-6 min-w-0 flex-1 sm:px-2' >
< Stack space = { 2 } >
< Stack >
< HStack space = { 1 } alignItems = 'center' >
< Text size = 'sm' theme = 'muted' >
@ { username }
< / T e x t >
< / H S t a c k >
< / S t a c k >
< / S t a c k >
2020-03-27 13:59:38 -07:00
< / d i v >
) ;
}
const content = { _ _html : account . get ( 'note_emojified' ) } ;
2021-01-18 11:59:24 -08:00
const deactivated = ! account . getIn ( [ 'pleroma' , 'is_active' ] , true ) ;
2020-08-12 11:02:20 -07:00
const displayNameHtml = deactivated ? { _ _html : intl . formatMessage ( messages . deactivated ) } : { _ _html : account . get ( 'display_name_html' ) } ;
2020-03-27 13:59:38 -07:00
const memberSinceDate = intl . formatDate ( account . get ( 'created_at' ) , { month : 'long' , year : 'numeric' } ) ;
2022-02-27 20:25:23 -08:00
const verified = account . get ( 'verified' ) ;
2021-09-13 10:59:44 -07:00
const badges = this . getBadges ( ) ;
2020-03-27 13:59:38 -07:00
return (
2022-03-21 11:09:01 -07:00
< div className = 'mt-6 min-w-0 flex-1 sm:px-2' >
< Stack space = { 2 } >
{ /* Not sure if this is actual used. */ }
{ / * < d i v c l a s s N a m e = ' p r o f i l e - i n f o - p a n e l - c o n t e n t _ _ d e a c t i v a t e d ' >
< FormattedMessage
id = 'account.deactivated_description' defaultMessage = 'This account has been deactivated.'
/ >
< /div> */ }
< Stack >
< HStack space = { 1 } alignItems = 'center' >
< Text size = 'lg' weight = 'bold' dangerouslySetInnerHTML = { displayNameHtml } / >
2020-03-27 13:59:38 -07:00
2020-08-05 10:08:52 -07:00
{ verified && < VerificationBadge / > }
2022-03-21 11:09:01 -07:00
2022-04-01 17:35:57 -07:00
{ account . bot && < Badge slug = 'bot' title = { intl . formatMessage ( messages . bot ) } / > }
2020-03-27 13:59:38 -07:00
2022-03-21 11:09:01 -07:00
{ badges . length > 0 && (
< HStack space = { 1 } alignItems = 'center' >
{ badges }
< / H S t a c k >
) }
< / H S t a c k >
2020-08-25 11:47:02 -07:00
2022-03-21 11:09:01 -07:00
< HStack alignItems = 'center' space = { 0.5 } >
< Text size = 'sm' theme = 'muted' >
2022-04-01 17:35:57 -07:00
@ { displayFqn ? account . fqn : account . acct }
2022-03-21 11:09:01 -07:00
< / T e x t >
{ account . get ( 'locked' ) && (
< Icon
src = { require ( '@tabler/icons/icons/lock.svg' ) }
title = { intl . formatMessage ( messages . account _locked ) }
className = 'w-4 h-4 text-gray-600'
/ >
) }
< / H S t a c k >
< / S t a c k >
< ProfileStats account = { account } / >
2020-03-27 13:59:38 -07:00
2020-08-25 11:47:02 -07:00
{
2020-03-27 13:59:38 -07:00
( account . get ( 'note' ) . length > 0 && account . get ( 'note' ) !== '<p></p>' ) &&
2022-03-21 11:09:01 -07:00
< Text size = 'sm' dangerouslySetInnerHTML = { content } / >
2020-03-27 13:59:38 -07:00
}
2022-03-24 11:07:08 -07:00
< div className = 'flex flex-col md:flex-row items-start md:flex-wrap md:items-center gap-2' >
2022-03-21 11:09:01 -07:00
{ isLocal ( account ) ? (
< HStack alignItems = 'center' space = { 0.5 } >
< Icon
src = { require ( '@tabler/icons/icons/calendar.svg' ) }
2022-04-04 12:58:27 -07:00
className = 'w-4 h-4 text-gray-800 dark:text-gray-200'
2022-03-21 11:09:01 -07:00
/ >
< Text size = 'sm' >
< FormattedMessage
id = 'account.member_since' defaultMessage = 'Joined {date}' values = { {
date : memberSinceDate ,
} }
/ >
< / T e x t >
< / H S t a c k >
) : null }
{ account . get ( 'location' ) ? (
< HStack alignItems = 'center' space = { 0.5 } >
< Icon
src = { require ( '@tabler/icons/icons/map-pin.svg' ) }
2022-04-04 12:58:27 -07:00
className = 'w-4 h-4 text-gray-800 dark:text-gray-200'
2022-03-21 11:09:01 -07:00
/ >
< Text size = 'sm' >
{ account . get ( 'location' ) }
< / T e x t >
< / H S t a c k >
) : null }
{ account . get ( 'website' ) ? (
< HStack alignItems = 'center' space = { 0.5 } >
< Icon
src = { require ( '@tabler/icons/icons/link.svg' ) }
2022-04-04 12:58:27 -07:00
className = 'w-4 h-4 text-gray-800 dark:text-gray-200'
2022-03-21 11:09:01 -07:00
/ >
2022-03-24 11:07:08 -07:00
< div className = 'max-w-[300px]' >
< Text size = 'sm' truncate >
{ isSafeUrl ( account . get ( 'website' ) ) ? (
2022-04-04 12:58:27 -07:00
< a className = 'text-primary-600 dark:text-primary-400 hover:underline' href = { account . get ( 'website' ) } target = '_blank' > { account . get ( 'website' ) } < / a >
2022-03-24 11:07:08 -07:00
) : (
account . get ( 'website' )
) }
< / T e x t >
< / d i v >
2022-03-21 11:09:01 -07:00
< / H S t a c k >
) : null }
{ this . renderBirthday ( ) }
< / d i v >
< / S t a c k >
2020-03-27 13:59:38 -07:00
< / d i v >
) ;
}
2020-04-14 11:44:40 -07:00
2020-03-27 13:59:38 -07:00
}
const mapStateToProps = ( state , { account } ) => {
const identity _proofs = account ? state . getIn ( [ 'identity_proofs' , account . get ( 'id' ) ] , ImmutableList ( ) ) : ImmutableList ( ) ;
return {
identity _proofs ,
domain : state . getIn ( [ 'meta' , 'domain' ] ) ,
2021-04-10 12:13:07 -07:00
displayFqn : displayFqn ( state ) ,
2020-03-27 13:59:38 -07:00
} ;
} ;
2022-02-26 06:57:09 -08:00
const mapDispatchToProps = ( dispatch ) => ( {
onShowNote ( account ) {
dispatch ( initAccountNoteModal ( account ) ) ;
} ,
} ) ;
2020-03-27 13:59:38 -07:00
export default injectIntl (
2022-02-26 06:57:09 -08:00
connect ( mapStateToProps , mapDispatchToProps , null , {
2020-03-27 13:59:38 -07:00
forwardRef : true ,
2020-10-07 11:08:36 -07:00
} ,
2020-04-14 11:44:40 -07:00
) ( ProfileInfoPanel ) ) ;