Skip to content

Disable image preview for invalid images #23103

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ const propTypes = {
...withLocalizePropTypes,
};

function AttachmentViewImage({source, file, isAuthTokenRequired, loadComplete, onPress, isImage, onScaleChanged, translate}) {
function AttachmentViewImage({source, file, isAuthTokenRequired, loadComplete, onPress, onError, isImage, onScaleChanged, translate}) {
const children = (
<ImageView
onScaleChanged={onScaleChanged}
url={source}
fileName={file.name}
isAuthTokenRequired={isImage && isAuthTokenRequired}
onError={onError}
/>
);
return onPress ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const propTypes = {
...withLocalizePropTypes,
};

function AttachmentViewImage({source, file, isAuthTokenRequired, isFocused, isUsedInCarousel, loadComplete, onPress, isImage, onScaleChanged, translate}) {
function AttachmentViewImage({source, file, isAuthTokenRequired, isFocused, isUsedInCarousel, loadComplete, onPress, onError, isImage, onScaleChanged, translate}) {
const children = isUsedInCarousel ? (
<AttachmentCarouselPage
source={source}
Expand All @@ -26,6 +26,7 @@ function AttachmentViewImage({source, file, isAuthTokenRequired, isFocused, isUs
onScaleChanged={onScaleChanged}
url={source}
fileName={file.name}
onError={onError}
isAuthTokenRequired={isImage && isAuthTokenRequired}
/>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/Attachments/AttachmentView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function AttachmentView({
isFocused,
}) {
const [loadComplete, setLoadComplete] = useState(false);
const [isValidImage, setIsValidImage] = useState(true);

// Handles case where source is a component (ex: SVG)
if (_.isFunction(source)) {
Expand Down Expand Up @@ -95,7 +96,7 @@ function AttachmentView({
// For this check we use both source and file.name since temporary file source is a blob
// both PDFs and images will appear as images when pasted into the the text field
const isImage = Str.isImage(source);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aimane-chnaif I wonder why this isn't ìsImage = Str.isImage(source) || (file && Str.isImage(file.name)) then next we can just use if (isImage && isValidImage), am I missing something on why this could be intentional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc: @chrispader as this logic was added in #20798

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually just taking over the original logic from the previous code: https://github.com/margelo/expensify-app-fork/blob/9fa8c89b095d88b4066f209c16d34e3ee261e991/src/components/AttachmentView.js#L105-L106

I think the difference here is that we first check if the source is an image, else if there is a file prop and if that's an image. Not sure if this is intentional though, so i think somebody else has to answer this question. :)

if (isImage || (file && Str.isImage(file.name))) {
if ((isImage || (file && Str.isImage(file.name))) && isValidImage) {
return (
<AttachmentViewImage
source={source}
Expand All @@ -105,6 +106,7 @@ function AttachmentView({
loadComplete={loadComplete}
isFocused={isFocused}
isImage={isImage}
onError={() => setIsValidImage(false)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Receiving onError callback doesn't always mean that image is invalid.
i.e. when offline:

Screen.Recording.2023-08-27.at.5.50.53.PM.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking into this

onPress={onPress}
onScaleChanged={onScaleChanged}
/>
Expand Down
2 changes: 2 additions & 0 deletions src/components/ImageView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ class ImageView extends PureComponent {
resizeMode={this.state.zoomScale > 1 ? Image.resizeMode.center : Image.resizeMode.contain}
onLoadStart={this.imageLoadingStart}
onLoad={this.imageLoad}
onError={this.props.onError}
/>
{this.state.isLoading && <FullscreenLoadingIndicator style={[styles.opacity1, styles.bgTransparent]} />}
</View>
Expand Down Expand Up @@ -299,6 +300,7 @@ class ImageView extends PureComponent {
resizeMode={Image.resizeMode.contain}
onLoadStart={this.imageLoadingStart}
onLoad={this.imageLoad}
onError={this.props.onError}
/>
</PressableWithoutFeedback>

Expand Down
1 change: 1 addition & 0 deletions src/components/ImageView/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ class ImageView extends PureComponent {
resizeMode={Image.resizeMode.contain}
onLoadStart={this.imageLoadingStart}
onLoad={this.configureImageZoom}
onError={this.props.onError}
/>
{/**
Create an invisible view on top of the image so we can capture and set the amount of touches before
Expand Down