Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/components/ImageWithLoading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ type ImageWithSizeLoadingProps = {

/** Invoked on mount and layout changes */
onLayout?: (event: LayoutChangeEvent) => void;

/** Low-resolution URI shown as a placeholder while the full image loads */
previewUri?: string;
} & ImageProps;

function ImageWithLoading({
Expand All @@ -37,12 +40,14 @@ function ImageWithLoading({
onLoad,
onLayout,
style,
previewUri,
...rest
}: ImageWithSizeLoadingProps) {
const styles = useThemeStyles();
const isLoadedRef = useRef<boolean | null>(null);
const [isImageCached, setIsImageCached] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [isThumbnailLoading, setIsThumbnailLoading] = useState(!!previewUri);
const {isOffline} = useNetwork();

const handleError = () => {
Expand Down Expand Up @@ -83,6 +88,21 @@ function ImageWithLoading({
style={[styles.w100, styles.h100, containerStyles]}
onLayout={onLayout}
>
Comment thread
sosek108 marked this conversation as resolved.
{isLoading && !!previewUri && (
// eslint-disable-next-line react-native-a11y/has-valid-accessibility-ignores-invert-colors -- Custom Image wrapper does not support this prop.
<Image
{...rest}
source={{uri: previewUri}}
style={[styles.w100, styles.h100, style]}
resizeMode={resizeMode}
onLoad={(e) => {
setIsThumbnailLoading(false);
onLoad?.(e);
Comment thread
sosek108 marked this conversation as resolved.
}}
loadingIconSize={loadingIconSize}
loadingIndicatorStyles={loadingIndicatorStyles}
/>
)}
{/* eslint-disable-next-line react-native-a11y/has-valid-accessibility-ignores-invert-colors -- Custom Image wrapper does not support this prop. */}
<Image
{...rest}
Expand All @@ -104,12 +124,13 @@ function ImageWithLoading({
isLoadedRef.current = false;
setIsImageCached(false);
setIsLoading(true);
setIsThumbnailLoading(!!previewUri);
waitForSession?.();
}}
loadingIconSize={loadingIconSize}
loadingIndicatorStyles={loadingIndicatorStyles}
/>
{isLoading && !isImageCached && !isOffline && (
{isLoading && (!previewUri || isThumbnailLoading) && !isImageCached && !isOffline && (
Comment thread
sosek108 marked this conversation as resolved.
<LoadingIndicator
iconSize={loadingIconSize}
style={[styles.opacity1, styles.bgTransparent, loadingIndicatorStyles]}
Expand Down
5 changes: 5 additions & 0 deletions src/components/ImageWithSizeCalculation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ type ImageWithSizeCalculationProps = {

/** Reason attributes for skeleton span telemetry */
reasonAttributes?: SkeletonSpanReasonAttributes;

/** Low-resolution URI shown as a placeholder while the full image loads */
previewUri?: string;
};

/**
Expand All @@ -74,6 +77,7 @@ function ImageWithSizeCalculation({
onLoad,
resizeMode,
reasonAttributes,
previewUri,
}: ImageWithSizeCalculationProps) {
const styles = useThemeStyles();

Expand Down Expand Up @@ -104,6 +108,7 @@ function ImageWithSizeCalculation({
loadingIconSize={loadingIconSize}
loadingIndicatorStyles={loadingIndicatorStyles}
reasonAttributes={reasonAttributes}
previewUri={previewUri}
/>
);
}
Expand Down
6 changes: 6 additions & 0 deletions src/components/ReceiptImage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ type ReceiptImageProps = (

/** Any additional styles to apply */
style?: StyleProp<ViewStyle & ImageStyle>;

/** Low-resolution URI shown as a placeholder while the full image loads */
previewUri?: string;
};

function ReceiptImage({
Expand Down Expand Up @@ -161,6 +164,7 @@ function ReceiptImage({
onLoadFailure,
resizeMode,
style,
previewUri,
}: ReceiptImageProps) {
const styles = useThemeStyles();
const [receiptImageWidth, setReceiptImageWidth] = useState<number | undefined>(undefined);
Expand Down Expand Up @@ -216,6 +220,7 @@ function ReceiptImage({
return (
<ThumbnailImage
previewSourceURL={source ?? ''}
previewUri={previewUri}
style={[styles.w100, styles.h100, style, thumbnailContainerStyles]}
isAuthTokenRequired={isAuthTokenRequired ?? false}
shouldDynamicallyResize={false}
Expand Down Expand Up @@ -255,6 +260,7 @@ function ReceiptImage({
onError={onLoadFailure}
resizeMode={resizeMode}
reasonAttributes={reasonAttributes}
previewUri={previewUri}
/>
);
}
Expand Down
6 changes: 6 additions & 0 deletions src/components/ReportActionItem/ReportActionItemImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import {getReportIDForExpense} from '@libs/MergeTransactionUtils';
import Navigation from '@libs/Navigation/Navigation';
import {getThumbnailAndImageURIs} from '@libs/ReceiptUtils';
import {hasEReceipt, hasReceiptSource, isDistanceRequest, isFetchingWaypointsFromServer, isManualDistanceRequest, isPerDiemRequest} from '@libs/TransactionUtils';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
import variables from '@styles/variables';
Expand Down Expand Up @@ -142,10 +143,13 @@ function ReportActionItemImage({
const localSource = transaction?.receipt?.localSource;
const effectiveIsLocalFile = isLocalFile || !!localSource;
const effectiveThumbnail = localSource ?? thumbnail;
const receiptURIs = transaction ? getThumbnailAndImageURIs(transaction, null, null) : undefined;
const effectivePreviewUri = localSource ? undefined : receiptURIs?.thumbnail320;
const effectiveImage = localSource != null && typeof image === 'string' ? localSource : image;

const originalImageSource = tryResolveUrlFromApiRoot(effectiveImage ?? '');
const thumbnailSource = tryResolveUrlFromApiRoot(effectiveThumbnail ?? '');
const previewUriSource = effectivePreviewUri ? tryResolveUrlFromApiRoot(effectivePreviewUri) : undefined;
const isEReceipt = transaction && !hasReceiptSource(transaction) && hasEReceipt(transaction);
const isPDF = filename && Str.isPDF(filename);

Expand Down Expand Up @@ -207,6 +211,7 @@ function ReportActionItemImage({
onLoad={onLoad}
shouldUseFullHeight={shouldUseFullHeight}
onLoadFailure={onLoadFailure}
previewUri={previewUriSource}
/>
</PressableWithoutFocus>
);
Expand All @@ -219,6 +224,7 @@ function ReportActionItemImage({
thumbnailContainerStyles={styles.thumbnailImageContainerHover}
onLoad={onLoad}
onLoadFailure={onLoadFailure}
previewUri={previewUriSource}
/>
);
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/ThumbnailImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ type ThumbnailImageProps = {

/** Reason attributes for skeleton span telemetry */
reasonAttributes?: SkeletonSpanReasonAttributes;

/** Low-resolution URI shown as a placeholder while the full image loads */
previewUri?: string;
};

function ThumbnailImage({
Expand All @@ -106,6 +109,7 @@ function ThumbnailImage({
onLoad,
resizeMode,
reasonAttributes,
previewUri,
}: ThumbnailImageProps) {
const icons = useMemoizedLazyExpensifyIcons(['Gallery', 'OfflineCloud']);
const styles = useThemeStyles();
Expand Down Expand Up @@ -172,6 +176,7 @@ function ThumbnailImage({
onLoad={onLoad}
resizeMode={resizeMode}
reasonAttributes={reasonAttributes}
previewUri={previewUri}
/>
</View>
</View>
Expand Down
Loading