Skip to content

Commit

Permalink
feat: new provideEmbeddedHeaders prop to pass headers to img, iframes
Browse files Browse the repository at this point in the history
The function takes `uri` and `tagName` parameters, and returns either
`null`, nothing, or a headers object. Could also be used for video,
audio... and actually any embeddable element which has a remote source
attribute.
  • Loading branch information
jsamr committed Aug 28, 2021
1 parent 46e2ca4 commit 2ea1ca6
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 4 deletions.
3 changes: 2 additions & 1 deletion packages/render-html/src/RenderHTMLConfigProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export const renderHTMLConfigPropTypes: RenderHTMLConfigPropTypes = {
defaultWebViewProps: PropTypes.object,
pressableHightlightColor: PropTypes.string,
customListStyleSpecs: PropTypes.object,
renderers: PropTypes.object
renderers: PropTypes.object,
provideEmbeddedHeaders: PropTypes.func
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
defaultHTMLElementModels,
HTMLContentModel
} from '@native-html/transient-render-engine';
import { StyleSheet, Text } from 'react-native';
import { Image, StyleSheet, Text } from 'react-native';
import { useRendererProps } from '../context/RenderersPropsProvider';
import TNodeChildrenRenderer from '../TNodeChildrenRenderer';
import OLElement from '../elements/OLElement';
Expand Down Expand Up @@ -646,4 +646,28 @@ describe('RenderHTML', () => {
});
});
});
describe('regarding provideEmbeddedHeaders prop', () => {
it('should apply returned headers to IMG tags', async () => {
const headers = {
Authorization: 'Bearer XXX'
};
function provideEmbeddedHeaders(uri: string, tag: string) {
expect(tag).toBe('img');
return headers;
}
const { UNSAFE_getByType, findByTestId } = render(
<RenderHTML
source={{
html: '<img src="https://custom.domain/" />'
}}
debug={false}
contentWidth={100}
provideEmbeddedHeaders={provideEmbeddedHeaders}
/>
);
await findByTestId('image-success');
const image = UNSAFE_getByType(Image);
expect(image.props.source.headers).toBe(headers);
});
});
});
1 change: 1 addition & 0 deletions packages/render-html/src/context/defaultSharedProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const defaultSharedProps: Required<RenderHTMLSharedProps> = {
defaultViewProps: {},
enableExperimentalMarginCollapsing: false,
computeEmbeddedMaxWidth: (contentWidth) => contentWidth,
provideEmbeddedHeaders: () => null,
GenericPressable: undefined as any,
WebView: WebViewPlaceholder,
defaultWebViewProps: {},
Expand Down
18 changes: 16 additions & 2 deletions packages/render-html/src/elements/useIMGElementState.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useEffect } from 'react';
import { useEffect, useMemo } from 'react';
import { Image } from 'react-native';
import type { UseIMGElementStateProps, IMGElementState } from './img-types';
import useImageNaturalDimensions from './useImageNaturalDimensions';
import useImageConcreteDimensions from './useImageConcreteDimensions';
import defaultImageInitialDimensions from './defaultInitialImageDimensions';
import { ImageDimensions } from '../shared-types';
import { getIMGState } from './getIMGState';
import { useSharedProps } from '../context/SharedPropsProvider';

function getImageSizeAsync({
uri,
Expand Down Expand Up @@ -88,6 +89,19 @@ export default function useIMGElementState(
} = props;
const { naturalDimensions, specifiedDimensions, flatStyle, onError, error } =
useFetchedNaturalDimensions(props);
const { provideEmbeddedHeaders } = useSharedProps();
const nomalizedSource = useMemo(() => {
if (source.uri) {
const headers = provideEmbeddedHeaders(source.uri, 'img');
if (headers) {
return {
headers,
...source
};
}
}
return source;
}, [provideEmbeddedHeaders, source]);
const concreteDimensions = useImageConcreteDimensions({
flatStyle,
naturalDimensions,
Expand All @@ -104,6 +118,6 @@ export default function useIMGElementState(
initialDimensions,
objectFit,
onError,
source
source: nomalizedSource
});
}
23 changes: 23 additions & 0 deletions packages/render-html/src/shared-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,29 @@ export interface RenderHTMLSharedProps {
* @defaultValue rgba(38, 132, 240, 0.2)
*/
pressableHightlightColor?: string;

/**
* Provide headers for specific embedded elements, such as images, iframes...
*
* @example
*
* ```tsx
* function provideEmbeddedHeaders(uri: string, tagName: string) {
* if (tagName === "img" && uri.startsWith("https://example.com")) {
* return {
* Authorization: "Bearer daem6QuaeloopheiD7Oh"
* }
* }
*
* // ...
*
* <RenderHTML provideEmbeddedHeaders={provideEmbeddedHeaders} />
* ```
*/
provideEmbeddedHeaders?: (
embeddedUri: string,
tagName: string
) => Record<string, string> | null | void;
}

/**
Expand Down

0 comments on commit 2ea1ca6

Please sign in to comment.