react-native-fast-image 9.3.7 → 9.4.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.
@@ -16,7 +16,6 @@ import com.bumptech.glide.load.model.LazyHeaders;
16
16
  import com.bumptech.glide.request.RequestOptions;
17
17
  import com.bumptech.glide.signature.ApplicationVersionSignature;
18
18
  import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
19
- import com.facebook.react.bridge.NoSuchKeyException;
20
19
  import com.facebook.react.bridge.ReadableMap;
21
20
  import com.facebook.react.bridge.ReadableMapKeySetIterator;
22
21
  import com.facebook.react.bridge.ReadableType;
@@ -34,6 +33,10 @@ class FastImageViewConverter {
34
33
  put("immutable", FastImageCacheControl.IMMUTABLE);
35
34
  put("web", FastImageCacheControl.WEB);
36
35
  put("cacheOnly", FastImageCacheControl.CACHE_ONLY);
36
+ // React Native's ImageURISource value, which views take. Its
37
+ // others (e.g. 'reload') are immutable, as any value this map
38
+ // doesn't have (see getValueFromSource).
39
+ put("only-if-cached", FastImageCacheControl.CACHE_ONLY);
37
40
  }};
38
41
 
39
42
  private static final Map<String, Priority> FAST_IMAGE_PRIORITY_MAP =
@@ -174,13 +177,12 @@ class FastImageViewConverter {
174
177
  return value;
175
178
  }
176
179
 
180
+ // A value the map doesn't have (e.g. React Native's `cache: 'reload'`, or
181
+ // one that isn't a string) gets the default, as on iOS.
177
182
  private static <T> T getValueFromSource(String propName, String defaultProp, Map<String, T> map, ReadableMap source) {
178
- String propValue;
179
- try {
180
- propValue = source != null ? source.getString(propName) : null;
181
- } catch (NoSuchKeyException e) {
182
- propValue = null;
183
- }
184
- return getValue(propName, defaultProp, map, propValue);
183
+ T value = source != null && source.hasKey(propName) && source.getType(propName) == ReadableType.String
184
+ ? map.get(source.getString(propName))
185
+ : null;
186
+ return value != null ? value : map.get(defaultProp);
185
187
  }
186
188
  }
package/dist/index.cjs.js CHANGED
@@ -82,6 +82,24 @@ function resolveObjectFit(objectFit, style, resizeMode) {
82
82
  return (_RESIZE_MODE_FIT$resi = RESIZE_MODE_FIT[resizeMode]) !== null && _RESIZE_MODE_FIT$resi !== void 0 ? _RESIZE_MODE_FIT$resi : "cover";
83
83
  }
84
84
  //#endregion
85
+ //#region src/reactNativeCache.ts
86
+ const REACT_NATIVE_CACHE = [
87
+ "default",
88
+ "reload",
89
+ "force-cache",
90
+ "only-if-cached"
91
+ ];
92
+ const isReactNativeCache = (cache) => REACT_NATIVE_CACHE.includes(cache);
93
+ let warnedReload = false;
94
+ function warnIfReload(source) {
95
+ if (warnedReload || typeof __DEV__ === "undefined" || !__DEV__) return;
96
+ for (const entry of Array.isArray(source) ? source : [source]) if ((entry === null || entry === void 0 ? void 0 : entry.cache) === "reload") {
97
+ warnedReload = true;
98
+ console.warn("react-native-fast-image: `cache: 'reload'` loads the image as the default, `'immutable'`: it isn't loaded again each time. For an image that changes at the same url, use `cache: 'web'` (it follows the server's cache headers), or change its `cacheKey`.");
99
+ return;
100
+ }
101
+ }
102
+ //#endregion
85
103
  //#region src/index.tsx
86
104
  const resolveDefaultSource = (defaultSource) => {
87
105
  if (!defaultSource) return null;
@@ -139,8 +157,11 @@ function transitionProps(transition) {
139
157
  };
140
158
  }
