diff --git a/app/javascript/mastodon/components/__tests__/display_name-test.jsx b/app/javascript/mastodon/components/__tests__/display_name-test.jsx index 0d040c4cd8cc04661fd4ebcb02b04d1c746647b9..afb6c4758a93ea991b5ead1f10cee7c5adf59a1e 100644 --- a/app/javascript/mastodon/components/__tests__/display_name-test.jsx +++ b/app/javascript/mastodon/components/__tests__/display_name-test.jsx @@ -1,7 +1,7 @@ import React from 'react'; import renderer from 'react-test-renderer'; import { fromJS } from 'immutable'; -import DisplayName from '../display_name'; +import { DisplayName } from '../display_name'; describe('<DisplayName />', () => { it('renders display name + account name', () => { diff --git a/app/javascript/mastodon/components/account.jsx b/app/javascript/mastodon/components/account.jsx index b0bbea7ce46da7e0e5837a0f926160f4f124368b..f110bce7a83b77078219b55a4f288481fdd7f1f5 100644 --- a/app/javascript/mastodon/components/account.jsx +++ b/app/javascript/mastodon/components/account.jsx @@ -2,7 +2,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { Avatar } from './avatar'; -import DisplayName from './display_name'; +import { DisplayName } from './display_name'; import { IconButton } from './icon_button'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; diff --git a/app/javascript/mastodon/components/display_name.jsx b/app/javascript/mastodon/components/display_name.jsx deleted file mode 100644 index 1dd9fb1d67f1d4296142dc59f01b2d2fa7549319..0000000000000000000000000000000000000000 --- a/app/javascript/mastodon/components/display_name.jsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import PropTypes from 'prop-types'; -import { autoPlayGif } from 'mastodon/initial_state'; -import Skeleton from 'mastodon/components/skeleton'; - -export default class DisplayName extends React.PureComponent { - - static propTypes = { - account: ImmutablePropTypes.map, - others: ImmutablePropTypes.list, - localDomain: PropTypes.string, - }; - - handleMouseEnter = ({ currentTarget }) => { - if (autoPlayGif) { - return; - } - - const emojis = currentTarget.querySelectorAll('.custom-emoji'); - - for (var i = 0; i < emojis.length; i++) { - let emoji = emojis[i]; - emoji.src = emoji.getAttribute('data-original'); - } - }; - - handleMouseLeave = ({ currentTarget }) => { - if (autoPlayGif) { - return; - } - - const emojis = currentTarget.querySelectorAll('.custom-emoji'); - - for (var i = 0; i < emojis.length; i++) { - let emoji = emojis[i]; - emoji.src = emoji.getAttribute('data-static'); - } - }; - - render () { - const { others, localDomain } = this.props; - - let displayName, suffix, account; - - if (others && others.size > 1) { - displayName = others.take(2).map(a => <bdi key={a.get('id')}><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }} /></bdi>).reduce((prev, cur) => [prev, ', ', cur]); - - if (others.size - 2 > 0) { - suffix = `+${others.size - 2}`; - } - } else if ((others && others.size > 0) || this.props.account) { - if (others && others.size > 0) { - account = others.first(); - } else { - account = this.props.account; - } - - let acct = account.get('acct'); - - if (acct.indexOf('@') === -1 && localDomain) { - acct = `${acct}@${localDomain}`; - } - - displayName = <bdi><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi>; - suffix = <span className='display-name__account'>@{acct}</span>; - } else { - displayName = <bdi><strong className='display-name__html'><Skeleton width='10ch' /></strong></bdi>; - suffix = <span className='display-name__account'><Skeleton width='7ch' /></span>; - } - - return ( - <span className='display-name' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}> - {displayName} {suffix} - </span> - ); - } - -} diff --git a/app/javascript/mastodon/components/display_name.tsx b/app/javascript/mastodon/components/display_name.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0452dba794cf122df7a79a49d2a58b45256fe2d9 --- /dev/null +++ b/app/javascript/mastodon/components/display_name.tsx @@ -0,0 +1,115 @@ +import React from 'react'; +import { autoPlayGif } from '..//initial_state'; +import Skeleton from './skeleton'; +import { Account } from '../../types/resources'; +import { List } from 'immutable'; + +type Props = { + account: Account; + others: List<Account>; + localDomain: string; +}; +export class DisplayName extends React.PureComponent<Props> { + handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({ + currentTarget, + }) => { + if (autoPlayGif) { + return; + } + + const emojis = + currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji'); + + emojis.forEach((emoji) => { + const originalSrc = emoji.getAttribute('data-original'); + if (originalSrc != null) emoji.src = originalSrc; + }); + }; + + handleMouseLeave: React.ReactEventHandler<HTMLSpanElement> = ({ + currentTarget, + }) => { + if (autoPlayGif) { + return; + } + + const emojis = + currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji'); + + emojis.forEach((emoji) => { + const staticSrc = emoji.getAttribute('data-static'); + if (staticSrc != null) emoji.src = staticSrc; + }); + }; + + render() { + const { others, localDomain } = this.props; + + let displayName: React.ReactNode, suffix: React.ReactNode, account: Account; + + if (others && others.size > 1) { + displayName = others + .take(2) + .map((a) => ( + <bdi key={a.get('id')}> + <strong + className='display-name__html' + dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }} + /> + </bdi> + )) + .reduce((prev, cur) => [prev, ', ', cur]); + + if (others.size - 2 > 0) { + suffix = `+${others.size - 2}`; + } + } else if ((others && others.size > 0) || this.props.account) { + if (others && others.size > 0) { + account = others.first(); + } else { + account = this.props.account; + } + + let acct = account.get('acct'); + + if (acct.indexOf('@') === -1 && localDomain) { + acct = `${acct}@${localDomain}`; + } + + displayName = ( + <bdi> + <strong + className='display-name__html' + dangerouslySetInnerHTML={{ + __html: account.get('display_name_html'), + }} + /> + </bdi> + ); + suffix = <span className='display-name__account'>@{acct}</span>; + } else { + displayName = ( + <bdi> + <strong className='display-name__html'> + <Skeleton width='10ch' /> + </strong> + </bdi> + ); + suffix = ( + <span className='display-name__account'> + <Skeleton width='7ch' /> + </span> + ); + } + + return ( + <span + className='display-name' + onMouseEnter={this.handleMouseEnter} + onMouseLeave={this.handleMouseLeave} + > + {displayName} {suffix} + </span> + ); + } +} diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index 3ca840b7200bebdde9972bda24b603bf84cc07e7..8cd322edabfedf7e8ca2255e401f9a71eed68842 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { Avatar } from './avatar'; import { AvatarOverlay } from './avatar_overlay'; import { RelativeTimestamp } from './relative_timestamp'; -import DisplayName from './display_name'; +import { DisplayName } from './display_name'; import StatusContent from './status_content'; import StatusActionBar from './status_action_bar'; import AttachmentList from './attachment_list'; diff --git a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx index 273583c0ad8a77447977250b6a5db3ab6e220e9a..29861612c3109ff23b539e4417f48fac92759747 100644 --- a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx +++ b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx @@ -3,7 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { AvatarOverlay } from '../../../components/avatar_overlay'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import { Link } from 'react-router-dom'; export default class MovedNote extends ImmutablePureComponent { diff --git a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx index 2c92016e86df925b4790a588622ff1a55cea845d..a635657d9f1daa457e1963dc9c45b24bdc454159 100644 --- a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx +++ b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { Avatar } from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx index 68cd7b080414719a77769bd1f9edf4fc2df980ff..b3f1b1b4827b6048a16691f8eab77e853080e8a1 100644 --- a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx +++ b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx @@ -3,7 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { Avatar } from '../../../components/avatar'; import { IconButton } from '../../../components/icon_button'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import AttachmentList from 'mastodon/components/attachment_list'; diff --git a/app/javascript/mastodon/features/directory/components/account_card.jsx b/app/javascript/mastodon/features/directory/components/account_card.jsx index 495142715180d87f7365ded3c63de27f88455339..1ef9d648136b3e098d27317f15c270c5a7ff26ba 100644 --- a/app/javascript/mastodon/features/directory/components/account_card.jsx +++ b/app/javascript/mastodon/features/directory/components/account_card.jsx @@ -5,7 +5,7 @@ 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'; +import { DisplayName } from 'mastodon/components/display_name'; import { Link } from 'react-router-dom'; import Button from 'mastodon/components/button'; import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; diff --git a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx index b370b33ecb4dee64cd93432b6e873ccb6a250e7c..5d0632b0f66f788b8b0131497612424cfafa6f8d 100644 --- a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx +++ b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { Link } from 'react-router-dom'; import { Avatar } from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import { IconButton } from '../../../components/icon_button'; import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; diff --git a/app/javascript/mastodon/features/list_adder/components/account.jsx b/app/javascript/mastodon/features/list_adder/components/account.jsx index 410f1537a5a67890d0bd8e067f9137b263c1f59d..5dc384aba6f7a2fcc482e4fc05c60fd3666bc3ce 100644 --- a/app/javascript/mastodon/features/list_adder/components/account.jsx +++ b/app/javascript/mastodon/features/list_adder/components/account.jsx @@ -4,7 +4,7 @@ import { makeGetAccount } from '../../../selectors'; import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { Avatar } from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import { injectIntl } from 'react-intl'; const makeMapStateToProps = () => { diff --git a/app/javascript/mastodon/features/list_editor/components/account.jsx b/app/javascript/mastodon/features/list_editor/components/account.jsx index b46d0504a4693f8b601097b2d57b43a64ee8954c..fc1d2d6071905a702db8900b4ca7f9f111b057ad 100644 --- a/app/javascript/mastodon/features/list_editor/components/account.jsx +++ b/app/javascript/mastodon/features/list_editor/components/account.jsx @@ -5,7 +5,7 @@ import { makeGetAccount } from '../../../selectors'; import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { Avatar } from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import { IconButton } from '../../../components/icon_button'; import { defineMessages, injectIntl } from 'react-intl'; import { removeFromListEditor, addToListEditor } from '../../../actions/lists'; diff --git a/app/javascript/mastodon/features/notifications/components/follow_request.jsx b/app/javascript/mastodon/features/notifications/components/follow_request.jsx index 0d930f0b1f07eda0931821c14193015f7987002b..d8b2ca1cc9f0a35df41d61a727ebe9053a1c3a24 100644 --- a/app/javascript/mastodon/features/notifications/components/follow_request.jsx +++ b/app/javascript/mastodon/features/notifications/components/follow_request.jsx @@ -2,7 +2,7 @@ import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { Avatar } from 'mastodon/components/avatar'; -import DisplayName from 'mastodon/components/display_name'; +import { DisplayName } from 'mastodon/components/display_name'; import { Link } from 'react-router-dom'; import { IconButton } from 'mastodon/components/icon_button'; import { defineMessages, injectIntl } from 'react-intl'; diff --git a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx index c6d2a103dc0402d361554210a3d5a84be652f15c..c1c04da5483a66053aa22ec6b18d30d06fd7fbc0 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx +++ b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx @@ -6,7 +6,7 @@ import PropTypes from 'prop-types'; import { IconButton } from 'mastodon/components/icon_button'; import { Link } from 'react-router-dom'; import { Avatar } from 'mastodon/components/avatar'; -import DisplayName from 'mastodon/components/display_name'; +import { DisplayName } from 'mastodon/components/display_name'; import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ diff --git a/app/javascript/mastodon/features/report/components/status_check_box.jsx b/app/javascript/mastodon/features/report/components/status_check_box.jsx index 003cdc8e3af4ffbffc29432bd514b578f27d677c..8d6091f778285afd17cca13bdfe9c113a2b88cd5 100644 --- a/app/javascript/mastodon/features/report/components/status_check_box.jsx +++ b/app/javascript/mastodon/features/report/components/status_check_box.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import StatusContent from 'mastodon/components/status_content'; import { Avatar } from 'mastodon/components/avatar'; -import DisplayName from 'mastodon/components/display_name'; +import { DisplayName } from 'mastodon/components/display_name'; import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; import Option from './option'; import MediaAttachments from 'mastodon/components/media_attachments'; diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx index 72c9021242bb9897266ad05d7550c76c95fa8ea1..5019dfdb4db94a747841baff4871add21c25260c 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.jsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { Avatar } from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; import { Link } from 'react-router-dom'; diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.jsx b/app/javascript/mastodon/features/ui/components/boost_modal.jsx index 1f28927d60eeb6bbdb2cc9bdd0dadbeb48d8f57e..4eeb30be09c6013e4f62412cbcd7a339127febde 100644 --- a/app/javascript/mastodon/features/ui/components/boost_modal.jsx +++ b/app/javascript/mastodon/features/ui/components/boost_modal.jsx @@ -7,7 +7,7 @@ import Button from '../../../components/button'; import StatusContent from '../../../components/status_content'; import { Avatar } from '../../../components/avatar'; import { RelativeTimestamp } from '../../../components/relative_timestamp'; -import DisplayName from '../../../components/display_name'; +import { DisplayName } from '../../../components/display_name'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { Icon } from 'mastodon/components/icon'; import AttachmentList from 'mastodon/components/attachment_list';