userAvatar.tsx 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import * as React from 'react';
  2. import BaseAvatar from 'sentry/components/avatar/baseAvatar';
  3. import {Actor, AvatarUser} from 'sentry/types';
  4. import {userDisplayName} from 'sentry/utils/formatters';
  5. import {isRenderFunc} from 'sentry/utils/isRenderFunc';
  6. type RenderTooltipFunc = (user: AvatarUser | Actor) => React.ReactNode;
  7. const defaultProps = {
  8. // Default gravatar to false in order to support transparent avatars
  9. // Avatar falls through to letter avatars if a remote image fails to load,
  10. // however gravatar sends back a transparent image when it does not find a gravatar,
  11. // so there's little we have to control whether we need to fallback to letter avatar
  12. gravatar: false,
  13. };
  14. type Props = {
  15. user?: Actor | AvatarUser;
  16. renderTooltip?: RenderTooltipFunc;
  17. gravatar?: boolean;
  18. } & Omit<BaseAvatar['props'], 'uploadPath' | 'uploadId'>;
  19. function isActor(maybe: AvatarUser | Actor): maybe is Actor {
  20. return typeof (maybe as AvatarUser).email === 'undefined';
  21. }
  22. class UserAvatar extends React.Component<Props> {
  23. static defaultProps = defaultProps;
  24. getType = (user: AvatarUser | Actor, gravatar: boolean | undefined) => {
  25. if (isActor(user)) {
  26. return 'letter_avatar';
  27. }
  28. if (user.avatar) {
  29. return user.avatar.avatarType;
  30. }
  31. if (user.options && user.options.avatarType) {
  32. return user.options.avatarType;
  33. }
  34. return user.email && gravatar ? 'gravatar' : 'letter_avatar';
  35. };
  36. render() {
  37. const {user, gravatar, renderTooltip, ...props} = this.props;
  38. if (!user) {
  39. return null;
  40. }
  41. const type = this.getType(user, gravatar);
  42. let tooltip: React.ReactNode = null;
  43. if (isRenderFunc<RenderTooltipFunc>(renderTooltip)) {
  44. tooltip = renderTooltip(user);
  45. } else if (props.tooltip) {
  46. tooltip = props.tooltip;
  47. } else {
  48. tooltip = userDisplayName(user);
  49. }
  50. const avatarData = isActor(user)
  51. ? {
  52. uploadId: '',
  53. gravatarId: '',
  54. letterId: user.name,
  55. title: user.name,
  56. }
  57. : {
  58. uploadId: user.avatar?.avatarUuid ?? '',
  59. gravatarId: user.email?.toLowerCase(),
  60. letterId: user.email || user.username || user.id || user.ip_address,
  61. title: user.name || user.email || user.username || '',
  62. };
  63. return (
  64. <BaseAvatar
  65. round
  66. {...props}
  67. type={type}
  68. uploadPath="avatar"
  69. uploadId={avatarData.uploadId}
  70. gravatarId={avatarData.gravatarId}
  71. letterId={avatarData.letterId}
  72. title={avatarData.title}
  73. tooltip={tooltip}
  74. />
  75. );
  76. }
  77. }
  78. export default UserAvatar;