Skip to content

Commit

Permalink
fix: provideEmbeddedHeaders results in failing fetch for img
Browse files Browse the repository at this point in the history
fix #533
  • Loading branch information
jsamr committed Nov 3, 2021
1 parent 8f98f8a commit 5488259
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 101 deletions.
6 changes: 3 additions & 3 deletions packages/render-html/src/__mocks__/react-native.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ export class Image extends RNImage {
* be extracted, it will use 640x360.
*/
static getSizeWithHeaders(uri, headers, success, failure) {
getSizeWithHeaders(uri, headers, callback, failure);
getSizeWithHeaders(uri, headers, success, failure);
}

static getSize(uri, callback, failure) {
getSizeWithHeaders(uri, undefined, callback, failure);
static getSize(uri, success, failure) {
getSizeWithHeaders(uri, undefined, success, failure);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,9 @@ describe('RenderHTML', () => {
expect(image.props.source.headers).toBe(headers);
expect(getSizeWithHeaders).toHaveBeenCalledWith(
'https://custom.domain/',
headers
headers,
expect.anything(),
expect.anything()
);
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/render-html/src/elements/getIMGState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface GetStateProps<C> extends Omit<IMGElementStateBase, 'dimensions'> {
error: Error | null;
initialDimensions: ImageDimensions;
objectFit: UseIMGElementStateProps['objectFit'];
onError: (e: Error) => void;
onError?: (e: Error) => void;
}

export function getIMGState(
Expand Down
8 changes: 8 additions & 0 deletions packages/render-html/src/elements/img-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,11 @@ export interface IMGElementStateError extends IMGElementStateBase {
error: Error;
type: 'error';
}

/**
* Partial image dimensions.
*/
export interface IncompleteImageDimensions {
height: number | null;
width: number | null;
}
85 changes: 62 additions & 23 deletions packages/render-html/src/elements/useIMGElementState.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { useEffect } from 'react';
import { Image } from 'react-native';
import type { UseIMGElementStateProps, IMGElementState } from './img-types';
import useImageNaturalDimensions from './useImageNaturalDimensions';
import useImageConcreteDimensions from './useImageConcreteDimensions';
import { useEffect, useState } from 'react';
import { Image, ImageURISource } from 'react-native';
import {
UseIMGElementStateProps,
IMGElementState,
IncompleteImageDimensions
} from './img-types';
import defaultImageInitialDimensions from './defaultInitialImageDimensions';
import useIMGNormalizedSource from './useIMGNormalizedSource';
import { ImageDimensions } from '../shared-types';
import useImageConcreteDimensions from './useImageConcreteDimensions';
import { getIMGState } from './getIMGState';
import useIMGNormalizedSource from './useIMGNormalizedSource';
import useImageSpecifiedDimensions from './useImageSpecifiedDimensions';

function getImageSizeAsync({
uri,
Expand All @@ -26,16 +30,47 @@ function getImageSizeAsync({
});
}

function useFetchedNaturalDimensions(props: UseIMGElementStateProps) {
function useImageNaturalDimensions<P extends UseIMGElementStateProps>(props: {
cachedNaturalDimensions?: ImageDimensions;
source: ImageURISource;
specifiedDimensions: IncompleteImageDimensions;
}) {
const { source, cachedNaturalDimensions } = props;
const {
error,
flatStyle,
const [naturalDimensions, setNaturalDimensions] = useState<
P['cachedNaturalDimensions'] extends ImageDimensions
? ImageDimensions
: ImageDimensions | null
>((cachedNaturalDimensions as any) || null);
const { width: cachedNaturalWidth, height: cachedNaturalHeight } =
cachedNaturalDimensions || {};
const [error, setError] = useState<null | Error>(null);
useEffect(
function resetOnURIChange() {
setNaturalDimensions(
(cachedNaturalWidth != null && cachedNaturalHeight != null
? { width: cachedNaturalWidth, height: cachedNaturalHeight }
: null) as any
);
setError(null);
},
[cachedNaturalHeight, cachedNaturalWidth, source.uri]
);
return {
onNaturalDimensions: setNaturalDimensions,
onError: setError,
naturalDimensions,
specifiedDimensions,
onError,
onNaturalDimensions
} = useImageNaturalDimensions(props);
error
};
}

function useFetchedNaturalDimensions(props: {
cachedNaturalDimensions?: ImageDimensions;
source: ImageURISource;
specifiedDimensions: IncompleteImageDimensions;
}) {
const { source, cachedNaturalDimensions } = props;
const { error, naturalDimensions, onError, onNaturalDimensions } =
useImageNaturalDimensions(props);
const hasCachedDimensions = !!cachedNaturalDimensions;
useEffect(
function fetchPhysicalDimensions() {
Expand All @@ -58,8 +93,6 @@ function useFetchedNaturalDimensions(props: UseIMGElementStateProps) {
]
);
return {
specifiedDimensions,
flatStyle,
naturalDimensions,
error,
onError,
Expand All @@ -85,21 +118,27 @@ export default function useIMGElementState(
contentWidth,
computeMaxWidth,
objectFit,
initialDimensions = defaultImageInitialDimensions
initialDimensions = defaultImageInitialDimensions,
cachedNaturalDimensions
} = props;
const { naturalDimensions, specifiedDimensions, flatStyle, onError, error } =
useFetchedNaturalDimensions(props);
const { flatStyle, specifiedDimensions } = useImageSpecifiedDimensions(props);
const nomalizedSource = useIMGNormalizedSource({
specifiedDimensions,
source
});
const { naturalDimensions, onError, error } = useFetchedNaturalDimensions({
source: nomalizedSource,
specifiedDimensions,
cachedNaturalDimensions
});
const concreteDimensions = useImageConcreteDimensions({
flatStyle,
naturalDimensions,
specifiedDimensions,
computeMaxWidth,
contentWidth
});
const nomalizedSource = useIMGNormalizedSource({
concreteDimensions,
source
});

return getIMGState({
error,
alt,
Expand Down
22 changes: 11 additions & 11 deletions packages/render-html/src/elements/useIMGElementStateWithCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
IMGElementStateSuccess
} from './img-types';
import useImageConcreteDimensions from './useImageConcreteDimensions';
import useImageNaturalDimensions from './useImageNaturalDimensions';
import useImageSpecifiedDimensions from './useImageSpecifiedDimensions';
import useIMGNormalizedSource from './useIMGNormalizedSource';

/**
Expand All @@ -24,28 +24,28 @@ export default function useIMGElementStateWithCache(
contentWidth,
computeMaxWidth,
objectFit,
initialDimensions = defaultImageInitialDimensions
initialDimensions = defaultImageInitialDimensions,
cachedNaturalDimensions
} = props;
const { naturalDimensions, specifiedDimensions, flatStyle, error, onError } =
useImageNaturalDimensions(props);
const { flatStyle, specifiedDimensions } = useImageSpecifiedDimensions(props);
const nomalizedSource = useIMGNormalizedSource({
specifiedDimensions,
source
});
const concreteDimensions = useImageConcreteDimensions({
flatStyle,
naturalDimensions,
naturalDimensions: cachedNaturalDimensions,
specifiedDimensions,
computeMaxWidth,
contentWidth
});
const nomalizedSource = useIMGNormalizedSource({
concreteDimensions,
source
});

return getIMGState({
error,
error: null,
concreteDimensions,
containerStyle: flatStyle,
initialDimensions,
objectFit,
onError,
source: nomalizedSource,
alt,
altColor
Expand Down
16 changes: 9 additions & 7 deletions packages/render-html/src/elements/useIMGNormalizedSource.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { useMemo, useRef } from 'react';
import { useSharedProps } from '../context/SharedPropsProvider';
import { ImageDimensions } from '../shared-types';
import { UseIMGElementStateProps } from './img-types';
import {
IncompleteImageDimensions,
UseIMGElementStateProps
} from './img-types';

export default function useIMGNormalizedSource({
source,
concreteDimensions
specifiedDimensions
}: Pick<UseIMGElementStateProps, 'source'> & {
concreteDimensions: ImageDimensions | null;
specifiedDimensions: IncompleteImageDimensions;
}) {
const cachedDimensions = useRef(concreteDimensions);
const cachedDimensions = useRef(specifiedDimensions);
const { provideEmbeddedHeaders } = useSharedProps();
return useMemo(() => {
if (source.uri && typeof provideEmbeddedHeaders === 'function') {
const headers = provideEmbeddedHeaders(source.uri, 'img', {
printWidth: cachedDimensions.current?.width,
printHeight: cachedDimensions.current?.height
printWidth: cachedDimensions.current?.width || undefined,
printHeight: cachedDimensions.current?.height || undefined
});
if (headers) {
return {
Expand Down
17 changes: 10 additions & 7 deletions packages/render-html/src/elements/useImageConcreteDimensions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { useMemo } from 'react';
import { ImageStyle } from 'react-native';
import { ImageDimensions } from '../shared-types';
import { UseIMGElementStateProps } from './img-types';
import useImageNaturalDimensions from './useImageNaturalDimensions';
import {
IncompleteImageDimensions,
UseIMGElementStateProps
} from './img-types';

export type ConcreteDimensionsProps = Pick<
ReturnType<typeof useImageNaturalDimensions>,
'flatStyle' | 'naturalDimensions' | 'specifiedDimensions'
> &
Pick<UseIMGElementStateProps, 'computeMaxWidth' | 'contentWidth'>;
export type ConcreteDimensionsProps = {
flatStyle: ImageStyle;
naturalDimensions: ImageDimensions | null;
specifiedDimensions: IncompleteImageDimensions;
} & Pick<UseIMGElementStateProps, 'computeMaxWidth' | 'contentWidth'>;

function extractHorizontalSpace({
marginHorizontal,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { useState, useMemo, useEffect } from 'react';
import { StyleSheet } from 'react-native';
import { ImageDimensions } from '../shared-types';
import { useMemo } from 'react';
import {
UseIMGElementStateProps,
IncompleteImageDimensions
} from './img-types';
import getDimensionsWithAspectRatio from './getDimensionsWithAspectRatio';
import { UseIMGElementStateProps } from './img-types';

interface IncompleteImageDimensions {
height: number | null;
width: number | null;
}
import { StyleSheet } from 'react-native';

function normalizeSize(
dimension: string | number | null | undefined,
Expand Down Expand Up @@ -71,26 +68,12 @@ function deriveSpecifiedDimensionsFromProps({
);
}

export default function useImageNaturalDimensions<
P extends UseIMGElementStateProps
>(props: P) {
const {
source,
contentWidth,
enableExperimentalPercentWidth,
width,
height,
style,
cachedNaturalDimensions
} = props;
const [naturalDimensions, setNaturalDimensions] = useState<
P['cachedNaturalDimensions'] extends ImageDimensions
? ImageDimensions
: ImageDimensions | null
>((cachedNaturalDimensions as any) || null);
export default function useImageSpecifiedDimensions(
props: UseIMGElementStateProps
) {
const { contentWidth, enableExperimentalPercentWidth, style, width, height } =
props;
const flatStyle = useMemo(() => StyleSheet.flatten(style) || {}, [style]);
const { width: cachedNaturalWidth, height: cachedNaturalHeight } =
cachedNaturalDimensions || {};
const specifiedDimensions = useMemo(
() =>
deriveSpecifiedDimensionsFromProps({
Expand All @@ -102,24 +85,5 @@ export default function useImageNaturalDimensions<
}),
[contentWidth, enableExperimentalPercentWidth, flatStyle, height, width]
);
const [error, setError] = useState<null | Error>(null);
useEffect(
function resetOnURIChange() {
setNaturalDimensions(
(cachedNaturalWidth != null && cachedNaturalHeight != null
? { width: cachedNaturalWidth, height: cachedNaturalHeight }
: null) as any
);
setError(null);
},
[cachedNaturalHeight, cachedNaturalWidth, source.uri]
);
return {
onNaturalDimensions: setNaturalDimensions,
onError: setError,
naturalDimensions,
specifiedDimensions,
flatStyle,
error
};
return { flatStyle, specifiedDimensions };
}

0 comments on commit 5488259

Please sign in to comment.