react-native-fast-image 10.7.0 → 10.8.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 =
@@ -189,13 +192,12 @@ class FastImageViewConverter {
189
192
  return value;
190
193
  }
191
194
 
195
+ // A value the map doesn't have (e.g. React Native's `cache: 'reload'`, or
196
+ // one that isn't a string) gets the default, as on iOS.
192
197
  private static <T> T getValueFromSource(String propName, String defaultProp, Map<String, T> map, ReadableMap source) {
193
- String propValue;
194
- try {
195
- propValue = source != null ? source.getString(propName) : null;
196
- } catch (NoSuchKeyException e) {
197
- propValue = null;
198
- }
199
- return getValue(propName, defaultProp, map, propValue);
198
+ T value = source != null && source.hasKey(propName) && source.getType(propName) == ReadableType.String
199
+ ? map.get(source.getString(propName))
200
+ : null;
201
+ return value != null ? value : map.get(defaultProp);
200
202
  }
201
203
  }
package/dist/index.cjs.js CHANGED
@@ -301,6 +301,11 @@ function composeRefs(...refs) {
301
301
  };
302
302
  }
303
303
  //#endregion
304
+ //#region src/reactNativeCache.ts
305
+ function warnIfReload(source) {
306
+ if (typeof __DEV__ !== "undefined" && __DEV__ && (source === null || source === void 0 ? void 0 : source.cache) === "reload") warnOnce("cache-reload", "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`.", "warn");
307
+ }
308
+ //#endregion
304
309
  //#region src/index.tsx
