gravatar.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import {useCallback, useEffect, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import * as qs from 'query-string';
  4. import ConfigStore from 'sentry/stores/configStore';
  5. import {useIsMountedRef} from 'sentry/utils/useIsMountedRef';
  6. import {imageStyle, ImageStyleProps} from './styles';
  7. type Props = {
  8. remoteSize: number;
  9. gravatarId?: string;
  10. onError?: () => void;
  11. onLoad?: () => void;
  12. placeholder?: string;
  13. } & ImageStyleProps;
  14. type HasherHelper = typeof import('crypto-js/md5');
  15. function Gravatar({
  16. remoteSize,
  17. gravatarId,
  18. placeholder,
  19. round,
  20. onError,
  21. onLoad,
  22. suggested,
  23. }: Props) {
  24. const isMountedRef = useIsMountedRef();
  25. const [MD5, setMD5] = useState<HasherHelper>();
  26. const loadMd5Helper = useCallback(async () => {
  27. const mod = await import('crypto-js/md5');
  28. if (isMountedRef.current) {
  29. // XXX: Use function invocation of `useState`s setter since the mod.default
  30. // is a function itself.
  31. setMD5(() => mod.default);
  32. }
  33. }, [isMountedRef]);
  34. useEffect(() => {
  35. loadMd5Helper();
  36. }, [loadMd5Helper]);
  37. if (MD5 === undefined) {
  38. return null;
  39. }
  40. const query = qs.stringify({
  41. s: remoteSize,
  42. // If gravatar is not found we need the request to return an error,
  43. // otherwise error handler will not trigger and avatar will not have a display a LetterAvatar backup.
  44. d: placeholder ?? '404',
  45. });
  46. const gravatarBaseUrl = ConfigStore.get('gravatarBaseUrl');
  47. const md5 = MD5(gravatarId ?? '');
  48. const url = `${gravatarBaseUrl}/avatar/${md5}?${query}`;
  49. return (
  50. <Image
  51. round={round}
  52. src={url}
  53. onLoad={onLoad}
  54. onError={onError}
  55. suggested={suggested}
  56. />
  57. );
  58. }
  59. export default Gravatar;
  60. const Image = styled('img')<ImageStyleProps>`
  61. ${imageStyle};
  62. `;