diff --git a/web/avatars/avatar.react.js b/web/avatars/avatar.react.js
index 8bac4add9..462978706 100644
--- a/web/avatars/avatar.react.js
+++ b/web/avatars/avatar.react.js
@@ -1,103 +1,119 @@
// @flow
import classnames from 'classnames';
import * as React from 'react';
import type {
ResolvedClientAvatar,
AvatarSize,
} from 'lib/types/avatar-types.js';
import css from './avatar.css';
import LoadingIndicator from '../loading-indicator.react.js';
+import EncryptedMultimedia from '../media/encrypted-multimedia.react.js';
type Props = {
+avatarInfo: ResolvedClientAvatar,
+size: AvatarSize,
+showSpinner?: boolean,
};
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(
+ () => (
+
+
+
+ ),
+ [loadingIndicatorSize],
+ );
+
const containerSizeClassName = classnames({
[css.imgContainer]: avatarInfo.type === 'image',
[css.xSmall]: size === 'XS',
[css.small]: size === 'S',
[css.medium]: size === 'M',
[css.large]: size === 'L',
[css.xLarge]: size === 'XL',
[css.xxLarge]: size === 'XXL',
});
const emojiSizeClassName = classnames({
[css.emojiContainer]: true,
[css.emojiXSmall]: size === 'XS',
[css.emojiSmall]: size === 'S',
[css.emojiMedium]: size === 'M',
[css.emojiLarge]: size === 'L',
[css.emojiXLarge]: size === 'XL',
[css.emojiXXLarge]: size === 'XXL',
});
const emojiContainerColorStyle = React.useMemo(() => {
if (avatarInfo.type === 'emoji') {
return { backgroundColor: `#${avatarInfo.color}` };
}
return undefined;
}, [avatarInfo.color, avatarInfo.type]);
const avatar = React.useMemo(() => {
if (avatarInfo.type === 'image') {
return (
);
+ } else if (avatarInfo.type === 'encrypted_image') {
+ return (
+
+ );
}
return (
);
}, [
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(
- () => (
-
-
-
- ),
- [loadingIndicatorSize],
- );
-
return (
{showSpinner ? loadingIndicator : null}
{avatar}
);
}
export default Avatar;
diff --git a/web/media/encrypted-multimedia.react.js b/web/media/encrypted-multimedia.react.js
index b4ebc4bef..2ea2dd11f 100644
--- a/web/media/encrypted-multimedia.react.js
+++ b/web/media/encrypted-multimedia.react.js
@@ -1,135 +1,140 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import 'react-circular-progressbar/dist/styles.css';
import { AlertCircle as AlertCircleIcon } from 'react-feather';
import type { Shape } from 'lib/types/core.js';
import type { EncryptedMediaType } from 'lib/types/media-types.js';
import { decryptMedia } from './encryption-utils.js';
import LoadableVideo from './loadable-video.react.js';
import css from './media.css';
import LoadingIndicator from '../loading-indicator.react.js';
import type { CSSStyle } from '../types/styles';
type Props = {
+blobURI: string,
+encryptionKey: string,
+type: EncryptedMediaType,
+thumbnailBlobURI?: ?string,
+thumbnailEncryptionKey?: ?string,
+placeholderSrc?: ?string,
+multimediaClassName?: string,
+elementStyle?: ?Shape,
+ // 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 {
const {
blobURI,
encryptionKey,
placeholderSrc,
elementStyle,
multimediaClassName,
+ invisibleLoad,
} = props;
const [source, setSource] = React.useState(null);
const videoRef = React.useRef(null);
React.useEffect(() => {
let isMounted = true,
uriToDispose;
setSource(null);
const loadDecrypted = async () => {
const { result } = await decryptMedia(blobURI, encryptionKey);
if (!isMounted) {
return;
}
if (result.success) {
const { uri } = result;
setSource({ uri });
uriToDispose = uri;
} else {
setSource({ error: result.reason });
}
};
loadDecrypted();
return () => {
isMounted = false;
if (uriToDispose) {
URL.revokeObjectURL(uriToDispose);
}
};
}, [blobURI, encryptionKey]);
// we need to update the video source when the source changes
// because re-rendering the