305
310
  const resolvePlaceholder = (placeholder) => {
306
311
  if (typeof placeholder === "string") {
@@ -374,7 +379,10 @@ function FastImageBase({ source, placeholder, defaultSource, tintColor, onLoadSt
374
379
  const fit = resolveObjectFit(objectFit, style);
375
380
  const position = objectPositionOrCentered(objectPosition);
376
381
  const resolvedSource = (0, react.useMemo)(() => {
377
- for (const entry of [source].flat()) dataUri(entry === null || entry === void 0 ? void 0 : entry.blurDataUri);
382
+ for (const entry of [source].flat()) {
383
+ dataUri(entry === null || entry === void 0 ? void 0 : entry.blurDataUri);
384
+ warnIfReload(entry);
385
+ }
378
386
  const single = Array.isArray(source) && source.length === 1 ? source[0] : source;
379
387
  return Array.isArray(single) ? single.map((entry) => react_native.Image.resolveAssetSource(entry)) : react_native.Image.resolveAssetSource(single);
380
388
  }, [source]);
@@ -137,6 +137,15 @@ export type FastImageSource = {
137
137
  scale?: number,
138
138
  }
139
139
 
140
+ // React Native's ImageURISource cache values, which the views' `source` takes
141
+ // so a React Native source works as it is: native reads 'only-if-cached' as
142
+ // 'cacheOnly', and the others as the default, 'immutable'.
143
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
144
+ type ViewSource = {
145
+ ...FastImageSource,
146
+ cache?: CacheControls | ReactNativeCache,
147
+ }
148
+
140
149
  export type FastImageProps = $ReadOnly<{|
141
150
  ...ViewProps,
142
151
  onError?: ?(event: OnErrorEvent) => void,
@@ -145,7 +154,7 @@ export type FastImageProps = $ReadOnly<{|
145
154
  onLoadStart?: ?() => void,
146
155
  onProgress?: ?(event: OnProgressEvent) => void,
147
156
 
148
- source?: ?(FastImageSource | Array<FastImageSource | number> | number),
157
+ source?: ?(ViewSource | Array<ViewSource | number> | number),
149
158
  placeholder?: ?(number | string | SourcePlaceholder | PlaceholderSource),
150
159
  // Deprecated: use placeholder, which is the same.
151
160
  defaultSource?: ?number,
@@ -137,6 +137,15 @@ export type FastImageSource = {
137
137
  scale?: number,
138
138
  }
139
139
 
140
+ // React Native's ImageURISource cache values, which the views' `source` takes
141
+ // so a React Native source works as it is: native reads 'only-if-cached' as
142
+ // 'cacheOnly', and the others as the default, 'immutable'.
143
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
144
+ type ViewSource = {
145
+ ...FastImageSource,
146
+ cache?: CacheControls | ReactNativeCache,
147
+ }
148
+
140
149
  export type FastImageProps = $ReadOnly<{|
141
150
  ...ViewProps,
142
151
  onError?: ?(event: OnErrorEvent) => void,
@@ -145,7 +154,7 @@ export type FastImageProps = $ReadOnly<{|
145
154
  onLoadStart?: ?() => void,
146
155
  onProgress?: ?(event: OnProgressEvent) => void,
147
156
 
148
- source?: ?(FastImageSource | Array<FastImageSource | number> | number),
157
+ source?: ?(ViewSource | Array<ViewSource | number> | number),
149
158
  placeholder?: ?(number | string | SourcePlaceholder | PlaceholderSource),
150
159
  // Deprecated: use placeholder, which is the same.
151
160
  defaultSource?: ?number,
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ 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
4
  import { type ObjectPosition } from './objectPosition';
5
+ import { type ReactNativeCache } from './reactNativeCache';
5
6
  /** How the image fits the view: see [`objectFit`](#objectfit). */
6
7
  export type ObjectFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
7
8
  export type { ObjectPosition, PositionLength } from './objectPosition';
@@ -152,6 +153,9 @@ export type Source = {
152
153
  /** With several sources, the scale `width` and `height` are multiplied by. */
153
154
  scale?: number;
154
155
  };
156
+ type ViewSource = Source | (Omit<Source, 'cache'> & {
157
+ cache?: ReactNativeCache;
158
+ });
155
159
  /** A `thumbhash` or `blurDataUri` as `placeholder`. */
156
160
  export type SourcePlaceholder = Pick<Source, 'thumbhash' | 'blurDataUri'>;
157
161
  /** A url as `placeholder`, loaded like a source (see `placeholder`). */
@@ -334,7 +338,7 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
334
338
  * - A `require()`d image can be one of the sizes: its size is the file's.
335
339
  * - An array of one is the same as that source.
336
340
  */
337
- source?: Source | Array<Source | ImageRequireSource> | ImageRequireSource;
341
+ source?: ViewSource | Array<ViewSource | ImageRequireSource> | ImageRequireSource;
338
342
  /**
339
343
  * A placeholder shown while the image loads, and if it fails to load:
340
344
  *
package/dist/index.js CHANGED
@@ -274,6 +274,11 @@ function composeRefs(...refs) {
274
274
  };
275
275
  }
276
276
  //#endregion
277
+ //#region src/reactNativeCache.ts
278
+ function warnIfReload(source) {
279
+ if (typeof __DEV__ !== "undefined" && __DEV__ && (source === null || source === void 0 ? void 0 : source.cache) === "reload") warnOnce("cache-reload", "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`.", "warn");
280
+ }
281
+ //#endregion
277
282
  //#region src/index.tsx
278
283
  const resolvePlaceholder = (placeholder) => {
279
284
  if (typeof placeholder === "string") {
@@ -347,7 +352,10 @@ function FastImageBase({ source, placeholder, defaultSource, tintColor, onLoadSt
347
352
  const fit = resolveObjectFit(objectFit, style);
348
353
  const position = objectPositionOrCentered(objectPosition);
349
354
  const resolvedSource = useMemo(() => {
350
- for (const entry of [source].flat()) dataUri(entry === null || entry === void 0 ? void 0 : entry.blurDataUri);
355
+ for (const entry of [source].flat()) {
356
+ dataUri(entry === null || entry === void 0 ? void 0 : entry.blurDataUri);
357
+ warnIfReload(entry);
358
+ }
351
359
  const single = Array.isArray(source) && source.length === 1 ? source[0] : source;
352
360
  return Array.isArray(single) ? single.map((entry) => Image.resolveAssetSource(entry)) : Image.resolveAssetSource(single);
353
361
  }, [source]);
@@ -137,6 +137,15 @@ export type FastImageSource = {
137
137
  scale?: number,
138
138
  }
139
139
 
140
+ // React Native's ImageURISource cache values, which the views' `source` takes
141
+ // so a React Native source works as it is: native reads 'only-if-cached' as
142
+ // 'cacheOnly', and the others as the default, 'immutable'.
143
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
144
+ type ViewSource = {
145
+ ...FastImageSource,
146
+ cache?: CacheControls | ReactNativeCache,
147
+ }
148
+
140
149
  export type FastImageProps = $ReadOnly<{|
141
150
  ...ViewProps,
142
151
  onError?: ?(event: OnErrorEvent) => void,
@@ -145,7 +154,7 @@ export type FastImageProps = $ReadOnly<{|
145
154
  onLoadStart?: ?() => void,
146
155
  onProgress?: ?(event: OnProgressEvent) => void,
147
156
 
148
- source?: ?(FastImageSource | Array<FastImageSource | number> | number),
157
+ source?: ?(ViewSource | Array<ViewSource | number> | number),
149
158
  placeholder?: ?(number | string | SourcePlaceholder | PlaceholderSource),
150
159
  // Deprecated: use placeholder, which is the same.
151
160
  defaultSource?: ?number,
@@ -137,6 +137,15 @@ export type FastImageSource = {
137
137
  scale?: number,
138
138
  }
139
139
 
140
+ // React Native's ImageURISource cache values, which the views' `source` takes
141
+ // so a React Native source works as it is: native reads 'only-if-cached' as
142
+ // 'cacheOnly', and the others as the default, 'immutable'.
143
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
144
+ type ViewSource = {
145
+ ...FastImageSource,
146
+ cache?: CacheControls | ReactNativeCache,
147
+ }
148
+
140
149
  export type FastImageProps = $ReadOnly<{|
141
150
  ...ViewProps,
142
151
  onError?: ?(event: OnErrorEvent) => void,
@@ -145,7 +154,7 @@ export type FastImageProps = $ReadOnly<{|
145
154
  onLoadStart?: ?() => void,
146
155
  onProgress?: ?(event: OnProgressEvent) => void,
147
156
 
148
- source?: ?(FastImageSource | Array<FastImageSource | number> | number),
157
+ source?: ?(ViewSource | Array<ViewSource | number> | number),
149
158
  placeholder?: ?(number | string | SourcePlaceholder | PlaceholderSource),
150
159
  // Deprecated: use placeholder, which is the same.
151
160
  defaultSource?: ?number,
@@ -0,0 +1,2 @@
1
+ export type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached';
2
+ export declare function warnIfReload(source: unknown): void;
@@ -21,6 +21,9 @@ RCT_ENUM_CONVERTER(FFFCacheControl, (@{
21
21
  @"immutable": @(FFFCacheControlImmutable),
22
22
  @"web": @(FFFCacheControlWeb),
23
23
  @"cacheOnly": @(FFFCacheControlCacheOnly),
24
+ // React Native's ImageURISource value, which views
25
+ // take. Its others (e.g. 'reload') are the default.
26
+ @"only-if-cached": @(FFFCacheControlCacheOnly),
24
27
  }), FFFCacheControlImmutable, integerValue);
25
28
 
26
29
  + (FFFastImageSource *)FFFastImageSource:(id)json {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "10.7.0",
3
+ "version": "10.8.0",
4
4
  "description": "FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",
package/src/index.js.flow CHANGED
@@ -137,6 +137,15 @@ export type FastImageSource = {
137
137
  scale?: number,
138
138
  }
139
139
 
140
+ // React Native's ImageURISource cache values, which the views' `source` takes
141
+ // so a React Native source works as it is: native reads 'only-if-cached' as
142
+ // 'cacheOnly', and the others as the default, 'immutable'.
143
+ type ReactNativeCache = 'default' | 'reload' | 'force-cache' | 'only-if-cached'
144
+ type ViewSource = {
145
+ ...FastImageSource,
146
+ cache?: CacheControls | ReactNativeCache,
147
+ }
148
+
140
149
  export type FastImageProps = $ReadOnly<{|
141
150
  ...ViewProps,
142
151
  onError?: ?(event: OnErrorEvent) => void,
@@ -145,7 +154,7 @@ export type FastImageProps = $ReadOnly<{|
145
154
  onLoadStart?: ?() => void,
146
155
  onProgress?: ?(event: OnProgressEvent) => void,
147
156
 
148
- source?: ?(FastImageSource | Array<FastImageSource | number> | number),
157
+ source?: ?(ViewSource | Array<ViewSource | number> | number),
149
158
  placeholder?: ?(number | string | SourcePlaceholder | PlaceholderSource),
150
159
  // Deprecated: use placeholder, which is the same.
151
160
  defaultSource?: ?number,
package/src/index.tsx CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  placeholderSource,
24
24
  } from './placeholders'
25
25
  import { composeRefs } from './composeRefs'
26
+ import { type ReactNativeCache, warnIfReload } from './reactNativeCache'
26
27
  import { warnIfChildren, warnOnce } from './warnings'
27
28
 
28
29
  /** How the image fits the view: see [`objectFit`](#objectfit). */
@@ -178,6 +179,14 @@ export type Source = {
178
179
  scale?: number
179
180
  }
180
181
 
182
+ // What the views' `source` takes: a Source, or one with React Native's cache
183
+ // values (see reactNativeCache.ts), so a React Native `ImageURISource` works as
184
+ // it is. Only the views: preload, getCachePath, writeToCache and placeholder
185
+ // take Fast Image's values.
186
+ type ViewSource =
187
+ | Source
188
+ | (Omit<Source, 'cache'> & { cache?: ReactNativeCache })
189
+
181
190
  /** A `thumbhash` or `blurDataUri` as `placeholder`. */
182
191
  export type SourcePlaceholder = Pick<Source, 'thumbhash' | 'blurDataUri'>
183
192
 
@@ -366,7 +375,10 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
366
375
  * - A `require()`d image can be one of the sizes: its size is the file's.
367
376
  * - An array of one is the same as that source.
368
377
  */
369
- source?: Source | Array<Source | ImageRequireSource> | ImageRequireSource
378
+ source?:
379
+ | ViewSource
380
+ | Array<ViewSource | ImageRequireSource>
381
+ | ImageRequireSource
370
382
  /**
371
383
  * A placeholder shown while the image loads, and if it fails to load:
372
384
  *
@@ -901,9 +913,11 @@ function FastImageBase({
901
913
  // only those change. Memoized on source, so an unchanged source reaches
902
914
  // the native view as the same object, and React's prop diff stops at it.
903
915
  const resolvedSource = useMemo(() => {
904
- // A blurDataUri that isn't a data uri is ignored, with a warning.
916
+ // A blurDataUri that isn't a data uri is ignored, with a warning, and
917
+ // React Native's cache: 'reload' warns (native reads its cache values).
905
918
  for (const entry of [source].flat()) {
906
919
  dataUri((entry as Source | undefined)?.blurDataUri)
920
+ warnIfReload(entry)
907
921
  }
908
922
  const single =
909
923
  Array.isArray(source) && source.length === 1 ? source[0] : source
package/src/index.web.tsx CHANGED
@@ -399,10 +399,13 @@ function assetScale(asset: PackagerAsset): number {
399
399
  )
400
400
  }
401
401
 
402
+ // What sizedSources reads of a source.
403
+ type SizedSource = Pick<Source, 'uri' | 'width' | 'height' | 'scale'>
404
+
402
405
  // One of several sizes: a require()d image in react-native-web's asset
403
406
  // registry as a source with its file's size (Expo's web builds make it a
404
407
  // { uri, width, height } object already).
405
- function sizedSource(source: Source | number): Source | undefined {
408
+ function sizedSource(source: SizedSource | number): SizedSource | undefined {
406
409
  if (typeof source !== 'number') return source
407
410
  const asset: PackagerAsset | undefined = getAssetByID(source)
408
411
  return asset
@@ -422,10 +425,12 @@ function sizedSource(source: Source | number): Source | undefined {
422
425
  // is laid out at; it only applies to lazy images, and otherwise, or in
423
426
  // browsers without it, the next value, 100vw (the viewport's width). src is the largest, for browsers without
424
427
  // srcset.
425
- function sizedSources(entries: (Source | number)[]) {
428
+ function sizedSources(entries: (SizedSource | number)[]) {
426
429
  const sources = entries.map(sizedSource)
427
430
  const widths = sources
428
- .filter((source): source is Source => !!source?.uri && !!source.width)
431
+ .filter(
432
+ (source): source is SizedSource => !!source?.uri && !!source.width,
433
+ )
429
434
  .map((source) => ({
430
435
  uri: source.uri as string,
431
436
  width: Math.round((source.width ?? 0) * (source.scale ?? 1)),
@@ -0,0 +1,28 @@
1
+ // React Native's `ImageURISource` cache values, which the views' `source`
2
+ // takes so a source typed for React Native's Image works as it is. Not
3
+ // documented: Fast Image's own values are the ones to use. Native reads
4
+ // 'only-if-cached' as 'cacheOnly', and the others as the default, 'immutable'.
5
+ import { warnOnce } from './warnings'
6
+
7
+ declare const __DEV__: boolean | undefined
8
+
9
+ export type ReactNativeCache =
10
+ | 'default'
11
+ | 'reload'
12
+ | 'force-cache'
13
+ | 'only-if-cached'
14
+
15
+ // Warns for a source with 'reload', as the image isn't loaded again each time.
16
+ export function warnIfReload(source: unknown) {
17
+ if (
18
+ typeof __DEV__ !== 'undefined' &&
19
+ __DEV__ &&
20
+ (source as { cache?: unknown } | null | undefined)?.cache === 'reload'
21
+ ) {
22
+ warnOnce(
23
+ 'cache-reload',
24
+ "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`.",
25
+ 'warn',
26
+ )
27
+ }
28
+ }