diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index 765c74a36d..b3a62896b2 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -36,6 +36,10 @@ $timelineImageBorderRadius: 4px; animation: mx--anim-pulse 1.75s infinite cubic-bezier(.4, 0, .6, 1); border-radius: $timelineImageBorderRadius; } + + .mx_no-image-placeholder { + background-color: $primary-bg-color; + } } .mx_MImageBody_thumbnail_container { diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index e7b77b731f..286d420c58 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -47,6 +47,7 @@ interface IState { }; hover: boolean; showImage: boolean; + placeholder: 'no-image' | 'blurhash'; } @replaceableComponent("views.messages.MImageBody") @@ -68,6 +69,7 @@ export default class MImageBody extends React.Component { loadedImageDimensions: null, hover: false, showImage: SettingsStore.getValue("showImages"), + placeholder: 'no-image', }; } @@ -277,6 +279,17 @@ export default class MImageBody extends React.Component { this.downloadImage(); this.setState({ showImage: true }); } // else don't download anything because we don't want to display anything. + + // Add a 150ms timer for blurhash to first appear. + if (this.media.isEncrypted) { + setTimeout(() => { + if (!this.state.imgLoaded || !this.state.imgError) { + this.setState({ + placeholder: 'blurhash', + }); + } + }, 150); + } } componentWillUnmount() { @@ -434,7 +447,14 @@ export default class MImageBody extends React.Component { // Overidden by MStickerBody protected getPlaceholder(width: number, height: number): JSX.Element { const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD]; - if (blurhash) return ; + + if (blurhash) { + if (this.state.placeholder === 'no-image') { + return
; + } else if (this.state.placeholder === 'blurhash') { + return ; + } + } return ( );