import React, { ReactNode, useEffect, useRef } from "react"; import FastImage, { OnLoadEvent } from "react-native-fast-image"; import { interpolate, useAnimatedStyle } from "react-native-reanimated"; import SkeletonContent from "react-native-skeleton-content-nonexpo"; import { useColors, useReanimatedValue } from "../commons"; import { Spinner, Svg, View } from "../components"; import { StyledProps } from "./Styled"; export type ImageProps = StyledProps & { uri?: string; require?: number; onLoaded?: (w: number, h: number) => void; renderError?: () => ReactNode; renderLoading?: () => ReactNode; cover?: boolean; isLoading?: boolean; background?: boolean; color?: string; }; const SVG_IMAGE_DEFAULT = ` `; export const Image = (props: ImageProps) => { const { uri, require, onLoaded, renderError, renderLoading, cover, isLoading, background, color, size, width, height, } = props; const sourceImage = uri ? { uri } : require; const colors = useColors(); const statusRef = useRef(uri ? 1 : 0); const statusValue = useReanimatedValue(uri ? 1 : 0); // 0: normal, 1: loading, 2: error const setLoadingValue = (value: number) => { if (statusRef.current !== value) { statusRef.current = value; statusValue.value = value; } }; const onLoadStart = () => { if (uri) setLoadingValue(1); }; const onLoad = (e: OnLoadEvent) => { onLoaded?.(e.nativeEvent.width, e.nativeEvent.height); }; const onLoadEnd = () => { if (statusRef.current === 1) setLoadingValue(0); }; const onError = () => { if (statusRef.current === 1) setLoadingValue(2); }; const renderDefault = () => { if (renderError) return renderError(); const d = size || height || width; const r = typeof d === "number" ? d / 4 : 20; return ( ); }; const renderSkeleton = () => { if (renderLoading) return renderLoading(); if (!cover && !background) return ; return ( ); }; const errorStyle = useAnimatedStyle( () => ({ opacity: interpolate(statusValue.value, [0, 1, 2], [0, 0, 1]), }), [] ); const loadingStyle = useAnimatedStyle( () => ({ opacity: interpolate(statusValue.value, [0, 1, 2], [0, 1, 0]), }), [] ); useEffect(() => { onLoadStart(); }, [uri]); return ( ); };