react-native-fast-image 10.0.0 → 10.1.1
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 +11 -1
- package/android/src/main/java/com/fastimage/FastImageGlide.java +10 -0
- package/android/src/main/java/com/fastimage/FastImageOkHttpProgressGlideModule.java +13 -5
- package/android/src/main/java/com/fastimage/FastImageSource.java +11 -0
- package/android/src/main/java/com/fastimage/FastImageViewConverter.java +17 -1
- package/android/src/main/java/com/fastimage/FastImageViewModule.java +19 -0
- package/dist/index.cjs.js.flow +1 -0
- package/dist/index.cjs.web.js.flow +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js.flow +1 -0
- package/dist/index.web.js.flow +1 -0
- package/ios/FastImage/FFFastImageModule.mm +19 -0
- package/ios/FastImage/FFFastImageSource.h +4 -0
- package/ios/FastImage/FFFastImageSource.m +5 -1
- package/ios/FastImage/FFFastImageView.m +35 -8
- package/ios/FastImage/RCTConvert+FFFastImage.m +2 -0
- package/package.json +1 -1
- package/src/index.js.flow +1 -0
- package/src/index.tsx +25 -0
package/README.md
CHANGED
|
@@ -201,6 +201,16 @@ Whether the decoded image is kept in the memory cache. With `false` it's only ke
|
|
|
201
201
|
|
|
202
202
|
---
|
|
203
203
|
|
|
204
|
+
##### `source.diskCache`
|
|
205
|
+
|
|
206
|
+
**Type:** `boolean` · **Default:** `true`
|
|
207
|
+
|
|
208
|
+
Whether the image is kept on disk. With `false` it isn't kept in the disk cache or an HTTP cache, or read from them. Use it for images the app shouldn't keep once they've been shown (e.g. disappearing messages, or where a security policy doesn't allow caching sensitive images), images that change every time they load, or large images shown once, which would push other images out of the disk cache. The image is downloaded again whenever it isn't in memory, e.g. for a view of another size (or on Android, a change of `blurRadius` or `objectFit`), so with `memoryCache: false` too it's downloaded each time it's shown. With `cache: 'web'` it isn't kept in memory either, so it's downloaded every time it loads. With `cache: 'cacheOnly'` it's only looked for in memory. On Android, a large download is held in a temporary file while it loads, as every download is, deleted as soon as it's opened.
|
|
209
|
+
|
|
210
|
+
`FastImage.preload`, `getCachePath` and `writeToCache` resolve not `ok` for it: there's no file, and a view decodes the image for its own size, so it may download a preloaded one again. A source for the same url (or `cacheKey`) without `diskCache: false` still stores the image.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
204
214
|
##### `source.width`
|
|
205
215
|
|
|
206
216
|
**Type:** `number`
|
|
@@ -873,7 +883,7 @@ FastImage works on the web with [react-native-web](https://necolas.github.io/rea
|
|
|
873
883
|
Support is minimal:
|
|
874
884
|
|
|
875
885
|
- Props that work: `source` (a `uri`, a `require()`d image, or several sizes), `defaultSource`, `objectFit`, `objectPosition`, `tintColor`, `blurRadius`, `style`, `onLoadStart`, `onLoad`, `onError`, `onLoadEnd`, and View props such as `testID`, accessibility props, `onLayout` and `pointerEvents`.
|
|
876
|
-
- Ignored: `source.headers` (a browser can't send them for an image), `source.priority`, `source.cache`, `source.cacheKey`, `source.memoryCache`, `recyclingKey`, `loop`, `imageRendering`, `paused`, `transition`, `downsample` and `onProgress`.
|
|
886
|
+
- Ignored: `source.headers` (a browser can't send them for an image), `source.priority`, `source.cache`, `source.cacheKey`, `source.memoryCache`, `source.diskCache`, `recyclingKey`, `loop`, `imageRendering`, `paused`, `transition`, `downsample` and `onProgress`.
|
|
877
887
|
- The image is an `<img>` element that fills the view inside its borders, with `objectFit` and `objectPosition` as its CSS `object-fit` and `object-position`. `tintColor` is an SVG filter and `blurRadius` a CSS `blur()`, and `defaultSource` is another `<img>`, under the image until it has loaded. A new `source` gets a new `<img>`, so the previous image doesn't stay while it loads (with several sizes, the browser shows it until the new one has loaded).
|
|
878
888
|
- Several sizes are shown with a lazily loaded `<img>` whose `srcset` lists them, with `sizes="auto, 100vw"`: the browser loads the one for the width the image is shown at, in device pixels (usually the smallest that's at least as wide). Browsers that don't support `sizes="auto"` use the viewport's width.
|
|
879
889
|
- `FastImage.preload` loads the images into the browser's cache and resolves with a result per source. `clearMemoryCache`, `clearDiskCache` and `configureCache` resolve without doing anything (the browser manages its cache), and `getCachePath` and `writeToCache` resolve with `{ ok: false, error: 'Not supported on the web' }`.
|
|
@@ -22,6 +22,16 @@ final class FastImageGlide {
|
|
|
22
22
|
return Boolean.TRUE.equals(options.get(REQUEST));
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// Set for a source with diskCache false: its download goes through a
|
|
26
|
+
// client without an HTTP cache (FastImageOkHttpProgressGlideModule), so
|
|
27
|
+
// neither the `web` images' HTTP cache nor one the app gave its client
|
|
28
|
+
// keeps it.
|
|
29
|
+
static final Option<Boolean> NO_STORE = Option.memory("com.fastimage.NoStore", false);
|
|
30
|
+
|
|
31
|
+
static boolean isNoStore(@NonNull Options options) {
|
|
32
|
+
return Boolean.TRUE.equals(options.get(NO_STORE));
|
|
33
|
+
}
|
|
34
|
+
|
|
25
35
|
// The Glide instance FastImage's components (FastImageOkHttpProgressGlideModule)
|
|
26
36
|
// were registered with.
|
|
27
37
|
private static volatile Glide registered;
|
|
@@ -154,7 +154,10 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
|
|
|
154
154
|
webCache = new Cache(new File(context.getCacheDir(), "fast-image-http-cache"), WEB_CACHE_SIZE);
|
|
155
155
|
webClient = client.newBuilder().cache(webCache).build();
|
|
156
156
|
FastImageSharedDownloads.setDirectory(new File(context.getCacheDir(), "fast-image-downloads"));
|
|
157
|
-
|
|
157
|
+
// diskCache false: no HTTP cache at all, also when the app's client has
|
|
158
|
+
// one.
|
|
159
|
+
OkHttpClient noStoreClient = client.newBuilder().cache(null).build();
|
|
160
|
+
registry.prepend(FastImageUrl.class, InputStream.class, new UrlLoaderFactory(client, webClient, noStoreClient));
|
|
158
161
|
FastImageSvg.register(registry, glide.getBitmapPool());
|
|
159
162
|
FastImageAnimated.register(context, glide, registry);
|
|
160
163
|
FastImageApng.register(registry);
|
|
@@ -168,16 +171,19 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
|
|
|
168
171
|
// Loads FastImage's remote images (FastImageUrls), with one download of an
|
|
169
172
|
// image at a time, shared by its requests (FastImageSharedDownloads):
|
|
170
173
|
// `web` ones (FastImageWebGlideUrls) with the client with the HTTP cache,
|
|
171
|
-
// others with the other client
|
|
174
|
+
// others with the other client, and those with diskCache false
|
|
175
|
+
// (FastImageGlide.NO_STORE) with a client without any. FastImageUrl isn't a GlideUrl, so Glide
|
|
172
176
|
// doesn't also give these to other GlideUrl loaders, which it would try
|
|
173
177
|
// after a failed load (e.g. a 404, requested again).
|
|
174
178
|
private static class UrlLoaderFactory implements ModelLoaderFactory<FastImageUrl, InputStream> {
|
|
175
179
|
private final OkHttpClient client;
|
|
176
180
|
private final OkHttpClient webClient;
|
|
181
|
+
private final OkHttpClient noStoreClient;
|
|
177
182
|
|
|
178
|
-
UrlLoaderFactory(OkHttpClient client, OkHttpClient webClient) {
|
|
183
|
+
UrlLoaderFactory(OkHttpClient client, OkHttpClient webClient, OkHttpClient noStoreClient) {
|
|
179
184
|
this.client = client;
|
|
180
185
|
this.webClient = webClient;
|
|
186
|
+
this.noStoreClient = noStoreClient;
|
|
181
187
|
}
|
|
182
188
|
|
|
183
189
|
@NonNull
|
|
@@ -186,8 +192,10 @@ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
|
|
|
186
192
|
return new ModelLoader<FastImageUrl, InputStream>() {
|
|
187
193
|
@Override
|
|
188
194
|
public LoadData<InputStream> buildLoadData(@NonNull FastImageUrl model, int width, int height, @NonNull Options options) {
|
|
189
|
-
|
|
190
|
-
|
|
195
|
+
OkHttpClient urlClient = FastImageGlide.isNoStore(options) ? noStoreClient
|
|
196
|
+
: model.url instanceof FastImageWebGlideUrl ? webClient
|
|
197
|
+
: client;
|
|
198
|
+
return FastImageSharedDownloads.loadData(model.url, urlClient);
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
@Override
|
|
@@ -156,6 +156,17 @@ public class FastImageSource extends ImageSource {
|
|
|
156
156
|
return mMemoryCache;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
// `diskCache`: whether the image is kept in the disk cache.
|
|
160
|
+
private boolean mDiskCache = true;
|
|
161
|
+
|
|
162
|
+
void setDiskCache(boolean diskCache) {
|
|
163
|
+
mDiskCache = diskCache;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
boolean isDiskCache() {
|
|
167
|
+
return mDiskCache;
|
|
168
|
+
}
|
|
169
|
+
|
|
159
170
|
// An http(s) url.
|
|
160
171
|
boolean isRemote() {
|
|
161
172
|
String scheme = mUri == null ? null : mUri.getScheme();
|
|
@@ -62,6 +62,13 @@ class FastImageViewConverter {
|
|
|
62
62
|
return uri != null && !uri.trim().isEmpty();
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// `diskCache`: whether the image is kept in the disk cache (true unless
|
|
66
|
+
// the source sets false).
|
|
67
|
+
static boolean isDiskCache(@Nullable ReadableMap source) {
|
|
68
|
+
return source == null || !source.hasKey("diskCache") || source.getType("diskCache") != ReadableType.Boolean
|
|
69
|
+
|| source.getBoolean("diskCache");
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
// Resolve the source uri to a file path that android understands.
|
|
66
73
|
static @Nullable
|
|
67
74
|
FastImageSource getImageSource(Context context, @Nullable ReadableMap source) {
|
|
@@ -71,6 +78,7 @@ class FastImageViewConverter {
|
|
|
71
78
|
if (source.hasKey("memoryCache") && source.getType("memoryCache") == ReadableType.Boolean) {
|
|
72
79
|
imageSource.setMemoryCache(source.getBoolean("memoryCache"));
|
|
73
80
|
}
|
|
81
|
+
imageSource.setDiskCache(isDiskCache(source));
|
|
74
82
|
if (source.hasKey("cacheKey") && source.getType("cacheKey") == ReadableType.String) {
|
|
75
83
|
imageSource.setCacheKey(source.getString("cacheKey"));
|
|
76
84
|
}
|
|
@@ -120,6 +128,13 @@ class FastImageViewConverter {
|
|
|
120
128
|
break;
|
|
121
129
|
}
|
|
122
130
|
|
|
131
|
+
// diskCache false: neither written to Glide's disk cache nor read from
|
|
132
|
+
// it, nor to an HTTP cache (NO_STORE).
|
|
133
|
+
final boolean noStore = imageSource != null && !imageSource.isDiskCache();
|
|
134
|
+
if (noStore) {
|
|
135
|
+
diskCacheStrategy = DiskCacheStrategy.NONE;
|
|
136
|
+
}
|
|
137
|
+
|
|
123
138
|
RequestOptions options = new RequestOptions()
|
|
124
139
|
.diskCacheStrategy(diskCacheStrategy)
|
|
125
140
|
.onlyRetrieveFromCache(onlyFromCache)
|
|
@@ -127,7 +142,8 @@ class FastImageViewConverter {
|
|
|
127
142
|
.skipMemoryCache(skipMemoryCache || (imageSource != null && !imageSource.isMemoryCache()))
|
|
128
143
|
.priority(priority)
|
|
129
144
|
.placeholder(TRANSPARENT_DRAWABLE)
|
|
130
|
-
.set(FastImageGlide.REQUEST, true)
|
|
145
|
+
.set(FastImageGlide.REQUEST, true)
|
|
146
|
+
.set(FastImageGlide.NO_STORE, noStore);
|
|
131
147
|
|
|
132
148
|
// imageSource is null when only a defaultSource is shown.
|
|
133
149
|
if (imageSource != null && imageSource.isResource()) {
|
|
@@ -136,6 +136,13 @@ class FastImageViewModule extends NativeFastImageModuleSpec {
|
|
|
136
136
|
finishOne.run();
|
|
137
137
|
continue;
|
|
138
138
|
}
|
|
139
|
+
// Views decode an image for their own size, so one only
|
|
140
|
+
// preloaded into memory would be downloaded again.
|
|
141
|
+
if (!FastImageViewConverter.isDiskCache(source)) {
|
|
142
|
+
results[i] = failure(NOT_ON_DISK);
|
|
143
|
+
finishOne.run();
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
139
146
|
final FastImageSource imageSource = FastImageViewConverter.getImageSource(context, source);
|
|
140
147
|
// A uri that can't be resolved (e.g. a relative path) resolves
|
|
141
148
|
// to an empty one.
|
|
@@ -314,6 +321,10 @@ class FastImageViewModule extends NativeFastImageModuleSpec {
|
|
|
314
321
|
}
|
|
315
322
|
}
|
|
316
323
|
|
|
324
|
+
// preload's, getCachePath's and writeToCache's error for a source with
|
|
325
|
+
// diskCache false.
|
|
326
|
+
private static final String NOT_ON_DISK = "The source has diskCache: false, so it isn't kept on disk";
|
|
327
|
+
|
|
317
328
|
private static WritableMap failure(String error) {
|
|
318
329
|
WritableMap result = Arguments.createMap();
|
|
319
330
|
result.putBoolean("ok", false);
|
|
@@ -342,6 +353,10 @@ class FastImageViewModule extends NativeFastImageModuleSpec {
|
|
|
342
353
|
@Override
|
|
343
354
|
public void getCachePath(final ReadableMap source, final Promise promise) {
|
|
344
355
|
final ReactApplicationContext context = getReactApplicationContext();
|
|
356
|
+
if (!FastImageViewConverter.isDiskCache(source)) {
|
|
357
|
+
promise.resolve(failure(NOT_ON_DISK));
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
345
360
|
if (!FastImageViewConverter.hasUri(source)) {
|
|
346
361
|
// `web` images ignore cacheKey.
|
|
347
362
|
final String cacheKey = FastImageViewConverter.getCacheControl(source) == FastImageCacheControl.WEB
|
|
@@ -474,6 +489,10 @@ class FastImageViewModule extends NativeFastImageModuleSpec {
|
|
|
474
489
|
@Override
|
|
475
490
|
public void writeToCache(final ReadableMap source, final String file, final Promise promise) {
|
|
476
491
|
final ReactApplicationContext context = getReactApplicationContext();
|
|
492
|
+
if (!FastImageViewConverter.isDiskCache(source)) {
|
|
493
|
+
promise.resolve(failure(NOT_ON_DISK));
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
477
496
|
if (FastImageViewConverter.getCacheControl(source) == FastImageCacheControl.WEB) {
|
|
478
497
|
promise.resolve(failure("Can't store cache: 'web' images (they're kept in an HTTP cache)"));
|
|
479
498
|
return;
|
package/dist/index.cjs.js.flow
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -86,6 +86,31 @@ export type Source = {
|
|
|
86
86
|
* @default true
|
|
87
87
|
*/
|
|
88
88
|
memoryCache?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Whether the image is kept on disk. With `false` it isn't kept in the
|
|
91
|
+
* disk cache or an HTTP cache, or read from them. Use it for images the
|
|
92
|
+
* app shouldn't
|
|
93
|
+
* keep once they've been shown (e.g. disappearing messages, or where a
|
|
94
|
+
* security policy doesn't allow caching sensitive images), images that
|
|
95
|
+
* change every time they load, or large images shown once, which would
|
|
96
|
+
* push other images out of the disk cache.
|
|
97
|
+
* The image is downloaded again whenever it isn't in memory, e.g. for a
|
|
98
|
+
* view of another size (or on Android, a change of `blurRadius` or
|
|
99
|
+
* `objectFit`), so with `memoryCache: false` too it's downloaded each
|
|
100
|
+
* time it's shown. With `cache: 'web'` it isn't kept in memory either,
|
|
101
|
+
* so it's downloaded every time it loads. With `cache: 'cacheOnly'` it's
|
|
102
|
+
* only looked for in memory. On Android, a large download is held in a
|
|
103
|
+
* temporary file while it loads, as every download is, deleted as soon
|
|
104
|
+
* as it's opened.
|
|
105
|
+
*
|
|
106
|
+
* `FastImage.preload`, `getCachePath` and `writeToCache` resolve not `ok`
|
|
107
|
+
* for it: there's no file, and a view decodes the image for its own
|
|
108
|
+
* size, so it may download a preloaded one again. A source for the same
|
|
109
|
+
* url (or `cacheKey`) without `diskCache: false` still stores the image.
|
|
110
|
+
*
|
|
111
|
+
* @default true
|
|
112
|
+
*/
|
|
113
|
+
diskCache?: boolean;
|
|
89
114
|
/**
|
|
90
115
|
* With several sources (`source` as an array), the image's width at this
|
|
91
116
|
* uri, in pixels (times `scale`, if given).
|
package/dist/index.js.flow
CHANGED
package/dist/index.web.js.flow
CHANGED
|
@@ -255,6 +255,10 @@ static NSDictionary *FFFFailure(NSString *error)
|
|
|
255
255
|
return @{@"ok": @NO, @"error": error};
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
+
// preload's, getCachePath's and writeToCache's error for a source with
|
|
259
|
+
// diskCache false.
|
|
260
|
+
static NSString *const FFFNotOnDisk = @"The source has diskCache: false, so it isn't kept on disk";
|
|
261
|
+
|
|
258
262
|
static NSDictionary *FFFFile(NSString *path)
|
|
259
263
|
{
|
|
260
264
|
return @{@"ok": @YES, @"path": path};
|
|
@@ -290,6 +294,13 @@ static NSDictionary *FFFFile(NSString *path)
|
|
|
290
294
|
finishOne();
|
|
291
295
|
return;
|
|
292
296
|
}
|
|
297
|
+
if (!source.diskCache) {
|
|
298
|
+
// Views decode an image for their own size, so one only
|
|
299
|
+
// preloaded into memory would be downloaded again.
|
|
300
|
+
[results addObject:FFFFailure(FFFNotOnDisk)];
|
|
301
|
+
finishOne();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
293
304
|
[results addObject:[NSNull null]];
|
|
294
305
|
SDWebImageOptions options = FFFPreloadOptions(source);
|
|
295
306
|
SDWebImageMutableContext *context = FFFPreloadContext(source);
|
|
@@ -327,6 +338,10 @@ static NSDictionary *FFFFile(NSString *path)
|
|
|
327
338
|
reject:(__unused RCTPromiseRejectBlock)reject
|
|
328
339
|
{
|
|
329
340
|
FFFastImageSource *source = [RCTConvert FFFastImageSource:sourceJSON];
|
|
341
|
+
if (source && !source.diskCache) {
|
|
342
|
+
resolve(FFFFailure(FFFNotOnDisk));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
330
345
|
if (!source.url) {
|
|
331
346
|
NSString *key = FFFDiskCacheKey(source);
|
|
332
347
|
if (!key) {
|
|
@@ -387,6 +402,10 @@ static NSDictionary *FFFFile(NSString *path)
|
|
|
387
402
|
reject:(__unused RCTPromiseRejectBlock)reject
|
|
388
403
|
{
|
|
389
404
|
FFFastImageSource *source = [RCTConvert FFFastImageSource:sourceJSON];
|
|
405
|
+
if (source && !source.diskCache) {
|
|
406
|
+
resolve(FFFFailure(FFFNotOnDisk));
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
390
409
|
if (source.cacheControl == FFFCacheControlWeb) {
|
|
391
410
|
resolve(FFFFailure(@"Can't store cache: 'web' images (they're kept in an HTTP cache)"));
|
|
392
411
|
return;
|
|
@@ -39,6 +39,10 @@ typedef NS_ENUM(NSInteger, FFFCacheControl) {
|
|
|
39
39
|
// default YES). Without it, it's only kept on disk: views don't leave it in
|
|
40
40
|
// memory, and preload doesn't decode it.
|
|
41
41
|
@property (nonatomic) BOOL memoryCache;
|
|
42
|
+
// Whether the image is kept in the disk cache (`diskCache`, default YES).
|
|
43
|
+
// Without it, it isn't read from or written to the disk cache, nor for `web`
|
|
44
|
+
// images the HTTP cache.
|
|
45
|
+
@property (nonatomic) BOOL diskCache;
|
|
42
46
|
|
|
43
47
|
- (instancetype)initWithURL:(NSURL *)url
|
|
44
48
|
priority:(FFFPriority)priority
|
|
@@ -346,6 +346,7 @@ static BOOL FFFLooksLikeSVG(NSData *data)
|
|
|
346
346
|
_headers = headers;
|
|
347
347
|
_cacheControl = cacheControl;
|
|
348
348
|
_memoryCache = YES;
|
|
349
|
+
_diskCache = YES;
|
|
349
350
|
}
|
|
350
351
|
return self;
|
|
351
352
|
}
|
|
@@ -366,7 +367,10 @@ static BOOL FFFLooksLikeSVG(NSData *data)
|
|
|
366
367
|
{
|
|
367
368
|
switch (_cacheControl) {
|
|
368
369
|
case FFFCacheControlWeb:
|
|
369
|
-
|
|
370
|
+
// Without the disk cache, nor the HTTP cache: without this option
|
|
371
|
+
// SDWebImage's requests neither read it nor store their responses
|
|
372
|
+
// there.
|
|
373
|
+
return _diskCache ? SDWebImageRefreshCached : 0;
|
|
370
374
|
case FFFCacheControlCacheOnly:
|
|
371
375
|
return SDWebImageFromCacheOnly;
|
|
372
376
|
case FFFCacheControlImmutable:
|
|
@@ -1031,10 +1031,7 @@ NSString *FFFErrorMessage(NSError *error)
|
|
|
1031
1031
|
context[SDWebImageContextCacheKeyFilter] = source.cacheKeyFilter;
|
|
1032
1032
|
if (CGSizeEqualToSize(box, CGSizeZero)) {
|
|
1033
1033
|
[FFFDownsampledImage addFullSizeToContext: context];
|
|
1034
|
-
|
|
1035
|
-
// Only on disk, also when it comes from there.
|
|
1036
|
-
context[SDWebImageContextStoreCacheType] = @(SDImageCacheTypeDisk);
|
|
1037
|
-
}
|
|
1034
|
+
[self applyCacheOptions: context source: source fullSize: YES];
|
|
1038
1035
|
[FFFDownsampledImage forgetSmallerFullSizeImageForURL: source.url context: context];
|
|
1039
1036
|
return context;
|
|
1040
1037
|
}
|
|
@@ -1046,12 +1043,35 @@ NSString *FFFErrorMessage(NSError *error)
|
|
|
1046
1043
|
context[SDWebImageContextOriginalStoreCacheType] = @(SDImageCacheTypeNone);
|
|
1047
1044
|
context[SDWebImageContextOriginalQueryCacheType] = @(SDImageCacheTypeNone);
|
|
1048
1045
|
}
|
|
1046
|
+
[self applyCacheOptions: context source: source fullSize: NO];
|
|
1047
|
+
return context;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// The source's memoryCache and diskCache: which caches the image is looked up
|
|
1051
|
+
// in and kept in. fullSize: the image is decoded at its own size, rather than
|
|
1052
|
+
// smaller (addToContext keeps those in memory only, as the disk cache has the
|
|
1053
|
+
// downloaded file).
|
|
1054
|
+
- (void) applyCacheOptions: (SDWebImageMutableContext*)context source: (FFFastImageSource*)source fullSize: (BOOL)fullSize {
|
|
1055
|
+
if (!source.diskCache) {
|
|
1056
|
+
// Neither the downloaded file (the original, for a smaller decode)
|
|
1057
|
+
// nor the decoded image is read from or written to the disk cache. A
|
|
1058
|
+
// `web` one isn't kept in memory either, as on Android: it's
|
|
1059
|
+
// downloaded every time it loads.
|
|
1060
|
+
SDImageCacheType memory = source.memoryCache && source.cacheControl != FFFCacheControlWeb
|
|
1061
|
+
? SDImageCacheTypeMemory
|
|
1062
|
+
: SDImageCacheTypeNone;
|
|
1063
|
+
context[SDWebImageContextStoreCacheType] = @(memory);
|
|
1064
|
+
context[SDWebImageContextQueryCacheType] = @(memory);
|
|
1065
|
+
context[SDWebImageContextOriginalStoreCacheType] = @(SDImageCacheTypeNone);
|
|
1066
|
+
context[SDWebImageContextOriginalQueryCacheType] = @(SDImageCacheTypeNone);
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1049
1069
|
if (!source.memoryCache) {
|
|
1050
|
-
//
|
|
1051
|
-
// downloaded file is still
|
|
1052
|
-
|
|
1070
|
+
// Only on disk, also when it comes from there. A smaller copy is
|
|
1071
|
+
// only kept in memory, so it isn't kept (the downloaded file is still
|
|
1072
|
+
// on disk).
|
|
1073
|
+
context[SDWebImageContextStoreCacheType] = @(fullSize ? SDImageCacheTypeDisk : SDImageCacheTypeNone);
|
|
1053
1074
|
}
|
|
1054
|
-
return context;
|
|
1055
1075
|
}
|
|
1056
1076
|
|
|
1057
1077
|
// events: NO for a quiet reload at a new size (see reloadIfResized), which
|
|
@@ -1154,6 +1174,13 @@ NSString *FFFErrorMessage(NSError *error)
|
|
|
1154
1174
|
if (weakSelf.loadCount != load) {
|
|
1155
1175
|
return;
|
|
1156
1176
|
}
|
|
1177
|
+
// cacheOnly: SDWebImage completes the load of an image that
|
|
1178
|
+
// isn't cached with neither an image nor an error.
|
|
1179
|
+
if (!error && !image) {
|
|
1180
|
+
error = [NSError errorWithDomain: @"FastImage"
|
|
1181
|
+
code: 0
|
|
1182
|
+
userInfo: @{NSLocalizedDescriptionKey: @"Not in the cache"}];
|
|
1183
|
+
}
|
|
1157
1184
|
// The download was running when the app went to the
|
|
1158
1185
|
// background, and failed: iOS suspends it there, and its
|
|
1159
1186
|
// timeout keeps counting, so it times out as the app comes
|
|
@@ -59,6 +59,8 @@ RCT_ENUM_CONVERTER(FFFCacheControl, (@{
|
|
|
59
59
|
imageSource.cacheKey = cacheKey.length > 0 ? cacheKey : nil;
|
|
60
60
|
id memoryCache = json[@"memoryCache"];
|
|
61
61
|
imageSource.memoryCache = memoryCache && memoryCache != (id)kCFNull ? [self BOOL:memoryCache] : YES;
|
|
62
|
+
id diskCache = json[@"diskCache"];
|
|
63
|
+
imageSource.diskCache = diskCache && diskCache != (id)kCFNull ? [self BOOL:diskCache] : YES;
|
|
62
64
|
CGFloat scale = json[@"scale"] && json[@"scale"] != (id)kCFNull ? [self CGFloat:json[@"scale"]] : 1;
|
|
63
65
|
imageSource.pixelCount = [self CGFloat:json[@"width"]] * [self CGFloat:json[@"height"]] * scale * scale;
|
|
64
66
|
|
package/package.json
CHANGED
package/src/index.js.flow
CHANGED
package/src/index.tsx
CHANGED
|
@@ -104,6 +104,31 @@ export type Source = {
|
|
|
104
104
|
* @default true
|
|
105
105
|
*/
|
|
106
106
|
memoryCache?: boolean
|
|
107
|
+
/**
|
|
108
|
+
* Whether the image is kept on disk. With `false` it isn't kept in the
|
|
109
|
+
* disk cache or an HTTP cache, or read from them. Use it for images the
|
|
110
|
+
* app shouldn't
|
|
111
|
+
* keep once they've been shown (e.g. disappearing messages, or where a
|
|
112
|
+
* security policy doesn't allow caching sensitive images), images that
|
|
113
|
+
* change every time they load, or large images shown once, which would
|
|
114
|
+
* push other images out of the disk cache.
|
|
115
|
+
* The image is downloaded again whenever it isn't in memory, e.g. for a
|
|
116
|
+
* view of another size (or on Android, a change of `blurRadius` or
|
|
117
|
+
* `objectFit`), so with `memoryCache: false` too it's downloaded each
|
|
118
|
+
* time it's shown. With `cache: 'web'` it isn't kept in memory either,
|
|
119
|
+
* so it's downloaded every time it loads. With `cache: 'cacheOnly'` it's
|
|
120
|
+
* only looked for in memory. On Android, a large download is held in a
|
|
121
|
+
* temporary file while it loads, as every download is, deleted as soon
|
|
122
|
+
* as it's opened.
|
|
123
|
+
*
|
|
124
|
+
* `FastImage.preload`, `getCachePath` and `writeToCache` resolve not `ok`
|
|
125
|
+
* for it: there's no file, and a view decodes the image for its own
|
|
126
|
+
* size, so it may download a preloaded one again. A source for the same
|
|
127
|
+
* url (or `cacheKey`) without `diskCache: false` still stores the image.
|
|
128
|
+
*
|
|
129
|
+
* @default true
|
|
130
|
+
*/
|
|
131
|
+
diskCache?: boolean
|
|
107
132
|
/**
|
|
108
133
|
* With several sources (`source` as an array), the image's width at this
|
|
109
134
|
* uri, in pixels (times `scale`, if given).
|