You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
5.0 KiB

  1. import React from 'react';
  2. import ImmutablePropTypes from 'react-immutable-proptypes';
  3. import PropTypes from 'prop-types';
  4. import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
  5. import ImmutablePureComponent from 'react-immutable-pure-component';
  6. import Avatar from 'flavours/glitch/components/avatar';
  7. import IconButton from 'flavours/glitch/components/icon_button';
  8. import emojify from 'flavours/glitch/util/emoji';
  9. import { me } from 'flavours/glitch/util/initial_state';
  10. import { processBio } from 'flavours/glitch/util/bio_metadata';
  11. const messages = defineMessages({
  12. unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
  13. follow: { id: 'account.follow', defaultMessage: 'Follow' },
  14. requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
  15. unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
  16. });
  17. @injectIntl
  18. export default class Header extends ImmutablePureComponent {
  19. static propTypes = {
  20. account: ImmutablePropTypes.map,
  21. onFollow: PropTypes.func.isRequired,
  22. onBlock: PropTypes.func.isRequired,
  23. intl: PropTypes.object.isRequired,
  24. };
  25. render () {
  26. const { account, intl } = this.props;
  27. if (!account) {
  28. return null;
  29. }
  30. let displayName = account.get('display_name_html');
  31. let info = '';
  32. let mutingInfo = '';
  33. let actionBtn = '';
  34. if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
  35. info = <span className='account--follows-info'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>;
  36. }
  37. else if (me !== account.get('id') && account.getIn(['relationship', 'blocking'])) {
  38. info = <span className='account--follows-info'><FormattedMessage id='account.blocked' defaultMessage='Blocked' /></span>;
  39. }
  40. if (me !== account.get('id') && account.getIn(['relationship', 'muting'])) {
  41. mutingInfo = <span className='account--muting-info'><FormattedMessage id='account.muted' defaultMessage='Muted' /></span>;
  42. } else if (me !== account.get('id') && account.getIn(['relationship', 'domain_blocking'])) {
  43. mutingInfo = <span className='account--muting-info'><FormattedMessage id='account.domain_blocked' defaultMessage='Domain hidden' /></span>;
  44. }
  45. if (me !== account.get('id')) {
  46. if (account.getIn(['relationship', 'requested'])) {
  47. actionBtn = (
  48. <div className='account--action-button'>
  49. <IconButton size={26} active icon='hourglass' title={intl.formatMessage(messages.requested)} onClick={this.props.onFollow} />
  50. </div>
  51. );
  52. } else if (!account.getIn(['relationship', 'blocking'])) {
  53. actionBtn = (
  54. <div className='account--action-button'>
  55. <IconButton size={26} icon={account.getIn(['relationship', 'following']) ? 'user-times' : 'user-plus'} active={account.getIn(['relationship', 'following'])} title={intl.formatMessage(account.getIn(['relationship', 'following']) ? messages.unfollow : messages.follow)} onClick={this.props.onFollow} />
  56. </div>
  57. );
  58. } else if (account.getIn(['relationship', 'blocking'])) {
  59. actionBtn = (
  60. <div className='account--action-button'>
  61. <IconButton size={26} icon='unlock-alt' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.props.onBlock} />
  62. </div>
  63. );
  64. }
  65. }
  66. const { text, metadata } = processBio(account.get('note'));
  67. return (
  68. <div className='account__header__wrapper'>
  69. <div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
  70. <div>
  71. <a
  72. href={account.get('url')}
  73. className='account__header__avatar'
  74. role='presentation'
  75. target='_blank'
  76. rel='noopener'
  77. >
  78. <Avatar account={account} size={90} />
  79. </a>
  80. <span className='account__header__display-name' dangerouslySetInnerHTML={{ __html: displayName }} />
  81. <span className='account__header__username'>@{account.get('acct')} {account.get('locked') ? <i className='fa fa-lock' /> : null}</span>
  82. <div className='account__header__content' dangerouslySetInnerHTML={{ __html: emojify(text) }} />
  83. {info}
  84. {mutingInfo}
  85. {actionBtn}
  86. </div>
  87. </div>
  88. {metadata.length && (
  89. <table className='account__metadata'>
  90. <tbody>
  91. {(() => {
  92. let data = [];
  93. for (let i = 0; i < metadata.length; i++) {
  94. data.push(
  95. <tr key={i}>
  96. <th scope='row'><div dangerouslySetInnerHTML={{ __html: emojify(metadata[i][0]) }} /></th>
  97. <td><div dangerouslySetInnerHTML={{ __html: emojify(metadata[i][1]) }} /></td>
  98. </tr>
  99. );
  100. }
  101. return data;
  102. })()}
  103. </tbody>
  104. </table>
  105. ) || null}
  106. </div>
  107. );
  108. }
  109. }