react-native-fast-image 8.30.1 → 8.31.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.
Files changed (25) hide show
  1. package/README.md +460 -210
  2. package/android/build.gradle +13 -1
  3. package/android/src/glide-4.15/java/com/dylanvann/fastimage/FastImageAnimated.java +2 -2
  4. package/android/src/main/java/com/dylanvann/fastimage/FastImageApng.java +2 -2
  5. package/android/src/main/java/com/dylanvann/fastimage/FastImageGif.java +1 -1
  6. package/android/src/main/java/com/dylanvann/fastimage/FastImageGlide.java +76 -0
  7. package/android/src/main/java/com/dylanvann/fastimage/FastImageGlideModule.java +1 -0
  8. package/android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java +25 -51
  9. package/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java +1 -2
  10. package/android/src/main/java/com/dylanvann/fastimage/FastImageSource.java +1 -1
  11. package/android/src/main/java/com/dylanvann/fastimage/FastImageSourceSize.java +1 -1
  12. package/android/src/main/java/com/dylanvann/fastimage/FastImageSvg.java +2 -0
  13. package/android/src/main/java/com/dylanvann/fastimage/FastImageUrl.java +36 -0
  14. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewConverter.java +2 -1
  15. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java +1 -0
  16. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewModule.java +13 -10
  17. package/android/src/main/java/com/dylanvann/fastimage/FastImageWebGlideUrl.java +1 -0
  18. package/app.plugin.js +1 -1
  19. package/dist/index.d.ts +358 -63
  20. package/ios/FastImage/FFFAnimatedAVIFCoder.h +11 -0
  21. package/ios/FastImage/FFFAnimatedAVIFCoder.m +103 -0
  22. package/ios/FastImage/FFFastImageSource.h +4 -0
  23. package/ios/FastImage/FFFastImageSource.m +36 -2
  24. package/ios/FastImage/FFFastImageViewManager.m +1 -2
  25. package/package.json +4 -2
package/README.md CHANGED
@@ -1,70 +1,65 @@
1
- <h1 align="center">
2
- React Native Fast Image
3
- </h1>
4
-
5
- <div align="center">
1
+ # React Native Fast Image
6
2
 
7
3
  Performant React Native image component.
8
4
 
9
5
  [![Version][version-badge]][package]
10
6
  [![Downloads][downloads-badge]][npmtrends]
11
7
  [![Build Status][build-badge]][build]
8
+ [![Docs][docs-badge]][docs]
12
9
 
13
- [![Watch on GitHub][github-watch-badge]][github-watch]
14
- [![Star on GitHub][github-star-badge]][github-star]
15
- [![Tweet][twitter-badge]][twitter]
16
-
17
- </div>
18
-
19
- <p align="center" >
20
- <kbd>
21
- <img
22
- src="https://github.com/DylanVann/react-native-fast-image/blob/main/docs/assets/scroll.gif?raw=true"
23
- title="Scroll Demo"
24
- float="left"
25
- >
26
- </kbd>
27
- <kbd>
28
- <img
29
- src="https://github.com/DylanVann/react-native-fast-image/blob/main/docs/assets/priority.gif?raw=true"
30
- title="Priority Demo"
31
- float="left"
32
- >
33
- </kbd>
34
- <br>
35
- <em>FastImage example app.</em>
36
- </p>
37
-
38
- React Native's `Image` component handles image caching like browsers
39
- for the most part.
40
- If the server is returning proper cache control
41
- headers for images you'll generally get the sort of built in
42
- caching behavior you'd have in a browser.
43
- Even so many people have noticed:
10
+ React Native's `Image` component handles image caching like browsers for the most part. If the server is returning proper cache control headers for images you'll generally get the sort of built in caching behavior you'd have in a browser. Even so, many people have noticed:
44
11
 
45
12
  - Flickering.
46
13
  - Cache misses.
47
14
  - Low performance loading from cache.
48
15
  - Low performance in general.
49
16
 
