react-native-fast-image 8.6.37 → 8.6.39

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
@@ -139,7 +139,7 @@ Indicates the load order priority of an image. Images with `FastImage.priority.h
139
139
  ### `source.cache?: enum`
140
140
 
141
141
  - `FastImage.cacheControl.immutable` - **(Default)** - Only updates if url changes.
142
- - `FastImage.cacheControl.web` - Use headers and follow normal caching procedures.
142
+ - `FastImage.cacheControl.web` - Use headers and follow normal caching procedures. On Android these responses are kept in a 50 MB HTTP cache (or the app's own, if its OkHttp client has one).
143
143
  - `FastImage.cacheControl.cacheOnly` - Only show images from cache, do not make any network requests.
144
144
 
145
145
  ---
@@ -7,16 +7,22 @@ import com.bumptech.glide.Glide;
7
7
  import com.bumptech.glide.Registry;
8
8
  import com.bumptech.glide.annotation.GlideModule;
9
9
  import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
10
+ import com.bumptech.glide.load.Options;
10
11
  import com.bumptech.glide.load.model.GlideUrl;
12
+ import com.bumptech.glide.load.model.ModelLoader;
13
+ import com.bumptech.glide.load.model.ModelLoaderFactory;
14
+ import com.bumptech.glide.load.model.MultiModelLoaderFactory;
11
15
  import com.bumptech.glide.module.LibraryGlideModule;
12
16
  import com.facebook.react.modules.network.OkHttpClientProvider;
13
17
 
18
+ import java.io.File;
14
19
  import java.io.IOException;
15
20
  import java.io.InputStream;
16
21
  import java.util.HashMap;
17
22
  import java.util.Map;
18
23
  import java.util.WeakHashMap;
19
24
 
25
+ import okhttp3.Cache;
20
26
  import okhttp3.Interceptor;
21
27
  import okhttp3.MediaType;
22
28
  import okhttp3.OkHttpClient;
@@ -33,6 +39,7 @@ import okio.Source;
33
39
  public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
34
40
 
35
41
  private static final DispatchingProgressListener progressListener = new DispatchingProgressListener();
42
+ private static final long WEB_CACHE_SIZE = 50 * 1024 * 1024;
36
43
 
37
44
  @Override
38
45
  public void registerComponents(
@@ -47,6 +54,47 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
47
54
  .build();
48
55
  OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(client);
49
56
  registry.replace(GlideUrl.class, InputStream.class, factory);
57
+
58
+ // `cache: 'web'` skips Glide's caches and relies on HTTP caching, but
59
+ // React Native's shared client has no HTTP cache (unless the app gave
60
+ // it one), so those urls get a client with one (#280). Other urls are
61
+ // cached by Glide, so they don't use it (that would store them twice).
62
+ OkHttpClient webClient = client.cache() != null
63
+ ? client
64
+ : client.newBuilder()
65
+ .cache(new Cache(new File(context.getCacheDir(), "fast-image-http-cache"), WEB_CACHE_SIZE))
66
+ .build();
67
+ registry.prepend(FastImageWebGlideUrl.class, InputStream.class, new WebUrlLoaderFactory(webClient));
68
+ }
69
+
70
+ // Loads FastImageWebGlideUrls with the given client.
71
+ private static class WebUrlLoaderFactory implements ModelLoaderFactory<FastImageWebGlideUrl, InputStream> {
72
+ private final OkHttpClient client;
73
+
74
+ WebUrlLoaderFactory(OkHttpClient client) {
75
+ this.client = client;
76
+ }
77
+
78
+ @NonNull
79
+ @Override
80
+ public ModelLoader<FastImageWebGlideUrl, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
81
+ final OkHttpUrlLoader loader = new OkHttpUrlLoader(client);
82
+ return new ModelLoader<FastImageWebGlideUrl, InputStream>() {
83
+ @Override
84
+ public LoadData<InputStream> buildLoadData(@NonNull FastImageWebGlideUrl model, int width, int height, @NonNull Options options) {
85
+ return loader.buildLoadData(model, width, height, options);
86
+ }
87
+
88
+ @Override
89
+ public boolean handles(@NonNull FastImageWebGlideUrl model) {
90
+ return true;
91
+ }
92
+ };
93
+ }
94
+
95
+ @Override
96
+ public void teardown() {
97
+ }
50
98
  }
51
99
 
52
100
  private static Interceptor createInterceptor(final ResponseProgressListener listener) {
@@ -92,7 +140,10 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
92
140
  @Override
93
141
  public void update(final String key, final long bytesRead, final long contentLength) {
94
142
  final FastImageProgressListener listener = LISTENERS.get(key);
95
- if (listener == null) {
143
+ // Without a Content-Length the total is unknown (-1), and a
144
+ // percentage can't be worked out from it, so don't send those. (It
145
+ // also looked like the last update, which stopped all updates.)
146
+ if (listener == null || contentLength <= 0) {
96
147
  return;
97
148
  }
98
149
  if (contentLength <= bytesRead) {
@@ -117,7 +117,16 @@ public class FastImageSource extends ImageSource {
117
117
  return mHeaders;
118
118
  }
119
119
 
120
+ // Set for `cache: 'web'`.
121
+ private boolean mWebCache = false;
122
+
123
+ void setWebCache(boolean webCache) {
124
+ mWebCache = webCache;
125
+ }
126
+
120
127
  public GlideUrl getGlideUrl() {
121
- return new GlideUrl(getUri().toString(), getHeaders());
128
+ return mWebCache
129
+ ? new FastImageWebGlideUrl(getUri().toString(), getHeaders())
130
+ : new GlideUrl(getUri().toString(), getHeaders());
122
131
  }
123
132
  }
@@ -60,9 +60,10 @@ class FastImageViewConverter {
60
60
  // Resolve the source uri to a file path that android understands.
61
61
  static @Nullable
62
62
  FastImageSource getImageSource(Context context, @Nullable ReadableMap source) {
63
- return source == null
64
- ? null
65
- : new FastImageSource(context, source.getString("uri"), getHeaders(source));
63
+ if (source == null) return null;
64
+ FastImageSource imageSource = new FastImageSource(context, source.getString("uri"), getHeaders(source));
65
+ imageSource.setWebCache(getCacheControl(source) == FastImageCacheControl.WEB);
66
+ return imageSource;
66
67
  }
67
68
 
68
69
  static Headers getHeaders(ReadableMap source) {
@@ -0,0 +1,13 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import com.bumptech.glide.load.model.GlideUrl;
4
+ import com.bumptech.glide.load.model.Headers;
5
+
6
+ // A url loaded with `cache: 'web'`. Glide doesn't cache these, so they load
7
+ // through an OkHttp client with an HTTP cache (see
8
+ // FastImageOkHttpProgressGlideModule) to follow the server's caching headers.
9
+ class FastImageWebGlideUrl extends GlideUrl {
10
+ FastImageWebGlideUrl(String url, Headers headers) {
11
+ super(url, headers);
12
+ }
13
+ }
@@ -247,6 +247,11 @@
247
247
  SDImageLoaderProgressBlock progress = nil;
248
248
  if (self.onFastImageProgress) {
249
249
  progress = ^(NSInteger receivedSize, NSInteger expectedSize, NSURL* _Nullable targetURL) {
250
+ // Without a Content-Length the total is unknown (-1 or 0), and a
251
+ // percentage can't be worked out from it, so don't send those.
252
+ if (expectedSize <= 0) {
253
+ return;
254
+ }
250
255
  // SDWebImage calls this on its download queue, while React Native
251
256
  // sets onFastImageProgress (and deallocates the view) on the main
252
257
  // queue. Read and call it there, so it can't change or be released
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "8.6.37",
3
+ "version": "8.6.39",
4
4
  "description": "🚩 FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",