userAvatar.tsx 2.3 KB

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