import { PixelRatio } from 'react-native' import { BlurhashMetadataLocal, BlurhashMetadataRemote, ImageResizeModeForBlurhash, RunnerObject, } from 'types' /** * * @description retrieve blurhash metadata from Image component or from Database Collection field */ const getMetadata = ( object: RunnerObject, source: any, componentProps: any ): BlurhashMetadataRemote | undefined => { // Source is a locally cached image on a native build if (typeof source === 'number') { return undefined } // Image was uploaded via Builder if (object.attributes.imageType === 'uploaded') { const ratio = PixelRatio.getPixelSizeForLayoutSize(1) let sizes = [3, 2, 1] sizes.sort((a, b) => Math.abs(ratio - a) - Math.abs(ratio - b)) const largerSizes = sizes.filter(s => s >= ratio) const smallerSizes = sizes.filter(s => s < ratio) sizes = largerSizes.concat(smallerSizes) for (const size of sizes) { const key = `filename${size}x` if (object.attributes[key]?.metadata) { return object.attributes[key].metadata } } } // Image was uploaded to a Database Collection if (object.attributes.imageType === 'dynamic') { const image = Array.isArray(componentProps?.image) && componentProps?.image.length > 0 ? componentProps?.image[0] : componentProps?.image if (image && image.metadata) { return image.metadata } const options = object.attributes.imageBinding?.options if ( typeof options?.placeholderImageEnabled === 'boolean' && options.placeholderImageEnabled === true && typeof options?.placeholderImage !== 'undefined' && typeof options?.placeholderImageMetadata !== 'undefined' ) { return options.placeholderImageMetadata } } return undefined } const validateMetadata = (metadata: BlurhashMetadataRemote): boolean => { if ( typeof metadata.blurHash === 'string' && typeof metadata.width === 'number' && typeof metadata.height === 'number' && typeof metadata.blurHashWidth === 'number' ) { return true } return false } /** * * @description retrive blurhash with calculated width and height, ready for rendering in ImageBlurhash component */ export const getBlurhash = ( object: RunnerObject, source: any, componentProps: any ): BlurhashMetadataLocal | undefined => { const metadata = getMetadata(object, source, componentProps) if (!metadata || !validateMetadata(metadata)) { return undefined } const { blurHash, width, height, blurHashWidth } = metadata const blurHashHeight = Math.round((height / width) * blurHashWidth) const { attributes } = object const resizeMode = (attributes.imageResize || 'cover') as ImageResizeModeForBlurhash // prettier-ignore return { blurHash, width, height, blurHashWidth, blurHashHeight, resizeMode, } }