gravatar.tsx 1.8 KB

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