react-native-fast-image 8.21.0 → 8.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java +15 -0
- package/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java +199 -3
- package/dist/constants.d.ts +16 -0
- package/dist/index.cjs.js +18 -2
- package/dist/index.cjs.js.flow +7 -0
- package/dist/index.cjs.web.js +193 -0
- package/dist/index.cjs.web.js.flow +154 -0
- package/dist/index.d.ts +37 -16
- package/dist/index.js +18 -2
- package/dist/index.js.flow +7 -0
- package/dist/index.web.d.ts +6 -0
- package/dist/index.web.js +165 -0
- package/dist/index.web.js.flow +154 -0
- package/ios/FastImage/FFFastImageView.h +6 -0
- package/ios/FastImage/FFFastImageView.m +107 -7
- package/ios/FastImage/FFFastImageViewManager.m +3 -0
- package/package.json +6 -4
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes'
|
|
4
|
+
import type { SyntheticEvent } from 'react-native/Libraries/Types/CoreEventTypes'
|
|
5
|
+
|
|
6
|
+
export type OnLoadEvent = SyntheticEvent<
|
|
7
|
+
$ReadOnly<{
|
|
8
|
+
width: number,
|
|
9
|
+
height: number,
|
|
10
|
+
// The view's React tag. Missing on Android with the legacy architecture.
|
|
11
|
+
// TODO: make it required once the New Architecture is the minimum.
|
|
12
|
+
target?: number,
|
|
13
|
+
}>,
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export type OnErrorEvent = SyntheticEvent<
|
|
17
|
+
$ReadOnly<{|
|
|
18
|
+
error: string,
|
|
19
|
+
|}>,
|
|
20
|
+
>
|
|
21
|
+
|
|
22
|
+
export type OnProgressEvent = SyntheticEvent<
|
|
23
|
+
$ReadOnly<{|
|
|
24
|
+
loaded: number,
|
|
25
|
+
total: number,
|
|
26
|
+
// loaded / total, from 0 to 1.
|
|
27
|
+
progress: number,
|
|
28
|
+
|}>,
|
|
29
|
+
>
|
|
30
|
+
|
|
31
|
+
export type ResizeMode = $ReadOnly<{|
|
|
32
|
+
contain: 'contain',
|
|
33
|
+
cover: 'cover',
|
|
34
|
+
stretch: 'stretch',
|
|
35
|
+
center: 'center',
|
|
36
|
+
|}>
|
|
37
|
+
|
|
38
|
+
export type Priority = $ReadOnly<{|
|
|
39
|
+
low: 'low',
|
|
40
|
+
normal: 'normal',
|
|
41
|
+
high: 'high',
|
|
42
|
+
|}>
|
|
43
|
+
|
|
44
|
+
export type CacheControl = $ReadOnly<{|
|
|
45
|
+
immutable: 'immutable',
|
|
46
|
+
web: 'web',
|
|
47
|
+
cacheOnly: 'cacheOnly',
|
|
48
|
+
|}>
|
|
49
|
+
|
|
50
|
+
export type ResizeModes = $Values<ResizeMode>
|
|
51
|
+
export type Priorities = $Values<Priority>
|
|
52
|
+
export type CacheControls = $Values<CacheControl>
|
|
53
|
+
|
|
54
|
+
export type LoadResult =
|
|
55
|
+
| {| ok: true, width: number, height: number |}
|
|
56
|
+
| {| ok: false, error: string |}
|
|
57
|
+
|
|
58
|
+
export type CacheLimits = {|
|
|
59
|
+
maxDiskSize?: ?number,
|
|
60
|
+
maxDiskAge?: ?number,
|
|
61
|
+
maxMemorySize?: ?number,
|
|
62
|
+
|}
|
|
63
|
+
|
|
64
|
+
export type CacheState = {|
|
|
65
|
+
maxDiskSize?: number,
|
|
66
|
+
maxDiskAge?: number,
|
|
67
|
+
maxMemorySize?: number,
|
|
68
|
+
diskSize?: number,
|
|
69
|
+
|}
|
|
70
|
+
|
|
71
|
+
export type CachePathResult =
|
|
72
|
+
| {| ok: true, path: string |}
|
|
73
|
+
| {| ok: false, error: string |}
|
|
74
|
+
|
|
75
|
+
export type Transition = $ReadOnly<{|
|
|
76
|
+
duration?: ?number,
|
|
77
|
+
betweenImages?: ?boolean,
|
|
78
|
+
skipOnCacheHit?: ?('none' | 'memory' | 'all'),
|
|
79
|
+
|}>
|
|
80
|
+
|
|
81
|
+
export type PreloadSuccess = {|
|
|
82
|
+
uri: string,
|
|
83
|
+
ok: true,
|
|
84
|
+
width: number,
|
|
85
|
+
height: number,
|
|
86
|
+
|}
|
|
87
|
+
|
|
88
|
+
export type PreloadFailure = {|
|
|
89
|
+
uri?: string,
|
|
90
|
+
ok: false,
|
|
91
|
+
error: string,
|
|
92
|
+
|}
|
|
93
|
+
|
|
94
|
+
export type PreloadResult = PreloadSuccess | PreloadFailure
|
|
95
|
+
|
|
96
|
+
export type PreloadFn = (
|
|
97
|
+
sources: Array<FastImageSource>,
|
|
98
|
+
) => Promise<Array<PreloadResult>>
|
|
99
|
+
export type FastImageSource = {
|
|
100
|
+
uri?: string,
|
|
101
|
+
headers?: Object,
|
|
102
|
+
priority?: Priorities,
|
|
103
|
+
cache?: CacheControls,
|
|
104
|
+
cacheKey?: string,
|
|
105
|
+
memoryCache?: boolean,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type FastImageProps = $ReadOnly<{|
|
|
109
|
+
...ViewProps,
|
|
110
|
+
onError?: ?(event: OnErrorEvent) => void,
|
|
111
|
+
onLoad?: ?(event: OnLoadEvent) => void,
|
|
112
|
+
onLoadEnd?: ?(result: LoadResult) => void,
|
|
113
|
+
onLoadStart?: ?() => void,
|
|
114
|
+
onProgress?: ?(event: OnProgressEvent) => void,
|
|
115
|
+
|
|
116
|
+
source?: ?(FastImageSource | number),
|
|
117
|
+
defaultSource?: ?number,
|
|
118
|
+
|
|
119
|
+
tintColor?: number | string,
|
|
120
|
+
resizeMode?: ?ResizeModes,
|
|
121
|
+
fallback?: ?boolean,
|
|
122
|
+
recyclingKey?: ?string,
|
|
123
|
+
loop?: ?(boolean | number),
|
|
124
|
+
imageRendering?: ?('auto' | 'smooth' | 'pixelated'),
|
|
125
|
+
paused?: ?boolean,
|
|
126
|
+
transition?: ?(boolean | number | Transition),
|
|
127
|
+
downsample?: ?boolean,
|
|
128
|
+
blurRadius?: ?number,
|
|
129
|
+
testID?: ?string,
|
|
130
|
+
|}>
|
|
131
|
+
|
|
132
|
+
export type FastImageBackgroundProps = $ReadOnly<{|
|
|
133
|
+
...FastImageProps,
|
|
134
|
+
imageStyle?: $PropertyType<ViewProps, 'style'>,
|
|
135
|
+
imageRef?: React$Ref<any>,
|
|
136
|
+
children?: React$Node,
|
|
137
|
+
|}>
|
|
138
|
+
|
|
139
|
+
declare export var FastImageBackground: React$ComponentType<FastImageBackgroundProps>
|
|
140
|
+
|
|
141
|
+
declare export default class FastImage extends React$Component<FastImageProps> {
|
|
142
|
+
static resizeMode: ResizeMode;
|
|
143
|
+
static priority: Priority;
|
|
144
|
+
static cacheControl: CacheControl;
|
|
145
|
+
static preload: PreloadFn;
|
|
146
|
+
static clearMemoryCache: () => Promise<void>;
|
|
147
|
+
static clearDiskCache: () => Promise<void>;
|
|
148
|
+
static getCachePath: (source: FastImageSource) => Promise<CachePathResult>;
|
|
149
|
+
static configureCache: (limits?: CacheLimits) => Promise<CacheState>;
|
|
150
|
+
static writeToCache: (
|
|
151
|
+
source: FastImageSource,
|
|
152
|
+
file: string,
|
|
153
|
+
) => Promise<CachePathResult>;
|
|
154
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LayoutChangeEvent, StyleProp, ViewStyle, ImageRequireSource, AccessibilityProps, ViewProps } from 'react-native';
|
|
3
|
+
import { cacheControl, priority, resizeMode } from './constants';
|
|
3
4
|
type ColorValue = NonNullable<ViewStyle['backgroundColor']>;
|
|
4
5
|
export type ResizeMode = 'contain' | 'cover' | 'stretch' | 'center';
|
|
5
|
-
declare const resizeMode: {
|
|
6
|
-
readonly contain: 'contain';
|
|
7
|
-
readonly cover: 'cover';
|
|
8
|
-
readonly stretch: 'stretch';
|
|
9
|
-
readonly center: 'center';
|
|
10
|
-
};
|
|
11
6
|
export type Priority = 'low' | 'normal' | 'high';
|
|
12
|
-
declare const priority: {
|
|
13
|
-
readonly low: 'low';
|
|
14
|
-
readonly normal: 'normal';
|
|
15
|
-
readonly high: 'high';
|
|
16
|
-
};
|
|
17
7
|
export type Cache = 'immutable' | 'web' | 'cacheOnly';
|
|
18
|
-
declare const cacheControl: {
|
|
19
|
-
readonly immutable: 'immutable';
|
|
20
|
-
readonly web: 'web';
|
|
21
|
-
readonly cacheOnly: 'cacheOnly';
|
|
22
|
-
};
|
|
23
8
|
export type Source = {
|
|
24
9
|
uri?: string;
|
|
25
10
|
headers?: {
|
|
@@ -42,6 +27,35 @@ export type Source = {
|
|
|
42
27
|
*/
|
|
43
28
|
memoryCache?: boolean;
|
|
44
29
|
};
|
|
30
|
+
export type Transition = {
|
|
31
|
+
/**
|
|
32
|
+
* How long the fade takes, in milliseconds; 0 means no fade. Defaults to
|
|
33
|
+
* the platform's usual length: 300 ms on Android, 250 ms on iOS.
|
|
34
|
+
*/
|
|
35
|
+
duration?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Also fades between images: a new `source` replacing an image that's
|
|
38
|
+
* showing cross-dissolves from it. Otherwise only an image that appears
|
|
39
|
+
* over nothing (or over `defaultSource`) fades in, and a new source
|
|
40
|
+
* replaces the image showing at once, once it has loaded.
|
|
41
|
+
* @default false
|
|
42
|
+
*/
|
|
43
|
+
betweenImages?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Skips the fade for an image from a cache, so images already loaded
|
|
46
|
+
* show at once, e.g. in a list scrolled back up or a reused row.
|
|
47
|
+
*
|
|
48
|
+
* - `'memory'`: skips it for images from the memory cache.
|
|
49
|
+
* - `'all'`: skips it for images from the memory or disk cache too, so
|
|
50
|
+
* images that download fade in, and local files and bundled images
|
|
51
|
+
* usually only the first time (the disk cache usually keeps them too).
|
|
52
|
+
* - `'none'`: always fades.
|
|
53
|
+
*
|
|
54
|
+
* Downloads, local files and bundled images (`require()`) fade in.
|
|
55
|
+
* @default 'memory'
|
|
56
|
+
*/
|
|
57
|
+
skipOnCacheHit?: 'none' | 'memory' | 'all' | null;
|
|
58
|
+
};
|
|
45
59
|
export interface OnLoadEvent {
|
|
46
60
|
nativeEvent: {
|
|
47
61
|
width: number;
|
|
@@ -135,6 +149,13 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
|
|
|
135
149
|
* its own, so pausing one doesn't pause others showing the same file.
|
|
136
150
|
*/
|
|
137
151
|
paused?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Fades the image in when it loads: `true` for the platform's usual fade,
|
|
154
|
+
* a duration in milliseconds, or a `Transition` (default: no fade). An
|
|
155
|
+
* image fades in when it appears over nothing (see `betweenImages`),
|
|
156
|
+
* unless it's from the memory cache (see `skipOnCacheHit`).
|
|
157
|
+
*/
|
|
158
|
+
transition?: boolean | number | Transition | null;
|
|
138
159
|
/**
|
|
139
160
|
* iOS only. Decodes a large image at about the size it's shown at, so it
|
|
140
161
|
* takes much less memory. For images much larger than their views that
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { forwardRef, memo, useRef } from "react";
|
|
2
2
|
import { Image, NativeModules, Platform, StyleSheet, View, requireNativeComponent } from "react-native";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/constants.ts
|
|
4
4
|
const resizeMode = {
|
|
5
5
|
contain: "contain",
|
|
6
6
|
cover: "cover",
|
|
@@ -17,6 +17,8 @@ const cacheControl = {
|
|
|
17
17
|
web: "web",
|
|
18
18
|
cacheOnly: "cacheOnly"
|
|
19
19
|
};
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/index.tsx
|
|
20
22
|
const resolveDefaultSource = (defaultSource) => {
|
|
21
23
|
if (!defaultSource) return null;
|
|
22
24
|
if (Platform.OS === "android") {
|
|
@@ -64,11 +66,24 @@ function withProgress(onProgress) {
|
|
|
64
66
|
onProgress(event);
|
|
65
67
|
});
|
|
66
68
|
}
|
|
69
|
+
const DEFAULT_FADE_MS = Platform.OS === "ios" ? 250 : 300;
|
|
70
|
+
function transitionProps(transition) {
|
|
71
|
+
var _transition$duration;
|
|
72
|
+
const { duration, betweenImages, skipOnCacheHit } = typeof transition === "number" ? { duration: transition } : typeof transition === "object" && transition ? {
|
|
73
|
+
...transition,
|
|
74
|
+
duration: (_transition$duration = transition.duration) !== null && _transition$duration !== void 0 ? _transition$duration : DEFAULT_FADE_MS
|
|
75
|
+
} : { duration: transition ? DEFAULT_FADE_MS : 0 };
|
|
76
|
+
return {
|
|
77
|
+
transitionDuration: typeof duration === "number" && duration > 0 ? duration : 0,
|
|
78
|
+
transitionBetweenImages: !!betweenImages,
|
|
79
|
+
transitionSkipOnCacheHit: skipOnCacheHit || "memory"
|
|
80
|
+
};
|
|
81
|
+
}
|
|
67
82
|
function withoutCache(source) {
|
|
68
83
|
const { cache: _cache, ...rest } = source || {};
|
|
69
84
|
return rest;
|
|
70
85
|
}
|
|
71
|
-
function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, fallback, children, resizeMode = "cover", loop, forwardedRef, onLayout, pointerEvents, ...viewProps }) {
|
|
86
|
+
function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, fallback, children, resizeMode = "cover", loop, transition, forwardedRef, onLayout, pointerEvents, ...viewProps }) {
|
|
72
87
|
const { onClick, ...props } = viewProps;
|
|
73
88
|
const fallbackResult = useRef(void 0);
|
|
74
89
|
const wrapperProps = {
|
|
@@ -131,6 +146,7 @@ function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgre
|
|
|
131
146
|
...imageProps,
|
|
132
147
|
tintColor: resolvedTintColor,
|
|
133
148
|
loopCount: loopCount(loop),
|
|
149
|
+
...transitionProps(transition),
|
|
134
150
|
style: StyleSheet.absoluteFill,
|
|
135
151
|
source: resolvedSource,
|
|
136
152
|
defaultSource: resolvedDefaultSource,
|
package/dist/index.js.flow
CHANGED
|
@@ -72,6 +72,12 @@ export type CachePathResult =
|
|
|
72
72
|
| {| ok: true, path: string |}
|
|
73
73
|
| {| ok: false, error: string |}
|
|
74
74
|
|
|
75
|
+
export type Transition = $ReadOnly<{|
|
|
76
|
+
duration?: ?number,
|
|
77
|
+
betweenImages?: ?boolean,
|
|
78
|
+
skipOnCacheHit?: ?('none' | 'memory' | 'all'),
|
|
79
|
+
|}>
|
|
80
|
+
|
|
75
81
|
export type PreloadSuccess = {|
|
|
76
82
|
uri: string,
|
|
77
83
|
ok: true,
|
|
@@ -117,6 +123,7 @@ export type FastImageProps = $ReadOnly<{|
|
|
|
117
123
|
loop?: ?(boolean | number),
|
|
118
124
|
imageRendering?: ?('auto' | 'smooth' | 'pixelated'),
|
|
119
125
|
paused?: ?boolean,
|
|
126
|
+
transition?: ?(boolean | number | Transition),
|
|
120
127
|
downsample?: ?boolean,
|
|
121
128
|
blurRadius?: ?number,
|
|
122
129
|
testID?: ?string,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FastImageBackgroundProps, FastImageProps, FastImageStaticProperties } from './index';
|
|
3
|
+
export type * from './index';
|
|
4
|
+
declare const FastImage: React.ComponentType<FastImageProps> & FastImageStaticProperties;
|
|
5
|
+
export declare const FastImageBackground: React.ComponentType<FastImageBackgroundProps>;
|
|
6
|
+
export default FastImage;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React, { forwardRef, memo, useRef } from "react";
|
|
2
|
+
import { Image, StyleSheet, View } from "react-native";
|
|
3
|
+
//#region src/constants.ts
|
|
4
|
+
const resizeMode = {
|
|
5
|
+
contain: "contain",
|
|
6
|
+
cover: "cover",
|
|
7
|
+
stretch: "stretch",
|
|
8
|
+
center: "center"
|
|
9
|
+
};
|
|
10
|
+
const priority = {
|
|
11
|
+
low: "low",
|
|
12
|
+
normal: "normal",
|
|
13
|
+
high: "high"
|
|
14
|
+
};
|
|
15
|
+
const cacheControl = {
|
|
16
|
+
immutable: "immutable",
|
|
17
|
+
web: "web",
|
|
18
|
+
cacheOnly: "cacheOnly"
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/index.web.tsx
|
|
22
|
+
const notSupported = {
|
|
23
|
+
ok: false,
|
|
24
|
+
error: "Not supported on the web"
|
|
25
|
+
};
|
|
26
|
+
function FastImageBase({ source, defaultSource, tintColor, blurRadius, onLoadStart, onLoad, onError, onLoadEnd, style, children, resizeMode: mode = "cover", forwardedRef, onLayout, pointerEvents, fallback: _fallback, recyclingKey: _recyclingKey, loop: _loop, imageRendering: _imageRendering, paused: _paused, transition: _transition, downsample: _downsample, onProgress: _onProgress, ...props }) {
|
|
27
|
+
const result = useRef(void 0);
|
|
28
|
+
const sent = useRef(Promise.resolve());
|
|
29
|
+
const image = useRef(null);
|
|
30
|
+
const uri = typeof source === "object" && source ? source.uri : void 0;
|
|
31
|
+
const webSource = typeof source === "number" ? source : uri ? { uri } : void 0;
|
|
32
|
+
return /* @__PURE__ */ React.createElement(View, {
|
|
33
|
+
style: [styles.container, style],
|
|
34
|
+
onLayout,
|
|
35
|
+
pointerEvents,
|
|
36
|
+
ref: forwardedRef
|
|
37
|
+
}, /* @__PURE__ */ React.createElement(Image, {
|
|
38
|
+
...props,
|
|
39
|
+
style: styles.image,
|
|
40
|
+
source: webSource,
|
|
41
|
+
defaultSource,
|
|
42
|
+
resizeMode: mode,
|
|
43
|
+
tintColor,
|
|
44
|
+
blurRadius,
|
|
45
|
+
ref: image,
|
|
46
|
+
onLoadStart,
|
|
47
|
+
onLoad: (event) => {
|
|
48
|
+
var _event$nativeEvent;
|
|
49
|
+
sent.current = loadedSize(event === null || event === void 0 || (_event$nativeEvent = event.nativeEvent) === null || _event$nativeEvent === void 0 ? void 0 : _event$nativeEvent.target, image.current, uri).then(({ width, height }) => {
|
|
50
|
+
result.current = {
|
|
51
|
+
ok: true,
|
|
52
|
+
width,
|
|
53
|
+
height
|
|
54
|
+
};
|
|
55
|
+
onLoad === null || onLoad === void 0 || onLoad({ nativeEvent: {
|
|
56
|
+
width,
|
|
57
|
+
height
|
|
58
|
+
} });
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
onError: (event) => {
|
|
62
|
+
var _event$nativeEvent$er, _event$nativeEvent2;
|
|
63
|
+
const error = String((_event$nativeEvent$er = event === null || event === void 0 || (_event$nativeEvent2 = event.nativeEvent) === null || _event$nativeEvent2 === void 0 ? void 0 : _event$nativeEvent2.error) !== null && _event$nativeEvent$er !== void 0 ? _event$nativeEvent$er : "Failed to load the image");
|
|
64
|
+
result.current = {
|
|
65
|
+
ok: false,
|
|
66
|
+
error
|
|
67
|
+
};
|
|
68
|
+
sent.current = Promise.resolve();
|
|
69
|
+
onError === null || onError === void 0 || onError({ nativeEvent: { error } });
|
|
70
|
+
},
|
|
71
|
+
onLoadEnd: () => {
|
|
72
|
+
sent.current.then(() => {
|
|
73
|
+
var _result$current;
|
|
74
|
+
onLoadEnd === null || onLoadEnd === void 0 || onLoadEnd((_result$current = result.current) !== null && _result$current !== void 0 ? _result$current : {
|
|
75
|
+
ok: false,
|
|
76
|
+
error: "Failed to load the image"
|
|
77
|
+
});
|
|
78
|
+
result.current = void 0;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}), children);
|
|
82
|
+
}
|
|
83
|
+
const FastImageMemo = memo(FastImageBase);
|
|
84
|
+
const FastImageComponent = forwardRef((props, ref) => /* @__PURE__ */ React.createElement(FastImageMemo, {
|
|
85
|
+
forwardedRef: ref,
|
|
86
|
+
...props
|
|
87
|
+
}));
|
|
88
|
+
FastImageComponent.displayName = "FastImage";
|
|
89
|
+
async function loadedSize(loaded, view, uri) {
|
|
90
|
+
var _view$querySelector;
|
|
91
|
+
if (loaded === null || loaded === void 0 ? void 0 : loaded.naturalWidth) return {
|
|
92
|
+
width: loaded.naturalWidth,
|
|
93
|
+
height: loaded.naturalHeight
|
|
94
|
+
};
|
|
95
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
96
|
+
const shown = view === null || view === void 0 || (_view$querySelector = view.querySelector) === null || _view$querySelector === void 0 ? void 0 : _view$querySelector.call(view, "img");
|
|
97
|
+
if (shown === null || shown === void 0 ? void 0 : shown.naturalWidth) return {
|
|
98
|
+
width: shown.naturalWidth,
|
|
99
|
+
height: shown.naturalHeight
|
|
100
|
+
};
|
|
101
|
+
const src = uri !== null && uri !== void 0 ? uri : shown === null || shown === void 0 ? void 0 : shown.src;
|
|
102
|
+
return src ? getSize(src) : {
|
|
103
|
+
width: 0,
|
|
104
|
+
height: 0
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function getSize(uri) {
|
|
108
|
+
return new Promise((resolve) => {
|
|
109
|
+
Image.getSize(uri, (width, height) => resolve({
|
|
110
|
+
width,
|
|
111
|
+
height
|
|
112
|
+
}), () => resolve({
|
|
113
|
+
width: 0,
|
|
114
|
+
height: 0
|
|
115
|
+
}));
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const FastImage = FastImageComponent;
|
|
119
|
+
FastImage.resizeMode = resizeMode;
|
|
120
|
+
FastImage.cacheControl = cacheControl;
|
|
121
|
+
FastImage.priority = priority;
|
|
122
|
+
FastImage.preload = (sources) => Promise.all(sources.map((source) => {
|
|
123
|
+
const uri = source ? source.uri : void 0;
|
|
124
|
+
if (typeof uri !== "string" || !uri) return Promise.resolve({
|
|
125
|
+
ok: false,
|
|
126
|
+
error: "Invalid source: no uri",
|
|
127
|
+
uri
|
|
128
|
+
});
|
|
129
|
+
return Image.prefetch(uri).then(() => getSize(uri).then((size) => ({
|
|
130
|
+
ok: true,
|
|
131
|
+
uri,
|
|
132
|
+
...size
|
|
133
|
+
})), () => ({
|
|
134
|
+
ok: false,
|
|
135
|
+
error: "Failed to load the image",
|
|
136
|
+
uri
|
|
137
|
+
}));
|
|
138
|
+
}));
|
|
139
|
+
FastImage.clearMemoryCache = () => Promise.resolve();
|
|
140
|
+
FastImage.clearDiskCache = () => Promise.resolve();
|
|
141
|
+
FastImage.configureCache = () => Promise.resolve({});
|
|
142
|
+
FastImage.writeToCache = () => Promise.resolve(notSupported);
|
|
143
|
+
FastImage.getCachePath = () => Promise.resolve(notSupported);
|
|
144
|
+
const styles = StyleSheet.create({
|
|
145
|
+
container: { overflow: "hidden" },
|
|
146
|
+
image: {
|
|
147
|
+
position: "absolute",
|
|
148
|
+
top: 0,
|
|
149
|
+
left: 0,
|
|
150
|
+
width: "100%",
|
|
151
|
+
height: "100%"
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
const FastImageWithRef = FastImageComponent;
|
|
155
|
+
const FastImageBackground = forwardRef(({ style, imageStyle, imageRef, children, ...props }, ref) => /* @__PURE__ */ React.createElement(View, {
|
|
156
|
+
style,
|
|
157
|
+
ref
|
|
158
|
+
}, /* @__PURE__ */ React.createElement(FastImageWithRef, {
|
|
159
|
+
...props,
|
|
160
|
+
style: [StyleSheet.absoluteFill, imageStyle],
|
|
161
|
+
ref: imageRef
|
|
162
|
+
}), children));
|
|
163
|
+
FastImageBackground.displayName = "FastImageBackground";
|
|
164
|
+
//#endregion
|
|
165
|
+
export { FastImageBackground, FastImage as default };
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes'
|
|
4
|
+
import type { SyntheticEvent } from 'react-native/Libraries/Types/CoreEventTypes'
|
|
5
|
+
|
|
6
|
+
export type OnLoadEvent = SyntheticEvent<
|
|
7
|
+
$ReadOnly<{
|
|
8
|
+
width: number,
|
|
9
|
+
height: number,
|
|
10
|
+
// The view's React tag. Missing on Android with the legacy architecture.
|
|
11
|
+
// TODO: make it required once the New Architecture is the minimum.
|
|
12
|
+
target?: number,
|
|
13
|
+
}>,
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export type OnErrorEvent = SyntheticEvent<
|
|
17
|
+
$ReadOnly<{|
|
|
18
|
+
error: string,
|
|
19
|
+
|}>,
|
|
20
|
+
>
|
|
21
|
+
|
|
22
|
+
export type OnProgressEvent = SyntheticEvent<
|
|
23
|
+
$ReadOnly<{|
|
|
24
|
+
loaded: number,
|
|
25
|
+
total: number,
|
|
26
|
+
// loaded / total, from 0 to 1.
|
|
27
|
+
progress: number,
|
|
28
|
+
|}>,
|
|
29
|
+
>
|
|
30
|
+
|
|
31
|
+
export type ResizeMode = $ReadOnly<{|
|
|
32
|
+
contain: 'contain',
|
|
33
|
+
cover: 'cover',
|
|
34
|
+
stretch: 'stretch',
|
|
35
|
+
center: 'center',
|
|
36
|
+
|}>
|
|
37
|
+
|
|
38
|
+
export type Priority = $ReadOnly<{|
|
|
39
|
+
low: 'low',
|
|
40
|
+
normal: 'normal',
|
|
41
|
+
high: 'high',
|
|
42
|
+
|}>
|
|
43
|
+
|
|
44
|
+
export type CacheControl = $ReadOnly<{|
|
|
45
|
+
immutable: 'immutable',
|
|
46
|
+
web: 'web',
|
|
47
|
+
cacheOnly: 'cacheOnly',
|
|
48
|
+
|}>
|
|
49
|
+
|
|
50
|
+
export type ResizeModes = $Values<ResizeMode>
|
|
51
|
+
export type Priorities = $Values<Priority>
|
|
52
|
+
export type CacheControls = $Values<CacheControl>
|
|
53
|
+
|
|
54
|
+
export type LoadResult =
|
|
55
|
+
| {| ok: true, width: number, height: number |}
|
|
56
|
+
| {| ok: false, error: string |}
|
|
57
|
+
|
|
58
|
+
export type CacheLimits = {|
|
|
59
|
+
maxDiskSize?: ?number,
|
|
60
|
+
maxDiskAge?: ?number,
|
|
61
|
+
maxMemorySize?: ?number,
|
|
62
|
+
|}
|
|
63
|
+
|
|
64
|
+
export type CacheState = {|
|
|
65
|
+
maxDiskSize?: number,
|
|
66
|
+
maxDiskAge?: number,
|
|
67
|
+
maxMemorySize?: number,
|
|
68
|
+
diskSize?: number,
|
|
69
|
+
|}
|
|
70
|
+
|
|
71
|
+
export type CachePathResult =
|
|
72
|
+
| {| ok: true, path: string |}
|
|
73
|
+
| {| ok: false, error: string |}
|
|
74
|
+
|
|
75
|
+
export type Transition = $ReadOnly<{|
|
|
76
|
+
duration?: ?number,
|
|
77
|
+
betweenImages?: ?boolean,
|
|
78
|
+
skipOnCacheHit?: ?('none' | 'memory' | 'all'),
|
|
79
|
+
|}>
|
|
80
|
+
|
|
81
|
+
export type PreloadSuccess = {|
|
|
82
|
+
uri: string,
|
|
83
|
+
ok: true,
|
|
84
|
+
width: number,
|
|
85
|
+
height: number,
|
|
86
|
+
|}
|
|
87
|
+
|
|
88
|
+
export type PreloadFailure = {|
|
|
89
|
+
uri?: string,
|
|
90
|
+
ok: false,
|
|
91
|
+
error: string,
|
|
92
|
+
|}
|
|
93
|
+
|
|
94
|
+
export type PreloadResult = PreloadSuccess | PreloadFailure
|
|
95
|
+
|
|
96
|
+
export type PreloadFn = (
|
|
97
|
+
sources: Array<FastImageSource>,
|
|
98
|
+
) => Promise<Array<PreloadResult>>
|
|
99
|
+
export type FastImageSource = {
|
|
100
|
+
uri?: string,
|
|
101
|
+
headers?: Object,
|
|
102
|
+
priority?: Priorities,
|
|
103
|
+
cache?: CacheControls,
|
|
104
|
+
cacheKey?: string,
|
|
105
|
+
memoryCache?: boolean,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type FastImageProps = $ReadOnly<{|
|
|
109
|
+
...ViewProps,
|
|
110
|
+
onError?: ?(event: OnErrorEvent) => void,
|
|
111
|
+
onLoad?: ?(event: OnLoadEvent) => void,
|
|
112
|
+
onLoadEnd?: ?(result: LoadResult) => void,
|
|
113
|
+
onLoadStart?: ?() => void,
|
|
114
|
+
onProgress?: ?(event: OnProgressEvent) => void,
|
|
115
|
+
|
|
116
|
+
source?: ?(FastImageSource | number),
|
|
117
|
+
defaultSource?: ?number,
|
|
118
|
+
|
|
119
|
+
tintColor?: number | string,
|
|
120
|
+
resizeMode?: ?ResizeModes,
|
|
121
|
+
fallback?: ?boolean,
|
|
122
|
+
recyclingKey?: ?string,
|
|
123
|
+
loop?: ?(boolean | number),
|
|
124
|
+
imageRendering?: ?('auto' | 'smooth' | 'pixelated'),
|
|
125
|
+
paused?: ?boolean,
|
|
126
|
+
transition?: ?(boolean | number | Transition),
|
|
127
|
+
downsample?: ?boolean,
|
|
128
|
+
blurRadius?: ?number,
|
|
129
|
+
testID?: ?string,
|
|
130
|
+
|}>
|
|
131
|
+
|
|
132
|
+
export type FastImageBackgroundProps = $ReadOnly<{|
|
|
133
|
+
...FastImageProps,
|
|
134
|
+
imageStyle?: $PropertyType<ViewProps, 'style'>,
|
|
135
|
+
imageRef?: React$Ref<any>,
|
|
136
|
+
children?: React$Node,
|
|
137
|
+
|}>
|
|
138
|
+
|
|
139
|
+
declare export var FastImageBackground: React$ComponentType<FastImageBackgroundProps>
|
|
140
|
+
|
|
141
|
+
declare export default class FastImage extends React$Component<FastImageProps> {
|
|
142
|
+
static resizeMode: ResizeMode;
|
|
143
|
+
static priority: Priority;
|
|
144
|
+
static cacheControl: CacheControl;
|
|
145
|
+
static preload: PreloadFn;
|
|
146
|
+
static clearMemoryCache: () => Promise<void>;
|
|
147
|
+
static clearDiskCache: () => Promise<void>;
|
|
148
|
+
static getCachePath: (source: FastImageSource) => Promise<CachePathResult>;
|
|
149
|
+
static configureCache: (limits?: CacheLimits) => Promise<CacheState>;
|
|
150
|
+
static writeToCache: (
|
|
151
|
+
source: FastImageSource,
|
|
152
|
+
file: string,
|
|
153
|
+
) => Promise<CachePathResult>;
|
|
154
|
+
}
|
|
@@ -30,6 +30,12 @@
|
|
|
30
30
|
@property (nonatomic, copy) NSString *imageRendering;
|
|
31
31
|
// Pauses animated images on the frame they're showing.
|
|
32
32
|
@property (nonatomic, assign) BOOL paused;
|
|
33
|
+
// The `transition` prop: how long a loaded image takes to fade in, in
|
|
34
|
+
// milliseconds (0 for no fade), whether it also fades over a loaded image
|
|
35
|
+
// (a new source), and which cache hits show at once (none, memory or all).
|
|
36
|
+
@property (nonatomic, assign) double transitionDuration;
|
|
37
|
+
@property (nonatomic, assign) BOOL transitionBetweenImages;
|
|
38
|
+
@property (nonatomic, copy) NSString *transitionSkipOnCacheHit;
|
|
33
39
|
// Decodes images at about the view's size instead of at full size.
|
|
34
40
|
@property (nonatomic, assign) BOOL downsample;
|
|
35
41
|
// Blurs the loaded image by this radius, in points (0 is no blur).
|