From 42bd4aa89569c451015c431c7355ca17a5d17352 Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:26:56 +0100 Subject: [PATCH] feature: Update `Image.getSize` method to return a promise --- .eslintrc.js | 1 + .../Libraries/Image/Image.android.js | 32 +++++++++++-------- .../react-native/Libraries/Image/Image.d.ts | 15 +++++++-- .../react-native/Libraries/Image/Image.ios.js | 32 ++++++++++++------- .../Libraries/Image/ImageTypes.flow.js | 9 ++++-- .../__snapshots__/public-api-test.js.snap | 9 ++++-- .../types/__typetests__/index.tsx | 6 ++++ 7 files changed, 74 insertions(+), 30 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b0410b566e3456..c1e8f5e0e9bad3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -113,6 +113,7 @@ module.exports = { files: ['**/*.d.ts'], plugins: ['redundant-undefined'], rules: { + 'no-dupe-class-members': 'off', 'redundant-undefined/redundant-undefined': [ 'error', {followExactOptionalPropertyTypes: true}, diff --git a/packages/react-native/Libraries/Image/Image.android.js b/packages/react-native/Libraries/Image/Image.android.js index ac8660e968e63f..a33ed30a3a851d 100644 --- a/packages/react-native/Libraries/Image/Image.android.js +++ b/packages/react-native/Libraries/Image/Image.android.js @@ -23,7 +23,9 @@ import { import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; import ImageViewNativeComponent from './ImageViewNativeComponent'; -import NativeImageLoaderAndroid from './NativeImageLoaderAndroid'; +import NativeImageLoaderAndroid, { + type ImageSize, +} from './NativeImageLoaderAndroid'; import resolveAssetSource from './resolveAssetSource'; import TextInlineImageNativeComponent from './TextInlineImageNativeComponent'; import * as React from 'react'; @@ -40,13 +42,15 @@ function generateRequestId() { */ function getSize( url: string, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderAndroid.getSize(url) - .then(function (sizes) { - success(sizes.width, sizes.height); - }) +): void | Promise { + const promise = NativeImageLoaderAndroid.getSize(url); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { @@ -64,13 +68,15 @@ function getSize( function getSizeWithHeaders( url: string, headers: {[string]: string, ...}, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderAndroid.getSizeWithHeaders(url, headers) - .then(function (sizes) { - success(sizes.width, sizes.height); - }) +): void | Promise { + const promise = NativeImageLoaderAndroid.getSizeWithHeaders(url, headers); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { diff --git a/packages/react-native/Libraries/Image/Image.d.ts b/packages/react-native/Libraries/Image/Image.d.ts index c9e0195ba9604c..a8725c419f5c29 100644 --- a/packages/react-native/Libraries/Image/Image.d.ts +++ b/packages/react-native/Libraries/Image/Image.d.ts @@ -325,20 +325,31 @@ export interface ImageProps extends ImagePropsBase { style?: StyleProp | undefined; } +export interface ImageSize { + width: number; + height: number; +} + declare class ImageComponent extends React.Component {} declare const ImageBase: Constructor & typeof ImageComponent; export class Image extends ImageBase { + static getSize(uri: string): Promise; static getSize( uri: string, success: (width: number, height: number) => void, failure?: (error: any) => void, - ): any; + ): void; + + static getSizeWithHeaders( + uri: string, + headers: {[index: string]: string}, + ): Promise; static getSizeWithHeaders( uri: string, headers: {[index: string]: string}, success: (width: number, height: number) => void, failure?: (error: any) => void, - ): any; + ): void; static prefetch(url: string): Promise; static prefetchWithMetadata( url: string, diff --git a/packages/react-native/Libraries/Image/Image.ios.js b/packages/react-native/Libraries/Image/Image.ios.js index 9ba060e16a9c6a..4b7353e2547f91 100644 --- a/packages/react-native/Libraries/Image/Image.ios.js +++ b/packages/react-native/Libraries/Image/Image.ios.js @@ -11,6 +11,7 @@ import type {ImageStyle, ImageStyleProp} from '../StyleSheet/StyleSheet'; import type {RootTag} from '../Types/RootTagTypes'; import type {AbstractImageIOS, ImageIOS} from './ImageTypes.flow'; +import type {ImageSize} from './NativeImageLoaderAndroid'; import {createRootTag} from '../ReactNative/RootTag'; import flattenStyle from '../StyleSheet/flattenStyle'; @@ -29,15 +30,22 @@ import * as React from 'react'; function getSize( uri: string, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderIOS.getSize(uri) - .then(([width, height]) => success(width, height)) +): void | Promise { + const promise = NativeImageLoaderIOS.getSize(uri).then(([width, height]) => ({ + width, + height, + })); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { - console.warn('Failed to get size for image ' + uri); + console.warn('Failed to get size for image: ' + uri); }, ); } @@ -45,13 +53,15 @@ function getSize( function getSizeWithHeaders( uri: string, headers: {[string]: string, ...}, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderIOS.getSizeWithHeaders(uri, headers) - .then(function (sizes) { - success(sizes.width, sizes.height); - }) +): void | Promise { + const promise = NativeImageLoaderIOS.getSizeWithHeaders(uri, headers); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { diff --git a/packages/react-native/Libraries/Image/ImageTypes.flow.js b/packages/react-native/Libraries/Image/ImageTypes.flow.js index 4200a776987f52..7ea0f71a5707ef 100644 --- a/packages/react-native/Libraries/Image/ImageTypes.flow.js +++ b/packages/react-native/Libraries/Image/ImageTypes.flow.js @@ -18,12 +18,17 @@ import typeof TextInlineImageNativeComponent from './TextInlineImageNativeCompon import * as React from 'react'; type ImageComponentStaticsIOS = $ReadOnly<{ - getSize: ( + getSize(uri: string): Promise<{width: number, height: number}>, + getSize( uri: string, success: (width: number, height: number) => void, failure?: (error: mixed) => void, - ) => void, + ): void, + getSizeWithHeaders( + uri: string, + headers: {[string]: string, ...}, + ): Promise<{width: number, height: number}>, getSizeWithHeaders( uri: string, headers: {[string]: string, ...}, diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index bc166b11ec19f1..1ff30448458c25 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -4478,11 +4478,16 @@ exports[`public API should not change unintentionally Libraries/Image/ImageSourc exports[`public API should not change unintentionally Libraries/Image/ImageTypes.flow.js 1`] = ` "type ImageComponentStaticsIOS = $ReadOnly<{ - getSize: ( + getSize(uri: string): Promise<{ width: number, height: number }>, + getSize( uri: string, success: (width: number, height: number) => void, failure?: (error: mixed) => void - ) => void, + ): void, + getSizeWithHeaders( + uri: string, + headers: { [string]: string, ... } + ): Promise<{ width: number, height: number }>, getSizeWithHeaders( uri: string, headers: { [string]: string, ... }, diff --git a/packages/react-native/types/__typetests__/index.tsx b/packages/react-native/types/__typetests__/index.tsx index a7f8250e25d0ab..33a3a2bba745b4 100644 --- a/packages/react-native/types/__typetests__/index.tsx +++ b/packages/react-native/types/__typetests__/index.tsx @@ -1267,12 +1267,18 @@ export class ImageTest extends React.Component { } }); + const promise1: Promise = Image.getSize(uri).then(({width, height}) => + console.log(width, height), + ); Image.getSize(uri, (width, height) => console.log(width, height)); Image.getSize( uri, (width, height) => console.log(width, height), error => console.error(error), ); + const promise2: Promise = Image.getSizeWithHeaders(uri, headers).then( + ({width, height}) => console.log(width, height), + ); Image.getSizeWithHeaders(uri, headers, (width, height) => console.log(width, height), );