50
- `FastImage` is an `Image` replacement that solves these issues.
51
- `FastImage` is a wrapper around
52
- [SDWebImage (iOS)](https://github.com/rs/SDWebImage)
53
- and
54
- [Glide (Android)](https://github.com/bumptech/glide).
17
+ `FastImage` is an `Image` replacement that solves these issues. `FastImage` is a wrapper around [SDWebImage (iOS)](https://github.com/SDWebImage/SDWebImage) and [Glide (Android)](https://github.com/bumptech/glide).
55
18
 
56
19
  ## Features
57
20
 
58
- - [x] Aggressively cache images.
59
- - [x] Add authorization headers.
60
- - [x] Prioritize images.
61
- - [x] Preload images.
62
- - [x] GIF support.
63
- - [x] Border radius.
64
-
65
- ## Usage
66
-
67
- Works with React Native 0.60 and later, with the New Architecture (through React Native's interop layer) and the legacy architecture, and with Expo. It's tested on React Native 0.87 with the New Architecture, 0.73 with the legacy architecture, and Expo SDK 57. A native New Architecture component is planned for the next major version.
21
+ - **Performance**, with images [decoded at the size they're shown](#downsample): in [benchmarks](docs/benchmarks.md), FastImage shows images about as fast as other React Native image components and uses among the least memory for large photos.
22
+ - **Aggressive caching**: an image downloads once, then shows from disk or memory until its url changes, without flickering ([freshness](#sourcecache), [cache keys](#sourcecachekey), [size limits](#configurecachelimits)).
23
+ - **Preloading**, with a [result per image](#preloadsources) and the [cached file's path](#getcachepathsource).
24
+ - **Headers**, e.g. for authentication ([`headers`](#sourceheaders)).
25
+ - **Priorities** for which images load first ([`priority`](#sourcepriority)).
26
+ - **Responsive images**: give several sizes, and the one that fits the view loads ([`source`](#source)).
27
+ - **Animated images** (GIF, WebP, APNG and AVIF) that can [loop](#loop) and [pause](#paused).
28
+ - **Fades** in and between images ([`transition`](#transition)).
29
+ - [**SVG**](docs/formats.md#svg-images) and [**photo library**](#photo-library-images-ios) images.
30
+ - [**`FastImageBackground`**](#fastimagebackground) for content over an image.
31
+ - **Expo and web support**, with a [config plugin](#expo-config-plugin) for Expo.
32
+
33
+ ## Image formats
34
+
35
+ | Format | iOS | Android |
36
+ | ------ | :---------------: | :---------------: |
37
+ | JPEG | ![Yes][yes] | ![Yes][yes] |
38
+ | PNG | ![Yes][yes] | ![Yes][yes] |
39
+ | APNG | ![Yes][yes] | ![Yes][yes] |
40
+ | GIF | ![Yes][yes] | ![Yes][yes] |
41
+ | WebP | ![Yes][yes] | ![Yes][yes] |
42
+ | AVIF | ![Yes][yes] | ![Yes][yes] |
43
+ | HEIC | ![Yes][yes] | ![Yes][yes] |
44
+ | SVG | ![Yes][yes][^svg] | ![Yes][yes][^svg] |
45
+ | ICO | ![Yes][yes] | ![Yes][yes] |
46
+ | BMP | ![Yes][yes] | ![Yes][yes] |
47
+ | TIFF | ![Yes][yes] | ![No][no] |
48
+ | ICNS | ![Yes][yes] | ![No][no] |
49
+ | PSD | ![Yes][yes][^psd] | ![No][no] |
50
+
51
+ See [Formats](docs/formats.md) for the versions of iOS and Android each format needs, and what decodes it.
52
+
53
+ [yes]: docs/assets/yes.svg
54
+ [no]: docs/assets/no.svg
55
+
56
+ [^svg]: With an SVG library in the app: see [SVG images](docs/formats.md#svg-images).
57
+
58
+ [^psd]: Its composite image (the layers as Photoshop saved them flattened).
59
+
60
+ ## Installation
61
+
62
+ Works with React Native 0.60 and later, with the New Architecture (through React Native's interop layer) and the legacy architecture, and with Expo. It's tested on React Native 0.87 with the New Architecture, 0.73 with the legacy architecture, and Expo SDK 57. A native New Architecture component is planned for a future major version.
68
63
 
69
64
  ```bash
70
65
  npm install react-native-fast-image
@@ -79,6 +74,12 @@ npx expo install react-native-fast-image
79
74
 
80
75
  It has native code, so it needs a [development build](https://docs.expo.dev/develop/development-builds/introduction/) (e.g. `npx expo run:ios`), not Expo Go.
81
76
 
77
+ To set the cache's size when the app starts, see [Native config](#native-config).
78
+
79
+ 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.
80
+
81
+ ## Usage
82
+
82
83
  ```jsx
83
84
  import FastImage from 'react-native-fast-image'
84
85
 
@@ -88,94 +89,98 @@ const YourImage = () => (
88
89
  source={{
89
90
  uri: 'https://example.com/image.jpg',
90
91
  headers: { Authorization: 'someAuthToken' },
91
- priority: FastImage.priority.normal,
92
+ priority: 'normal',
92
93
  }}
93
- resizeMode={FastImage.resizeMode.contain}
94
+ resizeMode="contain"
94
95
  />
95
96
  )
96
97
  ```
97
98
 
98
- ## If your app already has an AppGlideModule
99
+ ## Components
99
100
 
100
- If your Android app has its own Glide `AppGlideModule`, read [using FastImage with an AppGlideModule](docs/app-glide-module.md) first, or FastImage may not work.
101
+ ### `FastImage`
101
102
 
102
- ## Properties
103
+ It also takes React Native's View props, such as accessibility props, `testID`, `nativeID`, `onLayout` and `pointerEvents`.
103
104
 
104
- ### `source?: object`
105
-
106
- Source for the remote image to load.
107
-
108
- When `source` changes, the image that's showing stays until the new one has loaded. In views that get reused for other content, such as rows in FlashList or recyclerlistview, set `recyclingKey` so a reused row doesn't show the previous row's image.
105
+ <!-- api:props start (generated from src/ by website/scripts/generate.mts) -->
109
106
 
110
- ---
107
+ #### `source`
111
108
 
112
- ### `source.uri?: string`
109
+ **Type:** `number | Source | Source[]`
113
110
 
114
- Remote url to load the image from. e.g. `'https://example.com/image.jpg'`.
111
+ Source for the remote image to load: a `Source`, a `require()`d image, or an array of the same image at different sizes.
115
112
 
116
- #### Photo library images (iOS)
113
+ When `source` changes, the image that's showing stays until the new one has loaded. In views that get reused for other content, such as rows in FlashList or recyclerlistview, set `recyclingKey` so a reused row doesn't show the previous row's image.
117
114
 
118
- A photo library url (`ph://<localIdentifier>`, as camera roll libraries give) loads with SDWebImagePhotosPlugin, which FastImage includes on iOS.
115
+ **Several sizes of an image.** `source` can also be an array of the same image at different sizes, each with its `width` and `height` in pixels (times `scale`, if it has one). The view loads the one whose size is closest to its own, in pixels, so a small view downloads a small image:
119
116
 
120
- The app needs access to the photo library, which it has if it got the url from there. A photo library image is decoded at about the view's size, since photos are large and usually shown small; `onLoad` still reports the photo's own size. `FastImage.preload` of a `ph://` source loads the full-size photo (there's no view to size it for), which doesn't make a view's smaller copy load faster, so preloading photo library images usually isn't worth it. `assets-library://` urls aren't supported. On Android, photo pickers give `content://` urls, which load as they are.
117
+ ```jsx
118
+ <FastImage
119
+ style={{ width: 120, height: 120 }}
120
+ source={[
121
+ { uri: 'https://example.com/photo-200.jpg', width: 200, height: 200 },
122
+ { uri: 'https://example.com/photo-800.jpg', width: 800, height: 800 },
123
+ ]}
124
+ />
125
+ ```
121
126
 
122
- #### SVG images
127
+ - The view picks once it has been laid out. One that has no size (e.g. sized from `onLoad`) loads the largest.
128
+ - When the view's size changes so that another size fits better, it loads that one (with its load events), and keeps showing the current image until then, without a `transition`.
129
+ - Each size is cached separately. A `cacheKey` applies to its own entry: give each size its own key (or none), or the sizes would replace each other in the cache.
130
+ - `FastImage.preload`, `getCachePath` and `writeToCache` take one size: pass the one a view will show. An array fails with `{ ok: false, error }`.
131
+ - An array of one is the same as that source.
123
132
 
124
- SVG images (remote, bundled with `require()`, or local files) load when the app has an SVG library: SDWebImageSVGCoder on iOS and AndroidSVG on Android. Add them to the app:
133
+ ---
125
134
 
126
- ```ruby
127
- # ios/Podfile
128
- pod 'SDWebImageSVGCoder'
129
- ```
135
+ ##### `source.uri`
130
136
 
131
- ```groovy
132
- // android/app/build.gradle
133
- dependencies {
134
- implementation 'com.caverock:androidsvg-aar:1.4'
135
- }
136
- ```
137
+ **Type:** `string`
137
138
 
138
- On Android either of AndroidSVG's packages works (`com.caverock:androidsvg-aar` or `com.caverock:androidsvg`), so an app that already has one needs nothing more. With Expo, add the pod with [expo-build-properties](https://docs.expo.dev/versions/latest/sdk/build-properties/) (`{ "ios": { "extraPods": [{ "name": "SDWebImageSVGCoder" }] } }`).
139
+ Remote url to load the image from. e.g. `'https://example.com/image.jpg'`.
139
140
 
140
- An SVG is drawn at the size it's shown at, so it's sharp at any size, and then works like any other image: `resizeMode`, `tintColor`, `blurRadius`, `transition` and caching. `onLoad` reports the SVG's own size: its `width` and `height`, or its `viewBox`'s (300x150 if it has neither). Animated SVGs (SMIL or CSS animations) show their first state. On iOS, SVG images need iOS 13 or later. Without the SVG library, an SVG image fails with `onError`, saying what to add (on iOS, for a url that ends in `.svg`).
141
+ Also loads local files (`file://`, and on Android `content://`), photo library images on iOS (`ph://`, see [Photo library images](#photo-library-images-ios)) and SVG images (see [SVG images](docs/formats.md#svg-images)).
141
142
 
142
143
  ---
143
144
 
144
- #### Animated PNG (Android)
145
-
146
- APNG (animated PNG) images animate on Android with [APNG4Android](https://github.com/penfeizhou/APNG4Android), which FastImage includes when the app's `minSdkVersion` is 21 or later (React Native 0.64 and later by default). With an older `minSdkVersion` they show their first frame.
145
+ ##### `source.headers`
147
146
 
148
- APNGs work like other animated images: `loop`, `paused` (which continues from the frame it paused on), and a still first frame with `blurRadius` or `resizeMode="repeat"`. Each frame is decoded as it plays, at about the size it's shown at, off the main thread.
149
-
150
- ### `source.headers?: object`
147
+ **Type:** `{ [key: string]: string }`
151
148
 
152
149
  Headers to load the image with. e.g. `{ Authorization: 'someAuthToken' }`.
153
150
 
154
151
  ---
155
152
 
156
- ### `source.priority?: enum`
153
+ ##### `source.priority`
154
+
155
+ **Type:** `Priority` · **Default:** `'normal'`
157
156
 
158
- Indicates the load order priority of an image. Images with `FastImage.priority.high` will load before images in a similar context with low or normal priority.
157
+ A hint for which images to start loading first when several are waiting: `'high'` ones before `'normal'` ones, and `'low'` ones after. It's best effort, not an order: several images load at once, and when each finishes depends on its size and the network.
159
158
 
160
- - `FastImage.priority.low` - Low Priority.
161
- - `FastImage.priority.normal` **(Default)** - Normal Priority.
162
- - `FastImage.priority.high` - High Priority.
159
+ - `'low'`: e.g. images further down a list.
160
+ - `'normal'`: the default.
161
+ - `'high'`: e.g. the image the screen is about.
163
162
 
164
163
  ---
165
164
 
166
- ### `source.cache?: enum`
165
+ ##### `source.cache`
166
+
167
+ **Type:** `Cache` · **Default:** `'immutable'`
167
168
 
168
169
  How fresh the image must be. See [how caching is handled](docs/how-is-caching-handled.md) for how the options fit together.
169
170
 
170
- - `FastImage.cacheControl.immutable` - **(Default)** - Only updates if url changes.
171
- - `FastImage.cacheControl.web` - Use headers and follow normal caching procedures. These responses are kept in their own HTTP cache (50 MB on each platform), which `clearDiskCache` also clears.
172
- - `FastImage.cacheControl.cacheOnly` - Only show images from cache, do not make any network requests.
171
+ - `'immutable'`: loads the image once, then shows the cached copy until its url (or `cacheKey`) changes.
172
+ - `'web'`: follows the server's HTTP cache headers, as a browser does, checking with the server when it loads. These responses are kept in their own HTTP cache (50 MB on each platform), which `clearDiskCache` also clears.
173
+ - `'cacheOnly'`: only shows a cached image, without making a request.
173
174
 
174
175
  ---
175
176
 
176
- ### `source.cacheKey?: string`
177
+ ##### `source.cacheKey`
178
+
179
+ **Type:** `string`
177
180
 
178
- The key the image is cached under, instead of its uri. Use it for urls that change while the image stays the same, e.g. signed urls with a token or an expiry. Use something that identifies the image, and change it when the image changes (e.g. include a version or the time it was updated), or the old image keeps showing:
181
+ The key the image is cached under, instead of its uri. Use it for urls that change while the image stays the same, e.g. signed urls with a token or an expiry. Use something that identifies the image, and change it when the image changes (e.g. include a version or the time it was updated), or the old image keeps showing.
182
+
183
+ Not used with `cache: 'web'`, which follows the HTTP cache (keyed by url).
179
184
 
180
185
  ```jsx
181
186
  <FastImage
@@ -186,52 +191,75 @@ The key the image is cached under, instead of its uri. Use it for urls that chan
186
191
  />
187
192
  ```
188
193
 
189
- Not used with `cache: 'web'`, which follows the HTTP cache (keyed by url).
194
+ ---
195
+
196
+ ##### `source.memoryCache`
197
+
198
+ **Type:** `boolean` · **Default:** `true`
199
+
200
+ Whether the decoded image is kept in the memory cache. With `false` it's only kept on disk: a view doesn't leave it in memory once it stops showing it, and `FastImage.preload` downloads it without decoding it. Use it for large images that are shown once or rarely, like a full-screen photo: a decoded photo can take tens of MB of memory. Images shown again, like a list scrolled back, are decoded from disk again.
190
201
 
191
202
  ---
192
203
 
193
- ### `source.memoryCache?: boolean`
204
+ ##### `source.width`
205
+
206
+ **Type:** `number`
194
207
 
195
- Whether the decoded image is kept in the memory cache. **Default: true.** With `false` it's only kept on disk: a view doesn't leave it in memory once it stops showing it, and `FastImage.preload` downloads it without decoding it. Use it for large images that are shown once or rarely, like a full-screen photo: a decoded photo can take tens of MB of memory. Images shown again, like a list scrolled back, are decoded from disk again.
208
+ With several sources (`source` as an array), the image's width at this uri, in pixels (times `scale`, if given).
196
209
 
197
210
  ---
198
211
 
199
- ### Several sizes of an image
212
+ ##### `source.height`
200
213
 
201
- `source` can also be an array of the same image at different sizes, each with its `width` and `height` in pixels (times `scale`, if it has one). The view loads the one whose size is closest to its own, in pixels, so a small view downloads a small image:
214
+ **Type:** `number`
202
215
 
203
- ```jsx
204
- <FastImage
205
- style={{ width: 120, height: 120 }}
206
- source={[
207
- { uri: 'https://example.com/photo-200.jpg', width: 200, height: 200 },
208
- { uri: 'https://example.com/photo-800.jpg', width: 800, height: 800 },
209
- {
210
- uri: 'https://example.com/photo-2000.jpg',
211
- width: 2000,
212
- height: 2000,
213
- },
214
- ]}
215
- />
216
- ```
216
+ With several sources (`source` as an array), the image's height at this uri, in pixels (times `scale`, if given).
217
217
 
218
- - The view picks once it has been laid out. One that has no size (e.g. sized from `onLoad`) loads the largest.
219
- - When the view's size changes so that another size fits better, it loads that one (with its load events), and keeps showing the current image until then, without a `transition`.
220
- - Each size is cached separately. A `cacheKey` applies to its own entry: give each size its own key (or none), or the sizes would replace each other in the cache.
221
- - `FastImage.preload`, `getCachePath` and `writeToCache` take one size: pass the one a view will show. An array fails with `{ ok: false, error }`.
222
- - An array of one is the same as that source.
218
+ ---
219
+
220
+ ##### `source.scale`
221
+
222
+ **Type:** `number`
223
+
224
+ With several sources, the scale `width` and `height` are multiplied by.
225
+
226
+ ---
227
+
228
+ #### `defaultSource`
229
+
230
+ **Type:** `number`
231
+
232
+ An asset loaded with `require(...)`, shown while the first image loads, and if an image fails to load. When `source` changes, the previous image shows while the new one loads instead (see `source` and `recyclingKey`).
233
+
234
+ On Android, `defaultSource` doesn't show in debug builds: there the dev server serves `require()`d images, and `defaultSource` is only loaded from the app's resources.
223
235
 
224
236
  ---
225
237
 
226
- ### `defaultSource?: number`
238
+ #### `resizeMode`
239
+
240
+ **Type:** `ResizeMode` · **Default:** `'cover'`
241
+
242
+ How the image fills the view.
227
243
 
228
- - An asset loaded with `require(...)`.
229
- - Shown while the first image loads, and if an image fails to load. When `source` changes, the previous image shows while the new one loads instead (see `source` and `recyclingKey`).
230
- - On Android, `defaultSource` doesn't show in debug builds: there the dev server serves `require()`d images, and `defaultSource` is only loaded from the app's resources.
244
+ - `'contain'`: scales it uniformly (keeping its aspect ratio) so all of it fits in the view (minus padding).
245
+ - `'cover'`: scales it uniformly (keeping its aspect ratio) so it covers the view (minus padding), cropping what doesn't fit.
246
+ - `'stretch'`: scales its width and height separately to fill the view, which can change its aspect ratio.
247
+ - `'center'`: centers it at its own size, scaled down uniformly to fit if it's larger than the view.
248
+ - `'repeat'`: repeats it to cover the view, from its top-left corner, at the image's own size in pixels (a bundled image at its size in points), scaled down to fit if it's larger than the view. An animated image repeats its first frame, and `defaultSource` repeats too.
231
249
 
232
250
  ---
233
251
 
234
- ### `recyclingKey?: string`
252
+ #### `fallback`
253
+
254
+ **Type:** `boolean`
255
+
256
+ If true, the image is shown with React Native's `Image` instead, styled and laid out the same way. FastImage's own features, such as its caching options, `priority` and `transition`, don't apply.
257
+
258
+ ---
259
+
260
+ #### `recyclingKey`
261
+
262
+ **Type:** `string | null`
235
263
 
236
264
  For views that get reused for other content, such as rows in FlashList or recyclerlistview. Set it to something that identifies the content, e.g. the item's id. When it changes, the image is cleared right away (to `defaultSource`, or blank) instead of staying until the new one has loaded. Unlike changing `key`, this keeps the view, which is what list recycling is for.
237
265
 
@@ -241,55 +269,46 @@ For views that get reused for other content, such as rows in FlashList or recycl
241
269
 
242
270
  ---
243
271
 
244
- ### `resizeMode?: enum`
272
+ #### `loop`
245
273
 
246
- - `FastImage.resizeMode.contain` - Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
247
- - `FastImage.resizeMode.cover` **(Default)** - Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
248
- - `FastImage.resizeMode.stretch` - Scale width and height independently, This may change the aspect ratio of the src.
249
- - `FastImage.resizeMode.center` - Center the image at its own size, scaled down uniformly to fit if it's larger than the view.
250
- - `FastImage.resizeMode.repeat` - Repeat the image to cover the view, from its top-left corner, at the image's own size in pixels (a bundled image at its size in points), scaled down to fit if it's larger than the view. An animated image repeats its first frame, and `defaultSource` repeats too.
274
+ **Type:** `number | boolean`
251
275
 
252
- ---
276
+ How many times an animated image (GIF, animated WebP, APNG, or animated AVIF) plays:
253
277
 
254
- ### `loop?: boolean | number`
255
-
256
- How many times an animated image (GIF, animated WebP, APNG, and animated AVIF on Android) plays:
257
-
258
- - Not set **(Default)** - As many times as the file says (like a browser).
259
- - `true` - Loop forever.
260
- - `false` - Play once.
261
- - A number - Play that many times.
278
+ - Not set: as many times as the file says (like a browser).
279
+ - `true`: forever.
280
+ - `false`: once.
281
+ - A number: that many times.
262
282
 
263
283
  Changing it restarts the animation.
264
284
 
265
285
  ---
266
286
 
267
- ### `imageRendering?: 'auto' | 'smooth' | 'pixelated'`
287
+ #### `imageRendering`
288
+
289
+ **Type:** `'auto' | 'smooth' | 'pixelated'` · **Default:** `'auto'`
268
290
 
269
291
  How the image is filtered when it's drawn smaller or larger than its size (like CSS's `image-rendering`):
270
292
 
271
- - `'auto'` **(Default)** - The platform's usual filtering.
272
- - `'smooth'` - iOS only. Keeps a large image drawn much smaller than its size (e.g. a big photo as a thumbnail, or fine lines and text) from looking jagged or noisy. Such an image is already decoded at about the view's size by default (see `downsample`), so this is for images shown at less than half their size with `downsample={false}`, or a little smaller than their size. **It uses more memory:** the image is also kept at smaller sizes for drawing, about a third more than the decoded image. On Android it's the same as `'auto'` (images are always decoded at about the view's size there).
273
- - `'pixelated'` - Sharp pixels, without smoothing, e.g. for pixel art drawn larger than its size. On Android, animated images are still smoothed.
293
+ - `'auto'`: the platform's usual filtering.
294
+ - `'smooth'`: iOS only. Keeps a large image drawn much smaller than its size (e.g. a big photo as a thumbnail, or fine lines and text) from looking jagged or noisy. Such an image is already decoded at about the view's size by default (see `downsample`), so this is for images shown at less than half their size with `downsample={false}`, or a little smaller than their size. **It uses more memory:** the image is also kept at smaller sizes for drawing, about a third more than the decoded image. On Android it's the same as `'auto'` (images are always decoded at about the view's size there).
295
+ - `'pixelated'`: sharp pixels, without smoothing, e.g. for pixel art drawn larger than its size. On Android, animated images are still smoothed.
274
296
 
275
297
  ---
276
298
 
277
- ### `paused?: boolean`
299
+ #### `paused`
278
300
 
279
- Pauses an animated image (GIF, animated WebP, APNG, and animated AVIF on Android) on the frame it's showing; `false` plays it again from there (on Android, an animated WebP or AVIF plays again from its first frame: Android can't resume one). Each image animates on its own, so pausing one doesn't pause others showing the same file.
301
+ **Type:** `boolean`
302
+
303
+ Pauses an animated image (GIF, animated WebP, APNG, or animated AVIF) on the frame it's showing; `false` plays it again from there (on Android, an animated WebP or AVIF plays again from its first frame: Android can't resume one). Each image animates on its own, so pausing one doesn't pause others showing the same file.
280
304
 
281
305
  ---
282
306
 
283
- ### `transition?: boolean | number | Transition`
307
+ #### `transition`
284
308
 
285
- Fades the image in when it loads. Off by default. `true` uses the platform's usual fade, a number is the duration in milliseconds, or pass an object:
309
+ **Type:** `number | boolean | Transition | null` · **Default:** `false`
286
310
 
287
- - `duration`: milliseconds; 0 is no fade. Defaults to the platform's usual length: 300 ms on Android, 250 ms on iOS.
288
- - `betweenImages` (default `false`): also fade between images. By default an image fades in when it appears over nothing (or over `defaultSource`), and a new `source` replaces the image that's showing at once, once it has loaded. With `true`, the new image cross-dissolves from the one showing (for a gallery or an avatar that changes, say).
289
- - `skipOnCacheHit`: which images show at once, without the fade:
290
- - `'memory'` (default): images from the memory cache, so a list scrolled back up shows images it already loaded at once. Images from the disk cache fade in.
291
- - `'all'`: images from the memory or disk cache: images that download fade in, and local files and bundled images usually only the first time they load (the disk cache usually keeps them too).
292
- - `'none'`: every image fades in.
311
+ Fades the image in when it loads. `true` uses the platform's usual fade, a number is the duration in milliseconds, or pass a `Transition`.
293
312
 
294
313
  Downloads, local files (`file://`, `content://`) and bundled images (`require()`) fade in. In lists that reuse views (e.g. FlashList), set `recyclingKey`, so a reused view starts empty and its image fades in, instead of showing the previous item's image until it loads.
295
314
 
@@ -301,12 +320,14 @@ Downloads, local files (`file://`, `content://`) and bundled images (`require()`
301
320
 
302
321
  ---
303
322
 
304
- ### `downsample?: boolean`
323
+ #### `downsample`
324
+
325
+ **Type:** `boolean` · **Default:** `true` · iOS only
305
326
 
306
- iOS only. Decodes a large image at about the size it's shown at, instead of at full size, so it takes much less memory.
327
+ Decodes a large image at about the size it's shown at, instead of at full size, so it takes much less memory.
307
328
 
308
- - `true` **(Default)** - An image at least twice the size its view needs is decoded at about the view's size. If the view grows, the image is decoded again for its new size (from the disk cache).
309
- - `false` - Images are decoded at full size, e.g. for an image that's zoomed in on with a transform (a pinch-to-zoom viewer), which would otherwise show the smaller copy enlarged.
329
+ - `true`: an image at least twice the size its view needs is decoded at about the view's size. If the view grows, the image is decoded again for its new size (from the disk cache).
330
+ - `false`: images are decoded at full size, e.g. for an image that's zoomed in on with a transform (a pinch-to-zoom viewer), which would otherwise show the smaller copy enlarged.
310
331
 
311
332
  It doesn't change `onLoad`'s width and height (the image's own size) or the cached file. Needs SDWebImage 5.19.7 or later: before 5.19 images are decoded at full size, and 5.19.0 to 5.19.6 show photos stored sideways with an EXIF orientation (most phone photos) sideways. Photo library images are always decoded this way, and on Android images are always decoded at about the view's size (but Android 16 and later decode animated WebP at full size, and scale it as they draw it).
312
333
 
@@ -314,9 +335,11 @@ If you control the images, serve them at the size they're shown (resized on your
314
335
 
315
336
  ---
316
337
 
317
- ### `blurRadius?: number`
338
+ #### `blurRadius`
318
339
 
319
- Blurs the image by this radius, in points (the same radius looks about the same on iOS and Android). `0` **(Default)** is no blur.
340
+ **Type:** `number` · **Default:** `0`
341
+
342
+ Blurs the image by this radius, in points (the same radius looks about the same on iOS and Android). `0` is no blur.
320
343
 
321
344
  It's for still images, or a radius that changes now and then (e.g. blurring a photo behind a sheet). Each change blurs the image again on the CPU, so don't animate it.
322
345
 
@@ -330,37 +353,53 @@ To animate a blur, or to blur an animated image, use React Native's `filter` sty
330
353
 
331
354
  ---
332
355
 
333
- ### `onLoadStart?: () => void`
356
+ #### `onLoadStart`
357
+
358
+ **Type:** `() => void`
334
359
 
335
360
  Called when the image starts to load.
336
361
 
337
362
  ---
338
363
 
339
- ### `onProgress?: (event) => void`
364
+ #### `onProgress`
365
+
366
+ **Type:** `(event: OnProgressEvent) => void`
340
367
 
341
368
  Called while the image downloads, with the bytes `loaded` so far, the `total`, and `progress` (`loaded / total`, from 0 to 1; the last event has 1). Not called while the total is unknown (a response without a `Content-Length`).
342
369
 
343
- e.g. `onProgress={e => console.log(e.nativeEvent.progress)}`
370
+ ```jsx
371
+ onProgress={e => console.log(e.nativeEvent.progress)}
372
+ ```
344
373
 
345
374
  ---
346
375
 
347
- ### `onLoad?: (event) => void`
376
+ #### `onLoad`
377
+
378
+ **Type:** `(event: OnLoadEvent) => void`
348
379
 
349
380
  Called on a successful image fetch. Called with the width and height of the image itself, not of the view (on iOS, in points: an `@2x` asset reports half its pixel size).
350
381
 
351
- e.g. `onLoad={e => console.log(e.nativeEvent.width, e.nativeEvent.height)}`
382
+ ```jsx
383
+ onLoad={e => console.log(e.nativeEvent.width, e.nativeEvent.height)}
384
+ ```
352
385
 
353
386
  ---
354
387
 
355
- ### `onError?: (event) => void`
388
+ #### `onError`
389
+
390
+ **Type:** `(event: OnErrorEvent) => void`
356
391
 
357
392
  Called on an image fetching error, with a message describing it (e.g. the HTTP status code).
358
393
 
359
- e.g. `onError={e => console.log(e.nativeEvent.error)}`
394
+ ```jsx
395
+ onError={e => console.log(e.nativeEvent.error)}
396
+ ```
360
397
 
361
398
  ---
362
399
 
363
- ### `onLoadEnd?: (result) => void`
400
+ #### `onLoadEnd`
401
+
402
+ **Type:** `(result: LoadResult) => void`
364
403
 
365
404
  Called when the image finishes loading, whether it was successful or an error, with the result: `{ ok: true, width, height }` (the image's size, as `onLoad` gets it) or `{ ok: false, error }` (as `onError` gets it). TypeScript makes you check `ok` before reading the size or the error.
366
405
 
@@ -376,23 +415,31 @@ Called when the image finishes loading, whether it was successful or an error, w
376
415
 
377
416
  ---
378
417
 
379
- ### `style`
418
+ #### `style`
419
+
420
+ **Type:** `StyleProp<ImageStyle>`
380
421
 
381
- A React Native style. Supports using `borderRadius`.
422
+ The image's style: View's style props (`borderRadius` clips the image), and `tintColor`, as with React Native's `Image` (the `tintColor` prop wins).
382
423
 
383
424
  ---
384
425
 
385
- ### `fallback?: boolean`
426
+ #### `tintColor`
386
427
 
387
- If true, the image is shown with React Native's `Image` instead, styled and laid out the same way. FastImage's own features, such as its caching options, `priority` and `transition`, don't apply.
428
+ **Type:** `ColorValue`
429
+
430
+ If supplied, changes the color of all the non-transparent pixels to the given color.
388
431
 
389
432
  ---
390
433
 
391
- ### `tintColor?: number | string`
434
+ #### `children`
392
435
 
393
- If supplied, changes the color of all the non-transparent pixels to the given color.
436
+ **Type:** `ReactNode`
394
437
 
395
- ## `FastImageBackground`
438
+ Render children within the image. In the next major version, `FastImage` won't render children: use `FastImageBackground`.
439
+
440
+ <!-- api:props end -->
441
+
442
+ ### `FastImageBackground`
396
443
 
397
444
  An image with content on top of it: a view that the image fills, with the children on top.
398
445
 
@@ -412,14 +459,47 @@ const Banner = () => (
412
459
  )
413
460
  ```
414
461
 
415
- - `style`: the view's style (it sizes the view, which the image fills).
416
- - `imageStyle`: the image's style.
417
- - `imageRef`: a ref to the image.
418
- - The other props are `FastImage`'s, for the image.
462
+ Its own props are below; the others are `FastImage`'s and go to the image. Its ref is the view's (`imageRef` is the image's).
463
+
464
+ <!-- api:background-props start (generated from src/ by website/scripts/generate.mts) -->
465
+
466
+ #### `style`
467
+
468
+ **Type:** `StyleProp<ViewStyle>`
469
+
470
+ The container's style; the image fills it.
471
+
472
+ ---
473
+
474
+ #### `imageStyle`
475
+
476
+ **Type:** `StyleProp<ImageStyle>`
419
477
 
420
- ## Static Methods
478
+ The image's style.
421
479
 
422
- ### `FastImage.preload: (source[]) => Promise<result[]>`
480
+ ---
481
+
482
+ #### `imageRef`
483
+
484
+ **Type:** `Ref<any>`
485
+
486
+ A ref to the image (the FastImage inside).
487
+
488
+ ---
489
+
490
+ #### `children`
491
+
492
+ **Type:** `ReactNode`
493
+
494
+ Content shown on top of the image.
495
+
496
+ <!-- api:background-props end -->
497
+
498
+ ## Methods
499
+
500
+ ### `preload(sources)`
501
+
502
+ **Parameters:** `sources: Source[]` · **Returns:** `Promise<PreloadResult[]>`
423
503
 
424
504
  Preload images to display later. e.g.
425
505
 
@@ -457,15 +537,21 @@ A source with `memoryCache: false` is only downloaded to the disk cache, without
457
537
  await FastImage.preload(photos.map((uri) => ({ uri, memoryCache: false })))
458
538
  ```
459
539
 
460
- ### `FastImage.clearMemoryCache: () => Promise<void>`
540
+ ### `clearMemoryCache()`
541
+
542
+ **Returns:** `Promise<void>`
543
+
544
+ Removes every image from the memory cache, e.g. to free memory. They're decoded from the disk cache again when they're next shown.
461
545
 
462
- Clear all images from memory cache.
546
+ ### `clearDiskCache()`
463
547
 
464
- ### `FastImage.clearDiskCache: () => Promise<void>`
548
+ **Returns:** `Promise<void>`
465
549
 
466
- Clear all images from disk cache.
550
+ Removes every image from the disk cache, including the HTTP cache of `cache: 'web'` images, e.g. when a user logs out. They're downloaded again when they're next shown. There's no way to remove a single image: to load one again after it changed, change its [`cacheKey`](#sourcecachekey).
467
551
 
468
- ### `FastImage.getCachePath: (source: Source) => Promise<CachePathResult>`
552
+ ### `getCachePath(source)`
553
+
554
+ **Parameters:** `source: Source` · **Returns:** `Promise<CachePathResult>`
469
555
 
470
556
  The path of the source's downloaded file in the disk cache, e.g. to share, save or upload an image without downloading it again. If the file isn't there, it's downloaded first, without decoding the image or keeping it in memory. Resolves with `{ ok: true, path }`, or `{ ok: false, error }` if it can't be downloaded. Never rejects.
471
557
 
@@ -481,7 +567,7 @@ With `cache: 'cacheOnly'` it doesn't download: use it to check whether an image
481
567
  ```js
482
568
  const { ok } = await FastImage.getCachePath({
483
569
  uri: photo.url,
484
- cache: FastImage.cacheControl.cacheOnly,
570
+ cache: 'cacheOnly',
485
571
  })
486
572
  ```
487
573
 
@@ -491,11 +577,13 @@ const { ok } = await FastImage.getCachePath({
491
577
  - A `file://` source is its own path. Other local images (`require()` in a release build, `content://`) have no file to give.
492
578
  - With `cache: 'web'`, Android only keeps the file if the server allows caching it (in an HTTP cache), and returns `ok: false` otherwise. If the server compressed the image with `Content-Encoding` (rare for images), that file is compressed.
493
579
 
494
- There's no way to remove a single image from the cache. To load an image again after it changed on the server, change its [`cacheKey`](#sourcecachekey-string).
580
+ There's no way to remove a single image from the cache. To load an image again after it changed on the server, change its [`cacheKey`](#sourcecachekey).
581
+
582
+ ### `writeToCache(source, file)`
495
583
 
496
- ### `FastImage.writeToCache: (source: Source, file: string) => Promise<CachePathResult>`
584
+ **Parameters:** `source: Source`, `file: string` · **Returns:** `Promise<CachePathResult>`
497
585
 
498
- Stores a local image file as the source's image in the disk cache, so views and preloads of the source show it without downloading it. For example, after a user uploads a new avatar, store the photo they picked under the avatar's new url or [`cacheKey`](#sourcecachekey-string), and it shows at once. `file` is a `file://` uri or a path (or on Android a `content://` uri, as image pickers often return). A source with a `cacheKey` doesn't need a `uri`, so the image can be stored before its url is known. Resolves with `{ ok: true, path }` (the cached file) or `{ ok: false, error }`. Never rejects.
586
+ Stores a local image file as the source's image in the disk cache, so views and preloads of the source show it without downloading it. For example, after a user uploads a new avatar, store the photo they picked under the avatar's new url or [`cacheKey`](#sourcecachekey), and it shows at once. `file` is a `file://` uri or a path (or on Android a `content://` uri, as image pickers often return). A source with a `cacheKey` doesn't need a `uri`, so the image can be stored before its url is known. Resolves with `{ ok: true, path }` (the cached file) or `{ ok: false, error }`. Never rejects.
499
587
 
500
588
  ```js
501
589
  const result = await FastImage.writeToCache(
@@ -512,7 +600,9 @@ const result = await FastImage.writeToCache(
512
600
  - Not for `cache: 'web'` sources, which are kept in an HTTP cache.
513
601
  - Like any cached image, it can be removed from the cache later, and then it's downloaded from the source's url.
514
602
 
515
- ### `FastImage.configureCache: (limits?: CacheLimits) => Promise<CacheState>`
603
+ ### `configureCache(limits)`
604
+
605
+ **Parameters:** `limits?: CacheLimits` · **Returns:** `Promise<CacheState>`
516
606
 
517
607
  How much the image cache keeps. Set the limits your app starts with in its native config, so they're in effect from the first image, and change them while the app runs with `configureCache`, e.g. from a storage setting. Runtime changes are saved, and used on the next launches too.
518
608
 
@@ -520,17 +610,180 @@ How much the image cache keeps. Set the limits your app starts with in its nativ
520
610
  | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
521
611
  | `maxDiskSize`: the most bytes of images kept on disk. When it's over, the least recently used images are removed. | Changes apply at once (the cache is trimmed to half the limit). Default: no limit. | Changes apply from the next launch (Glide's disk cache size is set when it starts). Default: 250 MB. |
522
612
  | `maxDiskAge`: seconds an image is kept on disk after it was last used. | Default: 1 week (counted from when it was stored before SDWebImage 5.21, unless it's set). | No age limit. |
523
- | `maxMemorySize`: the most bytes of decoded images kept in memory. | Default: no limit (they're removed when the system is low on memory). | Sized from the screen by Glide. |
613
+ | `maxMemorySize`: the most bytes of decoded images kept in memory. | Default: no limit (they're removed when the system is low on memory). | About two screenfuls of images.[^glide-memory] |
524
614
 
525
615
  `0` means no limit.
526
616
 
527
- **Starting limits.** With Expo, in `app.json`:
617
+ **Starting limits.** Set them in the app's [native config](#native-config).
618
+
619
+ **Changing them at runtime.** Pass the limits to change; `null` goes back to the native config's (or the default). It resolves with the limits in effect and `diskSize`, the bytes the image disk cache uses now. Call it without limits to see them.
620
+
621
+ ```js
622
+ await FastImage.configureCache({ maxDiskSize: 500 * 1024 * 1024 })
623
+ const { maxDiskSize, diskSize } = await FastImage.configureCache()
624
+ ```
625
+
626
+ On Android, if your app has its own `AppGlideModule` (see [using FastImage with an AppGlideModule](docs/android-build-settings.md#if-your-app-has-its-own-appglidemodule)), set the disk cache size there instead: `maxDiskSize` isn't applied or reported. Likewise in an app with [expo-image](docs/android-build-settings.md#with-expo-image), whose Glide setup sets the disk cache.
627
+
628
+ Images with `cache: 'web'` are kept in their own HTTP cache instead, up to 50 MB on each platform, which these limits don't change.
629
+
630
+ ## Types
631
+
632
+ <!-- api:types start (generated from src/ by website/scripts/generate.mts) -->
633
+
634
+ ### `Cache`
635
+
636
+ **Type:** `'immutable' | 'web' | 'cacheOnly'`
637
+
638
+ How fresh an image must be: see [`source.cache`](#sourcecache).
639
+
640
+ ---
641
+
642
+ ### `CacheLimits`
643
+
644
+ `configureCache`'s changes: a number (0 for no limit), or `null` to go back to the app's native config (Info.plist, AndroidManifest.xml) or the platform's default. Leave one out to keep it. Changes are saved, and used on the next launches too. Android only has `maxDiskSize`.
645
+
646
+ - `maxDiskSize?` (`number | null`): The most bytes of images kept on disk. When it's over, the least recently used are removed (on iOS, until it's half this size). Default: no limit on iOS, 250 MB on Android.
647
+ - `maxDiskAge?` (`number | null`): iOS: the seconds an image is kept on disk after it was last used, or 0 to keep them until `maxDiskSize` removes them. Default: 1 week.
648
+ - `maxMemorySize?` (`number | null`): iOS: the most bytes of decoded images kept in memory. Default: no limit (they're removed when the system is low on memory).
649
+
650
+ ---
651
+
652
+ ### `CachePathResult`
653
+
654
+ **Type:** `{ ok: true; path: string } | { ok: false; error: string }`
655
+
656
+ `getCachePath`'s and `writeToCache`'s result: `ok` with the file's path, or not `ok` with the error.
657
+
658
+ ---
659
+
660
+ ### `CacheState`
661
+
662
+ `configureCache`'s result: the limits in effect (0 for no limit), and the bytes the disk cache uses now. Android only has `maxDiskSize` and `diskSize`, and neither if the app has its own `AppGlideModule` (or expo-image, which has one).
663
+
664
+ - `maxDiskSize?` (`number`)
665
+ - `maxDiskAge?` (`number`)
666
+ - `maxMemorySize?` (`number`)
667
+ - `diskSize?` (`number`): The bytes the disk cache uses now.
668
+
669
+ ---
670
+
671
+ ### `LoadResult`
672
+
673
+ **Type:** `{ ok: true; width: number; height: number } | { ok: false; error: string }`
674
+
675
+ A load's result, as `onLoadEnd` gets it: `ok` with the image's size, or not `ok` with the error (as `onLoad` and `onError` get them).
676
+
677
+ ---
678
+
679
+ ### `OnErrorEvent`
680
+
681
+ `onError`'s event: `nativeEvent.error` says what went wrong, e.g. an HTTP status code or an image that can't be decoded.
682
+
683
+ - `nativeEvent` (`{ error: string }`)
684
+
685
+ ---
686
+
687
+ ### `OnLoadEvent`
688
+
689
+ `onLoad`'s event: `nativeEvent` has the image's `width` and `height`, in pixels, and `target`, the view's React tag (missing on Android with the legacy architecture).
690
+
691
+ - `nativeEvent` (`{ width: number; height: number; target?: number }`)
692
+
693
+ ---
694
+
695
+ ### `OnProgressEvent`
696
+
697
+ `onProgress`'s event: `nativeEvent` has the bytes `loaded` and the `total`, and `progress`, `loaded / total` from 0 to 1.
698
+
699
+ - `nativeEvent` (`{ loaded: number; total: number; progress: number }`)
700
+
701
+ ---
702
+
703
+ ### `PreloadFailure`
704
+
705
+ A preloaded source that failed to load.
706
+
707
+ - `uri?` (`string`): The source's uri (none for a source without one, e.g. `null`).
708
+ - `ok` (`false`)
709
+ - `error` (`string`): What went wrong.
710
+
711
+ ---
712
+
713
+ ### `PreloadResult`
714
+
715
+ **Type:** `PreloadSuccess | PreloadFailure`
716
+
717
+ `preload`'s result for a source. Check `ok` to tell which it is: e.g. `if (result.ok)` narrows it to a `PreloadSuccess`, with its size. Reading `width` or `error` without checking is a type error.
718
+
719
+ ---
720
+
721
+ ### `PreloadSuccess`
722
+
723
+ A preloaded source that loaded (and is now cached).
724
+
725
+ - `uri` (`string`): The source's uri.
726
+ - `ok` (`true`)
727
+ - `width` (`number`): The image's width (as in `onLoad`).
728
+ - `height` (`number`): The image's height (as in `onLoad`).
729
+
730
+ ---
731
+
732
+ ### `Priority`
733
+
734
+ **Type:** `'low' | 'normal' | 'high'`
735
+
736
+ An image's load priority: see [`source.priority`](#sourcepriority).
737
+
738
+ ---
739
+
740
+ ### `ResizeMode`
741
+
742
+ **Type:** `'contain' | 'cover' | 'stretch' | 'center' | 'repeat'`
743
+
744
+ How the image fits the view: see [`resizeMode`](#resizemode).
745
+
746
+ ---
747
+
748
+ ### `Transition`
749
+
750
+ How the image fades in: see [`transition`](#transition).
751
+
752
+ - `duration?` (`number`): How long the fade takes, in milliseconds; 0 means no fade. Defaults to the platform's usual length: 300 ms on Android, 250 ms on iOS.
753
+ - `betweenImages?` (`boolean`, default `false`): Also fades between images: a new `source` replacing an image that's showing cross-dissolves from it. Otherwise only an image that appears over nothing (or over `defaultSource`) fades in, and a new source replaces the image showing at once, once it has loaded.
754
+ - `skipOnCacheHit?` (`'none' | 'memory' | 'all' | null`, default `'memory'`): Skips the fade for an image from a cache, so images already loaded show at once, e.g. in a list scrolled back up or a reused row.
755
+
756
+ - `'memory'`: skips it for images from the memory cache.
757
+ - `'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).
758
+ - `'none'`: always fades.
759
+
760
+ Downloads, local files and bundled images (`require()`) fade in.
761
+
762
+ <!-- api:types end -->
763
+
764
+ ## Native config
765
+
766
+ The cache's limits the app starts with, read from its native projects so they're in effect from the first image. [`configureCache`](#configurecachelimits) says what each one does and its default, and changes them while the app runs. `0` means no limit.
767
+
768
+ | Limit | Unit | iOS (`Info.plist`) | Android (`AndroidManifest.xml`) |
769
+ | --------------- | ------- | ------------------------ | --------------------------------------------- |
770
+ | `maxDiskSize` | bytes | `FastImageMaxDiskSize` | `fastimage.MAX_DISK_SIZE` |
771
+ | `maxDiskAge` | seconds | `FastImageMaxDiskAge` | No age limit |
772
+ | `maxMemorySize` | bytes | `FastImageMaxMemorySize` | About two screenfuls of images[^glide-memory] |
773
+
774
+ ### Expo config plugin
775
+
776
+ With Expo, FastImage's config plugin sets them, from its options in `app.json` (or `app.config.js`):
528
777
 
529
778
  ```json
530
779
  "plugins": [["react-native-fast-image", { "maxDiskSize": 209715200, "maxDiskAge": 2592000 }]]
531
780
  ```
532
781
 
533
- Without Expo, in `ios/<App>/Info.plist`:
782
+ It writes the native settings below when Expo generates the native projects (`npx expo prebuild`), so run that again after changing them. An app that keeps its own `ios/` and `android/` projects sets them there instead.
783
+
784
+ ### iOS
785
+
786
+ In `ios/<App>/Info.plist`:
534
787
 
535
788
  ```xml
536
789
  <key>FastImageMaxDiskSize</key>
@@ -539,22 +792,23 @@ Without Expo, in `ios/<App>/Info.plist`:
539
792
  <integer>2592000</integer>
540
793
  ```
541
794
 
542
- and in `android/app/src/main/AndroidManifest.xml`, inside `<application>`:
795
+ ### Android
796
+
797
+ In `android/app/src/main/AndroidManifest.xml`, inside `<application>`:
543
798
 
544
799
  ```xml
545
800
  <meta-data android:name="fastimage.MAX_DISK_SIZE" android:value="209715200" />
546
801
  ```
547
802
 
548
- **Changing them at runtime.** Pass the limits to change; `null` goes back to the native config's (or the default). It resolves with the limits in effect and `diskSize`, the bytes the image disk cache uses now. Call it without limits to see them.
803
+ If your app has its own `AppGlideModule` (see [using FastImage with an AppGlideModule](docs/android-build-settings.md#if-your-app-has-its-own-appglidemodule)), set the disk cache size there instead. In an app with [expo-image](docs/android-build-settings.md#with-expo-image), expo-image's Glide setup sets it.
549
804
 
550
- ```js
551
- await FastImage.configureCache({ maxDiskSize: 500 * 1024 * 1024 })
552
- const { maxDiskSize, diskSize } = await FastImage.configureCache()
553
- ```
805
+ [^glide-memory]: Glide's default, which FastImage keeps: room for two screenfuls of decoded images (2 × the screen's width × height × 4 bytes, about 20 MB on a 1080 × 2400 screen), plus a pool of bitmaps to reuse (one screenful on Android 8 and later, four before). Together they're limited to 40% of the memory Android gives the app (33% on low-memory devices), and both shrink to fit.
554
806
 
555
- On Android, if your app has its own `AppGlideModule` (see [using FastImage with an AppGlideModule](docs/app-glide-module.md)), set the disk cache size there instead: `maxDiskSize` isn't applied or reported.
807
+ ## Photo library images (iOS)
556
808
 
557
- Images with `cache: 'web'` are kept in their own HTTP cache instead, up to 50 MB on each platform, which these limits don't change.
809
+ A photo library url (`ph://<localIdentifier>`, as camera roll libraries give) loads with SDWebImagePhotosPlugin, which FastImage includes on iOS.
810
+
811
+ The app needs access to the photo library, which it has if it got the url from there. A photo library image is decoded at about the view's size, since photos are large and usually shown small; `onLoad` still reports the photo's own size. `FastImage.preload` of a `ph://` source loads the full-size photo (there's no view to size it for), which doesn't make a view's smaller copy load faster, so preloading photo library images usually isn't worth it. `assets-library://` urls aren't supported. On Android, photo pickers give `content://` urls, which load as they are.
558
812
 
559
813
  ## Web
560
814
 
@@ -593,13 +847,9 @@ Thanks to [@mobinni](https://github.com/mobinni) for helping with the conceptual
593
847
 
594
848
  [build-badge]: https://github.com/DylanVann/react-native-fast-image/actions/workflows/ci.yml/badge.svg
595
849
  [build]: https://github.com/DylanVann/react-native-fast-image/actions/workflows/ci.yml
850
+ [docs-badge]: https://img.shields.io/badge/docs-website-blue.svg
851
+ [docs]: https://react-native-fast-image.dylanvann.workers.dev
596
852
  [downloads-badge]: https://img.shields.io/npm/dm/react-native-fast-image.svg
597
853
  [npmtrends]: http://www.npmtrends.com/react-native-fast-image
598
854
  [package]: https://www.npmjs.com/package/react-native-fast-image
599
855
  [version-badge]: https://img.shields.io/npm/v/react-native-fast-image.svg
600
- [twitter]: https://twitter.com/home?status=Check%20out%20react-native-fast-image%20by%20%40atomarranger%20https%3A//github.com/DylanVann/react-native-fast-image
601
- [twitter-badge]: https://img.shields.io/twitter/url/https/github.com/DylanVann/react-native-fast-image.svg?style=social
602
- [github-watch-badge]: https://img.shields.io/github/watchers/dylanvann/react-native-fast-image.svg?style=social
603
- [github-watch]: https://github.com/dylanvann/react-native-fast-image/watchers
604
- [github-star-badge]: https://img.shields.io/github/stars/dylanvann/react-native-fast-image.svg?style=social
605
- [github-star]: https://github.com/dylanvann/react-native-fast-image/stargazers