import {useCallback, useEffect, useRef, useState} from 'react'; import styled from '@emotion/styled'; import * as qs from 'query-string'; import ConfigStore from 'sentry/stores/configStore'; import {imageStyle, ImageStyleProps} from './styles'; type Props = { remoteSize: number; gravatarId?: string; onError?: () => void; onLoad?: () => void; placeholder?: string; } & ImageStyleProps; type HasherHelper = typeof import('crypto-js/md5'); function Gravatar({ remoteSize, gravatarId, placeholder, round, onError, onLoad, suggested, }: Props) { const isMounted = useRef(false); const [MD5, setMD5] = useState(); const loadMd5Helper = useCallback(async () => { const mod = await import('crypto-js/md5'); if (isMounted.current) { // XXX: Use function invocation of `useState`s setter since the mod.default // is a function itself. setMD5(() => mod.default); } }, []); useEffect(() => { isMounted.current = true; loadMd5Helper(); return () => { isMounted.current = false; }; }, [loadMd5Helper]); if (MD5 === undefined) { return null; } const query = qs.stringify({ s: remoteSize, // If gravatar is not found we need the request to return an error, // otherwise error handler will not trigger and avatar will not have a display a LetterAvatar backup. d: placeholder ?? '404', }); const gravatarBaseUrl = ConfigStore.get('gravatarBaseUrl'); const md5 = MD5(gravatarId ?? ''); const url = `${gravatarBaseUrl}/avatar/${md5}?${query}`; return ( ); } export default Gravatar; const Image = styled('img')` ${imageStyle}; `;