diff --git a/src/assets/images/broken-image-fallback.png b/src/assets/images/broken-image-fallback.png
new file mode 100644
index 00000000..84e828fb
Binary files /dev/null and b/src/assets/images/broken-image-fallback.png differ
diff --git a/src/assets/symbols.svg b/src/assets/symbols.svg
index 87d63361..c9fda729 100644
--- a/src/assets/symbols.svg
+++ b/src/assets/symbols.svg
@@ -170,8 +170,11 @@
-
-
+
+
+
+
+
diff --git a/src/shared/components/common/pictrs-image.tsx b/src/shared/components/common/pictrs-image.tsx
index 9a5f450e..d942aba6 100644
--- a/src/shared/components/common/pictrs-image.tsx
+++ b/src/shared/components/common/pictrs-image.tsx
@@ -1,9 +1,10 @@
import classNames from "classnames";
-import { Component } from "inferno";
+import { Component, linkEvent } from "inferno";
import { UserService } from "../../services";
import { setIsoData } from "@utils/app";
import { IsoData } from "../../interfaces";
+import { getStaticDir } from "@utils/env";
const iconThumbnailSize = 96;
const thumbnailSize = 256;
@@ -20,13 +21,35 @@ interface PictrsImageProps {
cardTop?: boolean;
}
-export class PictrsImage extends Component {
+interface PictrsImageState {
+ src: string;
+}
+
+function handleImgLoadError(i: PictrsImage) {
+ i.setState({
+ src: `${getStaticDir()}/assets/images/broken-image-fallback.png`,
+ });
+}
+
+export class PictrsImage extends Component {
private readonly isoData: IsoData = setIsoData(this.context);
+ state: PictrsImageState = {
+ src: this.props.src,
+ };
+
+ componentDidUpdate(prevProps: PictrsImageProps) {
+ if (prevProps.src !== this.props.src) {
+ this.setState({ src: this.props.src });
+ }
+ }
+
render() {
- const { src, icon, iconOverlay, banner, thumbnail, nsfw, pushup, cardTop } =
+ const { icon, iconOverlay, banner, thumbnail, nsfw, pushup, cardTop } =
this.props;
+ const { src } = this.state;
+
const blurImage =
nsfw &&
(UserService.Instance.myUserInfo?.local_user_view.local_user.blur_nsfw ??
@@ -58,6 +81,7 @@ export class PictrsImage extends Component {
"avatar-pushup": pushup,
"card-img-top": cardTop,
})}
+ onError={linkEvent(this, handleImgLoadError)}
/>
)
@@ -70,14 +94,14 @@ export class PictrsImage extends Component {
let url: URL | undefined;
try {
- url = new URL(this.props.src);
+ url = new URL(this.state.src);
} catch {
- return this.props.src;
+ return this.state.src;
}
// If there's no match, then it's not a pictrs image
if (!url.pathname.includes("/pictrs/image/")) {
- return this.props.src;
+ return this.state.src;
}
// Keeps original search params. Could probably do `url.search = ""` here.