react-native-fast-image 9.2.0 → 9.2.2

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 CHANGED
@@ -76,6 +76,8 @@ To set the cache's size when the app starts, see [Native config](#native-config)
76
76
 
77
77
  If your Android app has its own Glide `AppGlideModule`, read [using FastImage with an AppGlideModule](docs/android-build-settings.md#if-your-app-has-its-own-appglidemodule) first, or FastImage may not work.
78
78
 
79
+ On iOS, FastImage works with SDWebImage 5.11.1 and later, but apps that run on iOS 26 or later need 5.21.4 or later: earlier versions can crash there while loading images ([SDWebImage#3849](https://github.com/SDWebImage/SDWebImage/issues/3849)). A new install gets the latest version. If your `Podfile.lock` has an older one, update it with `cd ios && pod update SDWebImage`.
80
+
79
81
  ## Usage
80
82
 
81
83
  ```jsx
@@ -529,9 +531,9 @@ for (const result of results) {
529
531
  }
530
532
  ```
531
533
 
532
- Each source's `cache` applies, as for a view: with `web` the preload follows the HTTP cache, and with `cacheOnly` it doesn't download. A `cacheOnly` preload resolves `ok` only if the image is cached, and loads it from the disk cache into memory, so a view shows it at once.
534
+ Each source's `cache` applies, as for a view: with `web` the preload follows the HTTP cache, and with `cacheOnly` it doesn't download. A `cacheOnly` preload resolves `ok` only if the image is cached.
533
535
 
534
- A source with `memoryCache: false` is only downloaded to the disk cache, without being decoded into memory, and is decoded when it's shown. Use it to preload many images, or large ones, e.g. the next pages of a feed: a decoded photo can take tens of MB of memory. Other sources are also kept decoded in memory, so they show at once.
536
+ A source with `memoryCache: false` is only downloaded to the disk cache, without being decoded into memory, and is decoded when it's shown. Use it to preload many images, or large ones, e.g. the next pages of a feed: a decoded photo can take tens of MB of memory. Other sources are decoded too. A view showing a preloaded image loads it from the cache for its own size: it doesn't wait for the network, but it fades in as other images from the disk cache do (see `transition`'s `skipOnCacheHit`).
535
537
 
536
538
  ```js
537
539
  await FastImage.preload(photos.map((uri) => ({ uri, memoryCache: false })))
@@ -765,7 +767,7 @@ How the image fades in: see [`transition`](#transition).
765
767
  - `'all'`: skips it for images from the memory or disk cache too, so images that download fade in, and local files and bundled images usually only the first time (the disk cache usually keeps them too).
766
768
  - `'none'`: always fades.
767
769
 
768
- Downloads, local files and bundled images (`require()`) fade in.
770
+ Downloads, local files and bundled images (`require()`) fade in. On Android, a `cache: 'web'` image from its HTTP cache, without a request, counts as one from the memory cache (these images aren't kept there).
769
771
 
770
772
  <!-- api:types end -->
771
773
 
@@ -370,11 +370,18 @@ final class FastImageSharedDownloads {
370
370
  // A preload's file is from Glide's disk cache. A download is remote
371
371
  // for every request reading it: Glide stores it in its disk cache once
372
372
  // (a request that finds it there already reads it from there), and
373
- // fades the image in as for any download.
373
+ // fades the image in as for any download. A `web` image's response
374
+ // from its HTTP cache, without the network, is from a disk cache too
375
+ // (OkHttp's; Glide doesn't store `web` images in its own).
374
376
  @NonNull
375
377
  @Override
376
378
  public DataSource getDataSource() {
377
- return fromFile ? DataSource.DATA_DISK_CACHE : DataSource.REMOTE;
379
+ if (fromFile) return DataSource.DATA_DISK_CACHE;
380
+ Download joined;
381
+ synchronized (downloads) {
382
+ joined = download;
383
+ }
384
+ return joined != null && joined.fromHttpCache ? DataSource.DATA_DISK_CACHE : DataSource.REMOTE;
378
385
  }
379
386
  }
380
387
 
@@ -553,6 +560,9 @@ final class FastImageSharedDownloads {
553
560
  // bytes it had received).
554
561
  private long reserved = 0;
555
562
  private boolean silent = false;
563
+ // Whether the response came from the HTTP cache of `web` images
564
+ // without the network (set before its bytes are read).
565
+ private volatile boolean fromHttpCache = false;
556
566
 
557
567
  // With downloads locked.
558
568
  private Download(String key, GlideUrl url, OkHttpClient client, Request request, Priority priority) {
@@ -838,6 +848,9 @@ final class FastImageSharedDownloads {
838
848
  fail(new HttpException(response.message(), response.code()));
839
849
  return;
840
850
  }
851
+ // OkHttp has no network response for one it served from the
852
+ // cache without checking with the server.
853
+ fromHttpCache = response.networkResponse() == null && response.cacheResponse() != null;
841
854
  final long length = body.contentLength();
842
855
  synchronized (downloads) {
843
856
  // No progress without a length.
@@ -288,14 +288,20 @@ class FastImageViewWithUrl extends AppCompatImageView implements ReactPointerEve
288
288
  // Fades a loaded image in, unless it's from a cache that skipOnCacheHit
289
289
  // skips, as Glide's and Coil's cross-fades and Fresco decide: from the
290
290
  // memory cache it shows at once (by default), and from the disk cache
291
- // too with 'all'. Downloads, local files and bundled images fade.
291
+ // too with 'all'. Downloads, local files and bundled images fade. A `web`
292
+ // image isn't kept in the memory cache, so one from its HTTP cache
293
+ // without the network (a disk cache hit, see FastImageSharedDownloads)
294
+ // counts as one from memory: shown again, e.g. in a list scrolled back
295
+ // up, it shows at once.
292
296
  private final class FadeFactory implements TransitionFactory<Drawable> {
293
297
  private final int duration;
294
298
  private final String skipOnCacheHit;
299
+ private final boolean webCache;
295
300
 
296
- FadeFactory(int duration, String skipOnCacheHit) {
301
+ FadeFactory(int duration, String skipOnCacheHit, boolean webCache) {
297
302
  this.duration = duration;
298
303
  this.skipOnCacheHit = skipOnCacheHit;
304
+ this.webCache = webCache;
299
305
  }
300
306
 
301
307
  @Override
@@ -314,6 +320,7 @@ class FastImageViewWithUrl extends AppCompatImageView implements ReactPointerEve
314
320
  private boolean skips(DataSource dataSource) {
315
321
  if (skipOnCacheHit.equals("none")) return false;
316
322
  if (dataSource == DataSource.MEMORY_CACHE) return true;
323
+ if (webCache && dataSource == DataSource.DATA_DISK_CACHE) return true;
317
324
  // Glide also keeps a local file's or bundled image's decoded
318
325
  // image in its disk cache (at the size it was decoded at, and not
319
326
  // for GIFs), so with 'all' they usually only fade the first time.
@@ -1056,7 +1063,10 @@ class FastImageViewWithUrl extends AppCompatImageView implements ReactPointerEve
1056
1063
  boolean replacing = shownRequest != null && model != null;
1057
1064
  if (mTransitionDuration > 0 && !switching && (!replacing || mTransitionBetweenImages)) {
1058
1065
  builder = builder.transition(DrawableTransitionOptions.with(
1059
- new FadeFactory(mTransitionDuration, mTransitionSkipOnCacheHit)));
1066
+ new FadeFactory(
1067
+ mTransitionDuration,
1068
+ mTransitionSkipOnCacheHit,
1069
+ imageSource != null && imageSource.isWebCache())));
1060
1070
  }
1061
1071
  if (thumbnail) {
1062
1072
  builder = builder.thumbnail(fromCache(shownRequest));
package/dist/index.d.ts CHANGED
@@ -122,7 +122,9 @@ export type Transition = {
122
122
  * usually only the first time (the disk cache usually keeps them too).
123
123
  * - `'none'`: always fades.
124
124
  *
125
- * Downloads, local files and bundled images (`require()`) fade in.
125
+ * Downloads, local files and bundled images (`require()`) fade in. On
126
+ * Android, a `cache: 'web'` image from its HTTP cache, without a request,
127
+ * counts as one from the memory cache (these images aren't kept there).
126
128
  * @default 'memory'
127
129
  */
128
130
  skipOnCacheHit?: 'none' | 'memory' | 'all' | null;
@@ -1048,6 +1048,11 @@ NSString *FFFErrorMessage(NSError *error)
1048
1048
  // queue. Read and call it there, so it can't change or be released
1049
1049
  // in between (EXC_BAD_ACCESS).
1050
1050
  dispatch_async(dispatch_get_main_queue(), ^{
1051
+ // Sent before the load was cancelled (the source changed) but
1052
+ // run after: it's not the current load's progress.
1053
+ if (weakSelf.loadCount != load) {
1054
+ return;
1055
+ }
1051
1056
  RCTDirectEventBlock onProgress = weakSelf.onFastImageProgress;
1052
1057
  if (onProgress) {
1053
1058
  onProgress(@{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "9.2.0",
3
+ "version": "9.2.2",
4
4
  "description": "FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",