141
159
  function withoutCache(source) {
142
- const { cache: _cache, ...rest } = source || {};
143
- return rest;
160
+ const { cache, ...rest } = source || {};
161
+ return isReactNativeCache(cache) ? {
162
+ ...rest,
163
+ cache
164
+ } : rest;
144
165
  }
145
166
  function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, fallback, children, objectFit, resizeMode = "cover", loop, transition, forwardedRef, onLayout, pointerEvents, hitSlop, onStartShouldSetResponder, onStartShouldSetResponderCapture, onMoveShouldSetResponder, onMoveShouldSetResponderCapture, onResponderGrant, onResponderReject, onResponderStart, onResponderMove, onResponderEnd, onResponderRelease, onResponderTerminationRequest, onResponderTerminate, onTouchStart, onTouchMove, onTouchEnd, onTouchCancel, onTouchEndCapture, ...viewProps }) {
146
167
  const { onClick, ...props } = viewProps;
@@ -214,6 +235,7 @@ function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgre
214
235
  resizeMode: mode === "none" || mode === "scale-down" ? "center" : mode
215
236
  }), children);
216
237
  }
238
+ warnIfReload(source);
217
239
  const sources = Array.isArray(source) ? source.length === 1 ? void 0 : source : void 0;
218
240
  const single = Array.isArray(source) ? source[0] : source;
219
241
  const resolvedSource = sources ? void 0 : react_native.Image.resolveAssetSource(single);
@@ -112,6 +112,15 @@ export type FastImageSource = {
112
112
  scale?: number,
113
113
  }
114
114
 
