1import React, { useEffect, Ref } from 'react';
2
3import ColorTintFilter, { getTintColorStyle } from './ColorTintFilter';
4import { ImageWrapperProps } from './ImageWrapper.types';
5import { getImageWrapperEventHandler } from './getImageWrapperEventHandler';
6import { useHeaders, useImageHashes } from './hooks';
7import { absoluteFilledPosition, getObjectPositionFromContentPositionObject } from './positioning';
8import { SrcSetSource } from './useSourceSelection';
9import { ImageNativeProps, ImageSource } from '../Image.types';
10
11function getFetchPriorityFromImagePriority(priority: ImageNativeProps['priority'] = 'normal') {
12  return priority && ['low', 'high'].includes(priority) ? priority : 'auto';
13}
14
15function getImgPropsFromSource(source: ImageSource | SrcSetSource | null | undefined) {
16  if (source && 'srcset' in source) {
17    return {
18      srcSet: source.srcset,
19      sizes: source.sizes,
20    };
21  }
22  return {};
23}
24
25const ImageWrapper = React.forwardRef(
26  (
27    {
28      source,
29      events,
30      contentPosition,
31      hashPlaceholderContentPosition,
32      priority,
33      style,
34      hashPlaceholderStyle,
35      tintColor,
36      className,
37      accessibilityLabel,
38      cachePolicy,
39      ...props
40    }: ImageWrapperProps,
41    ref: Ref<HTMLImageElement>
42  ) => {
43    useEffect(() => {
44      events?.onMount?.forEach((e) => e?.());
45    }, []);
46
47    // Thumbhash uri always has to start with 'thumbhash:/'
48    const { resolvedSource, isImageHash } = useImageHashes(source);
49
50    const objectPosition = getObjectPositionFromContentPositionObject(
51      isImageHash ? hashPlaceholderContentPosition : contentPosition
52    );
53
54    const sourceWithHeaders = useHeaders(resolvedSource, cachePolicy, events?.onError);
55    if (!sourceWithHeaders) {
56      return null;
57    }
58    return (
59      <>
60        <ColorTintFilter tintColor={tintColor} />
61        <img
62          ref={ref}
63          alt={accessibilityLabel}
64          className={className}
65          src={sourceWithHeaders?.uri || undefined}
66          key={source?.uri}
67          style={{
68            objectPosition,
69            ...absoluteFilledPosition,
70            ...getTintColorStyle(tintColor),
71            ...(isImageHash ? hashPlaceholderStyle : {}),
72            ...style,
73          }}
74          // @ts-ignore
75          // eslint-disable-next-line react/no-unknown-property
76          fetchpriority={getFetchPriorityFromImagePriority(priority || 'normal')}
77          {...getImageWrapperEventHandler(events, sourceWithHeaders)}
78          {...getImgPropsFromSource(source)}
79          {...props}
80        />
81      </>
82    );
83  }
84);
85
86export default ImageWrapper;
87