diff --git a/assets/images/gallery-not-found.svg b/assets/images/gallery-not-found.svg
new file mode 100644
index 000000000000..25da973ce9cb
--- /dev/null
+++ b/assets/images/gallery-not-found.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/src/components/AttachmentOfflineIndicator.tsx b/src/components/AttachmentOfflineIndicator.tsx
index d425e6f18e0e..4ff1940ba004 100644
--- a/src/components/AttachmentOfflineIndicator.tsx
+++ b/src/components/AttachmentOfflineIndicator.tsx
@@ -37,7 +37,7 @@ function AttachmentOfflineIndicator({isPreview = false}: AttachmentOfflineIndica
return (
setHasLoadFailed(true)}
+ onMeasure={() => setHasLoadFailed(false)}
+ fallbackIconBackground={theme.highlightBG}
+ fallbackIconColor={theme.border}
/>
);
@@ -102,6 +110,7 @@ function ImageRenderer({tnode}: ImageRendererProps) {
shouldUseHapticsOnLongPress
accessibilityRole={CONST.ROLE.BUTTON}
accessibilityLabel={translate('accessibilityHints.viewAttachment')}
+ disabled={hasLoadFailed}
>
{thumbnailImageComponent}
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index cd9c97105ff0..90f0e0d8a151 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -93,6 +93,7 @@ import FlagLevelTwo from '@assets/images/flag_level_02.svg';
import FlagLevelThree from '@assets/images/flag_level_03.svg';
import Folder from '@assets/images/folder.svg';
import Fullscreen from '@assets/images/fullscreen.svg';
+import GalleryNotFound from '@assets/images/gallery-not-found.svg';
import Gallery from '@assets/images/gallery.svg';
import Gear from '@assets/images/gear.svg';
import Globe from '@assets/images/globe.svg';
@@ -404,4 +405,5 @@ export {
Bookmark,
Star,
QBDSquare,
+ GalleryNotFound,
};
diff --git a/src/components/ThumbnailImage.tsx b/src/components/ThumbnailImage.tsx
index cea528e4537c..f283058042eb 100644
--- a/src/components/ThumbnailImage.tsx
+++ b/src/components/ThumbnailImage.tsx
@@ -55,6 +55,12 @@ type ThumbnailImageProps = {
/** The object position of image */
objectPosition?: ImageObjectPosition;
+
+ /** Callback fired when the image fails to load */
+ onLoadFailure?: () => void;
+
+ /** Callback fired when the image has been measured */
+ onMeasure?: () => void;
};
type UpdateImageSizeParams = {
@@ -75,6 +81,8 @@ function ThumbnailImage({
fallbackIconColor,
fallbackIconBackground,
objectPosition = CONST.IMAGE_OBJECT_POSITION.INITIAL,
+ onLoadFailure,
+ onMeasure,
}: ThumbnailImageProps) {
const styles = useThemeStyles();
const theme = useTheme();
@@ -137,8 +145,14 @@ function ThumbnailImage({
setFailedToLoad(true)}
+ onMeasure={(args) => {
+ updateImageSize(args);
+ onMeasure?.();
+ }}
+ onLoadFailure={() => {
+ setFailedToLoad(true);
+ onLoadFailure?.();
+ }}
isAuthTokenRequired={isAuthTokenRequired}
objectPosition={objectPosition}
/>