diff --git a/web/avatars/avatar.react.js b/web/avatars/avatar.react.js --- a/web/avatars/avatar.react.js +++ b/web/avatars/avatar.react.js @@ -10,6 +10,7 @@ import css from './avatar.css'; import LoadingIndicator from '../loading-indicator.react.js'; +import EncryptedMultimedia from '../media/encrypted-multimedia.react.js'; type Props = { +avatarInfo: ResolvedClientAvatar, @@ -20,6 +21,26 @@ function Avatar(props: Props): React.Node { const { avatarInfo, size, showSpinner } = props; + let loadingIndicatorSize; + if (size === 'XS') { + loadingIndicatorSize = 'small'; + } else if (size === 'S') { + loadingIndicatorSize = 'small'; + } else if (size === 'M') { + loadingIndicatorSize = 'medium'; + } else { + loadingIndicatorSize = 'large'; + } + + const loadingIndicator = React.useMemo( + () => ( + <div className={css.editAvatarLoadingSpinner}> + <LoadingIndicator status="loading" size={loadingIndicatorSize} /> + </div> + ), + [loadingIndicatorSize], + ); + const containerSizeClassName = classnames({ [css.imgContainer]: avatarInfo.type === 'image', [css.xSmall]: size === 'XS', @@ -56,6 +77,17 @@ className={containerSizeClassName} /> ); + } else if (avatarInfo.type === 'encrypted_image') { + return ( + <EncryptedMultimedia + type="encrypted_photo" + blobURI={avatarInfo.blobURI} + encryptionKey={avatarInfo.encryptionKey} + multimediaClassName={containerSizeClassName} + loadingIndicatorComponent={loadingIndicator} + invisibleLoad={showSpinner} + /> + ); } return ( @@ -67,31 +99,15 @@ avatarInfo.emoji, avatarInfo.type, avatarInfo.uri, + avatarInfo.blobURI, + avatarInfo.encryptionKey, + showSpinner, + loadingIndicator, containerSizeClassName, emojiContainerColorStyle, emojiSizeClassName, ]); - let loadingIndicatorSize; - if (size === 'XS') { - loadingIndicatorSize = 'small'; - } else if (size === 'S') { - loadingIndicatorSize = 'small'; - } else if (size === 'M') { - loadingIndicatorSize = 'medium'; - } else { - loadingIndicatorSize = 'large'; - } - - const loadingIndicator = React.useMemo( - () => ( - <div className={css.editAvatarLoadingSpinner}> - <LoadingIndicator status="loading" size={loadingIndicatorSize} /> - </div> - ), - [loadingIndicatorSize], - ); - return ( <div className={css.avatarContainer}> {showSpinner ? loadingIndicator : null} diff --git a/web/media/encrypted-multimedia.react.js b/web/media/encrypted-multimedia.react.js --- a/web/media/encrypted-multimedia.react.js +++ b/web/media/encrypted-multimedia.react.js @@ -23,6 +23,10 @@ +placeholderSrc?: ?string, +multimediaClassName?: string, +elementStyle?: ?Shape<CSSStyle>, + // if provided, this component will be shown instead of the loading indicator + +loadingIndicatorComponent?: React.Node, + // if true, the loading indicator will not be shown + +invisibleLoad?: boolean, }; function EncryptedMultimedia(props: Props): React.Node { @@ -32,6 +36,7 @@ placeholderSrc, elementStyle, multimediaClassName, + invisibleLoad, } = props; const [source, setSource] = React.useState(null); @@ -78,8 +83,8 @@ let loadingIndicator, errorIndicator; - if (!source) { - loadingIndicator = ( + if (!source && !invisibleLoad) { + loadingIndicator = props.loadingIndicatorComponent ?? ( <LoadingIndicator status="loading" size="large" diff --git a/web/package.json b/web/package.json --- a/web/package.json +++ b/web/package.json @@ -106,7 +106,7 @@ "\\.js$": "babel-jest" }, "transformIgnorePatterns": [ - "/node_modules/(?!@babel/runtime)" + "/node_modules/(?!(@babel/runtime|thumbhash))" ], "moduleNameMapper": { "\\.(css)$": "identity-obj-proxy"