Fix: Images no longer reserve their space in the timeline correctly (#10571)
* test case * fix + lint * refix strictNullChecks issue * add comment about max image size * tweak * use safer magic numberpull/28788/head^2
parent
9b8459e8e9
commit
6280395928
|
@ -385,22 +385,24 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected messageContent(
|
protected messageContent(
|
||||||
contentUrl: string,
|
contentUrl: string | null,
|
||||||
thumbUrl: string | null,
|
thumbUrl: string | null,
|
||||||
content: IMediaEventContent,
|
content: IMediaEventContent,
|
||||||
forcedHeight?: number,
|
forcedHeight?: number,
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
if (!thumbUrl) thumbUrl = contentUrl; // fallback
|
if (!thumbUrl) thumbUrl = contentUrl; // fallback
|
||||||
|
|
||||||
let infoWidth: number;
|
// magic number
|
||||||
let infoHeight: number;
|
// edge case for this not to be set by conditions below
|
||||||
|
let infoWidth = 500;
|
||||||
|
let infoHeight = 500;
|
||||||
let infoSvg = false;
|
let infoSvg = false;
|
||||||
|
|
||||||
if (content.info?.w && content.info?.h) {
|
if (content.info?.w && content.info?.h) {
|
||||||
infoWidth = content.info.w;
|
infoWidth = content.info.w;
|
||||||
infoHeight = content.info.h;
|
infoHeight = content.info.h;
|
||||||
infoSvg = content.info.mimetype === "image/svg+xml";
|
infoSvg = content.info.mimetype === "image/svg+xml";
|
||||||
} else {
|
} else if (thumbUrl && contentUrl) {
|
||||||
// Whilst the image loads, display nothing. We also don't display a blurhash image
|
// Whilst the image loads, display nothing. We also don't display a blurhash image
|
||||||
// because we don't really know what size of image we'll end up with.
|
// because we don't really know what size of image we'll end up with.
|
||||||
//
|
//
|
||||||
|
@ -522,7 +524,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.wrapImage(contentUrl, thumbnail);
|
return contentUrl ? this.wrapImage(contentUrl, thumbnail) : thumbnail;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overridden by MStickerBody
|
// Overridden by MStickerBody
|
||||||
|
@ -596,7 +598,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
thumbUrl = this.state.thumbUrl ?? this.state.contentUrl;
|
thumbUrl = this.state.thumbUrl ?? this.state.contentUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thumbnail = contentUrl ? this.messageContent(contentUrl, thumbUrl, content) : undefined;
|
const thumbnail = this.messageContent(contentUrl, thumbUrl, content);
|
||||||
const fileBody = this.getFileBody();
|
const fileBody = this.getFileBody();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -61,6 +61,10 @@ describe("<MImageBody/>", () => {
|
||||||
sender: userId,
|
sender: userId,
|
||||||
type: EventType.RoomMessage,
|
type: EventType.RoomMessage,
|
||||||
content: {
|
content: {
|
||||||
|
info: {
|
||||||
|
w: 40,
|
||||||
|
h: 50,
|
||||||
|
},
|
||||||
file: {
|
file: {
|
||||||
url: "mxc://server/encrypted-image",
|
url: "mxc://server/encrypted-image",
|
||||||
},
|
},
|
||||||
|
@ -72,6 +76,21 @@ describe("<MImageBody/>", () => {
|
||||||
permalinkCreator: new RoomPermalinkCreator(new Room(encryptedMediaEvent.getRoomId()!, cli, cli.getUserId()!)),
|
permalinkCreator: new RoomPermalinkCreator(new Room(encryptedMediaEvent.getRoomId()!, cli, cli.getUserId()!)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
it("should show a thumbnail while image is being downloaded", async () => {
|
||||||
|
fetchMock.getOnce(url, { status: 200 });
|
||||||
|
|
||||||
|
const { container } = render(
|
||||||
|
<MImageBody
|
||||||
|
{...props}
|
||||||
|
mxEvent={encryptedMediaEvent}
|
||||||
|
mediaEventHelper={new MediaEventHelper(encryptedMediaEvent)}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// thumbnail with dimensions present
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
it("should show error when encrypted media cannot be downloaded", async () => {
|
it("should show error when encrypted media cannot be downloaded", async () => {
|
||||||
fetchMock.getOnce(url, { status: 500 });
|
fetchMock.getOnce(url, { status: 500 });
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<MImageBody/> should show a thumbnail while image is being downloaded 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_MImageBody"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_MImageBody_thumbnail_container"
|
||||||
|
style="max-height: 50px; max-width: 40px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_MImageBody_placeholder"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_Spinner"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-label="Loading…"
|
||||||
|
class="mx_Spinner_icon"
|
||||||
|
data-testid="spinner"
|
||||||
|
role="progressbar"
|
||||||
|
style="width: 32px; height: 32px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="max-height: 50px; max-width: 40px;"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style="height: 50px; width: 40px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
Loading…
Reference in New Issue