115
+ // React Native's ImageURISource cache values, which the views' `source` takes
116
+ // so a React Native source works as it is: native reads 'only-if-cached' as
117
+ // 'cacheOnly', and the others as the default, 'immutable'.
118
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
119
+ type ViewSource = {
120
+ ...FastImageSource,
121
+ cache?: CacheControls | ReactNativeCache,
122
+ }
123
+
115
124
  export type FastImageProps = $ReadOnly<{|
116
125
  ...ViewProps,
117
126
  onError?: ?(event: OnErrorEvent) => void,
@@ -120,7 +129,7 @@ export type FastImageProps = $ReadOnly<{|
120
129
  onLoadStart?: ?() => void,
121
130
  onProgress?: ?(event: OnProgressEvent) => void,
122
131
 
123
- source?: ?(FastImageSource | Array<FastImageSource> | number),
132
+ source?: ?(ViewSource | Array<ViewSource> | number),
124
133
  defaultSource?: ?number,
125
134
 
126
135
  tintColor?: number | string,
@@ -112,6 +112,15 @@ export type FastImageSource = {
112
112
  scale?: number,
113
113
  }
114
114
 
115
+ // React Native's ImageURISource cache values, which the views' `source` takes
116
+ // so a React Native source works as it is: native reads 'only-if-cached' as
117
+ // 'cacheOnly', and the others as the default, 'immutable'.
118
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
119
+ type ViewSource = {
120
+ ...FastImageSource,
121
+ cache?: CacheControls | ReactNativeCache,
122
+ }
123
+
115
124
  export type FastImageProps = $ReadOnly<{|
116
125
  ...ViewProps,
117
126
  onError?: ?(event: OnErrorEvent) => void,
@@ -120,7 +129,7 @@ export type FastImageProps = $ReadOnly<{|
120
129
  onLoadStart?: ?() => void,
121
130
  onProgress?: ?(event: OnProgressEvent) => void,
122
131
 
123
- source?: ?(FastImageSource | Array<FastImageSource> | number),
132
+ source?: ?(ViewSource | Array<ViewSource> | number),
124
133
  defaultSource?: ?number,
125
134
 
126
135
  tintColor?: number | string,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { ColorValue, View, StyleProp, ViewStyle, ImageRequireSource, AccessibilityProps, ViewProps } from 'react-native';
3
3
  import { cacheControl, priority, resizeMode } from './constants';
4
+ import { type ReactNativeCache } from './reactNativeCache';
4
5
  /** How the image fits the view: see [`objectFit`](#objectfit). */
5
6
  export type ObjectFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
6
7
  /** How the image fits the view: see [`resizeMode`](#resizemode). */
@@ -99,6 +100,9 @@ export type Source = {
99
100
  /** With several sources, the scale `width` and `height` are multiplied by. */
100
101
  scale?: number;
101
102
  };
103
+ type ViewSource = Source | (Omit<Source, 'cache'> & {
104
+ cache?: ReactNativeCache;
105
+ });
102
106
  /** How the image fades in: see [`transition`](#transition). */
103
107
  export type Transition = {
104
108
  /**
@@ -277,7 +281,7 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
277
281
  * `{ ok: false, error }`.
278
282
  * - An array of one is the same as that source.
279
283
  */
280
- source?: Source | Source[] | ImageRequireSource;
284
+ source?: ViewSource | ViewSource[] | ImageRequireSource;
281
285
  /**
282
286
  * An asset loaded with `require(...)`, shown while the first image loads,
283
287
  * and if an image fails to load. When `source` changes, the previous image
package/dist/index.js CHANGED
@@ -55,6 +55,24 @@ function resolveObjectFit(objectFit, style, resizeMode) {
55
55
  return (_RESIZE_MODE_FIT$resi = RESIZE_MODE_FIT[resizeMode]) !== null && _RESIZE_MODE_FIT$resi !== void 0 ? _RESIZE_MODE_FIT$resi : "cover";
56
56
  }
57
57
  //#endregion
58
+ //#region src/reactNativeCache.ts
59
+ const REACT_NATIVE_CACHE = [
60
+ "default",
61
+ "reload",
62
+ "force-cache",
63
+ "only-if-cached"
64
+ ];
65
+ const isReactNativeCache = (cache) => REACT_NATIVE_CACHE.includes(cache);
66
+ let warnedReload = false;
67
+ function warnIfReload(source) {
68
+ if (warnedReload || typeof __DEV__ === "undefined" || !__DEV__) return;
69
+ for (const entry of Array.isArray(source) ? source : [source]) if ((entry === null || entry === void 0 ? void 0 : entry.cache) === "reload") {
70
+ warnedReload = true;
71
+ console.warn("react-native-fast-image: `cache: 'reload'` loads the image as the default, `'immutable'`: it isn't loaded again each time. For an image that changes at the same url, use `cache: 'web'` (it follows the server's cache headers), or change its `cacheKey`.");
72
+ return;
73
+ }
74
+ }
75
+ //#endregion
58
76
  //#region src/index.tsx
59
77
  const resolveDefaultSource = (defaultSource) => {
60
78
  if (!defaultSource) return null;
@@ -112,8 +130,11 @@ function transitionProps(transition) {
112
130
  };
113
131
  }
114
132
  function withoutCache(source) {
115
- const { cache: _cache, ...rest } = source || {};
116
- return rest;
133
+ const { cache, ...rest } = source || {};
134
+ return isReactNativeCache(cache) ? {
135
+ ...rest,
136
+ cache
137
+ } : rest;
117
138
  }
118
139
  function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, fallback, children, objectFit, resizeMode = "cover", loop, transition, forwardedRef, onLayout, pointerEvents, hitSlop, onStartShouldSetResponder, onStartShouldSetResponderCapture, onMoveShouldSetResponder, onMoveShouldSetResponderCapture, onResponderGrant, onResponderReject, onResponderStart, onResponderMove, onResponderEnd, onResponderRelease, onResponderTerminationRequest, onResponderTerminate, onTouchStart, onTouchMove, onTouchEnd, onTouchCancel, onTouchEndCapture, ...viewProps }) {
119
140
  const { onClick, ...props } = viewProps;
@@ -187,6 +208,7 @@ function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgre
187
208
  resizeMode: mode === "none" || mode === "scale-down" ? "center" : mode
188
209
  }), children);
189
210
  }
211
+ warnIfReload(source);
190
212
  const sources = Array.isArray(source) ? source.length === 1 ? void 0 : source : void 0;
191
213
  const single = Array.isArray(source) ? source[0] : source;
192
214
  const resolvedSource = sources ? void 0 : Image.resolveAssetSource(single);
@@ -112,6 +112,15 @@ export type FastImageSource = {
112
112
  scale?: number,
113
113
  }
114
114
 
115
+ // React Native's ImageURISource cache values, which the views' `source` takes
116
+ // so a React Native source works as it is: native reads 'only-if-cached' as
117
+ // 'cacheOnly', and the others as the default, 'immutable'.
118
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
119
+ type ViewSource = {
120
+ ...FastImageSource,
121
+ cache?: CacheControls | ReactNativeCache,
122
+ }
123
+
115
124
  export type FastImageProps = $ReadOnly<{|
116
125
  ...ViewProps,
117
126
  onError?: ?(event: OnErrorEvent) => void,
@@ -120,7 +129,7 @@ export type FastImageProps = $ReadOnly<{|
120
129
  onLoadStart?: ?() => void,
121
130
  onProgress?: ?(event: OnProgressEvent) => void,
122
131
 
123
- source?: ?(FastImageSource | Array<FastImageSource> | number),
132
+ source?: ?(ViewSource | Array<ViewSource> | number),
124
133
  defaultSource?: ?number,
125
134
 
126
135
  tintColor?: number | string,
@@ -112,6 +112,15 @@ export type FastImageSource = {
112
112
  scale?: number,
113
113
  }
114
114
 
115
+ // React Native's ImageURISource cache values, which the views' `source` takes
116
+ // so a React Native source works as it is: native reads 'only-if-cached' as
117
+ // 'cacheOnly', and the others as the default, 'immutable'.
118
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
119
+ type ViewSource = {
120
+ ...FastImageSource,
121
+ cache?: CacheControls | ReactNativeCache,
122
+ }
123
+
115
124
  export type FastImageProps = $ReadOnly<{|
116
125
  ...ViewProps,
117
126
  onError?: ?(event: OnErrorEvent) => void,
@@ -120,7 +129,7 @@ export type FastImageProps = $ReadOnly<{|
120
129
  onLoadStart?: ?() => void,
121
130
  onProgress?: ?(event: OnProgressEvent) => void,
122
131
 
123
- source?: ?(FastImageSource | Array<FastImageSource> | number),
132
+ source?: ?(ViewSource | Array<ViewSource> | number),
124
133
  defaultSource?: ?number,
125
134
 
126
135
  tintColor?: number | string,
@@ -0,0 +1,4 @@
1
+ export type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached';
2
+ export declare const isReactNativeCache: (cache: unknown) => cache is ReactNativeCache;
3
+ export declare function resetReloadWarning(): void;
4
+ export declare function warnIfReload(source: unknown): void;
@@ -24,6 +24,9 @@ RCT_ENUM_CONVERTER(FFFCacheControl, (@{
24
24
  @"immutable": @(FFFCacheControlImmutable),
25
25
  @"web": @(FFFCacheControlWeb),
26
26
  @"cacheOnly": @(FFFCacheControlCacheOnly),
27
+ // React Native's ImageURISource value, which views
28
+ // take. Its others (e.g. 'reload') are the default.
29
+ @"only-if-cached": @(FFFCacheControlCacheOnly),
27
30
  }), FFFCacheControlImmutable, integerValue);
28
31
 
29
32
  + (FFFastImageSource *)FFFastImageSource:(id)json {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "9.3.7",
3
+ "version": "9.4.0",
4
4
  "description": "FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",