display_name.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import React from 'react';
  2. import type { List } from 'immutable';
  3. import type { Account } from 'mastodon/models/account';
  4. import { autoPlayGif } from '../initial_state';
  5. import { Skeleton } from './skeleton';
  6. interface Props {
  7. account?: Account;
  8. others?: List<Account>;
  9. localDomain?: string;
  10. }
  11. export class DisplayName extends React.PureComponent<Props> {
  12. handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({
  13. currentTarget,
  14. }) => {
  15. if (autoPlayGif) {
  16. return;
  17. }
  18. const emojis =
  19. currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
  20. emojis.forEach((emoji) => {
  21. const originalSrc = emoji.getAttribute('data-original');
  22. if (originalSrc != null) emoji.src = originalSrc;
  23. });
  24. };
  25. handleMouseLeave: React.ReactEventHandler<HTMLSpanElement> = ({
  26. currentTarget,
  27. }) => {
  28. if (autoPlayGif) {
  29. return;
  30. }
  31. const emojis =
  32. currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
  33. emojis.forEach((emoji) => {
  34. const staticSrc = emoji.getAttribute('data-static');
  35. if (staticSrc != null) emoji.src = staticSrc;
  36. });
  37. };
  38. render() {
  39. const { others, localDomain } = this.props;
  40. let displayName: React.ReactNode,
  41. suffix: React.ReactNode,
  42. account: Account | undefined;
  43. if (others && others.size > 0) {
  44. account = others.first();
  45. } else if (this.props.account) {
  46. account = this.props.account;
  47. }
  48. if (others && others.size > 1) {
  49. displayName = others
  50. .take(2)
  51. .map((a) => (
  52. <bdi key={a.get('id')}>
  53. <strong
  54. className='display-name__html'
  55. dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }}
  56. />
  57. </bdi>
  58. ))
  59. .reduce((prev, cur) => [prev, ', ', cur]);
  60. if (others.size - 2 > 0) {
  61. suffix = `+${others.size - 2}`;
  62. }
  63. } else if (account) {
  64. let acct = account.get('acct');
  65. if (!acct.includes('@') && localDomain) {
  66. acct = `${acct}@${localDomain}`;
  67. }
  68. displayName = (
  69. <bdi>
  70. <strong
  71. className='display-name__html'
  72. dangerouslySetInnerHTML={{
  73. __html: account.get('display_name_html'),
  74. }}
  75. />
  76. </bdi>
  77. );
  78. suffix = <span className='display-name__account'>@{acct}</span>;
  79. } else {
  80. displayName = (
  81. <bdi>
  82. <strong className='display-name__html'>
  83. <Skeleton width='10ch' />
  84. </strong>
  85. </bdi>
  86. );
  87. suffix = (
  88. <span className='display-name__account'>
  89. <Skeleton width='7ch' />
  90. </span>
  91. );
  92. }
  93. return (
  94. <span
  95. className='display-name'
  96. onMouseEnter={this.handleMouseEnter}
  97. onMouseLeave={this.handleMouseLeave}
  98. >
  99. {displayName} {suffix}
  100. </span>
  101. );
  102. }
  103. }