actorAvatar.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import {useMemo} from 'react';
  2. import * as Sentry from '@sentry/react';
  3. import TeamAvatar from 'sentry/components/avatar/teamAvatar';
  4. import UserAvatar from 'sentry/components/avatar/userAvatar';
  5. import Placeholder from 'sentry/components/placeholder';
  6. import type {Actor} from 'sentry/types/core';
  7. import {useMembers} from 'sentry/utils/useMembers';
  8. import {useTeamsById} from 'sentry/utils/useTeamsById';
  9. import {BaseAvatar, type BaseAvatarProps} from './baseAvatar';
  10. interface Props extends BaseAvatarProps {
  11. actor: Actor;
  12. }
  13. /**
  14. * Wrapper to assist loading the team from api or store
  15. */
  16. function LoadTeamAvatar({
  17. teamId,
  18. ...props
  19. }: {teamId: string} & Omit<React.ComponentProps<typeof TeamAvatar>, 'team'>) {
  20. const {teams, isLoading} = useTeamsById({ids: [teamId]});
  21. const team = teams.find(t => t.id === teamId);
  22. if (isLoading) {
  23. const size = `${props.size}px`;
  24. return <Placeholder width={size} height={size} />;
  25. }
  26. return <TeamAvatar team={team} {...props} />;
  27. }
  28. /**
  29. * Wrapper to assist loading the user from api or store
  30. */
  31. function LoadMemberAvatar({
  32. userActor,
  33. ...props
  34. }: {userActor: Actor} & Omit<React.ComponentProps<typeof UserAvatar>, 'team'>) {
  35. const ids = useMemo(() => [userActor.id], [userActor.id]);
  36. const {members, fetching} = useMembers({ids});
  37. const member = members.find(u => u.id === userActor.id);
  38. if (fetching) {
  39. const size = `${props.size}px`;
  40. return <Placeholder shape="circle" width={size} height={size} />;
  41. }
  42. if (!member) {
  43. return (
  44. <BaseAvatar size={props.size} title={userActor.name ?? userActor.email} round />
  45. );
  46. }
  47. return <UserAvatar user={member} {...props} />;
  48. }
  49. function ActorAvatar({size = 24, hasTooltip = true, actor, ...props}: Props) {
  50. const otherProps = {
  51. size,
  52. hasTooltip,
  53. ...props,
  54. };
  55. if (actor.type === 'user') {
  56. return <LoadMemberAvatar userActor={actor} {...otherProps} />;
  57. }
  58. if (actor.type === 'team') {
  59. return <LoadTeamAvatar teamId={actor.id} {...otherProps} />;
  60. }
  61. Sentry.withScope(scope => {
  62. scope.setExtra('actor', actor);
  63. Sentry.captureException(new Error('Unknown avatar type'));
  64. });
  65. return null;
  66. }
  67. export default ActorAvatar;