react-native-fast-image 8.30.0 → 8.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,8 +1,4 @@
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
 
@@ -10,61 +6,59 @@ Performant React Native image component.
10
6
  [![Downloads][downloads-badge]][npmtrends]
11
7
  [![Build Status][build-badge]][build]
12
8
 
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:
9
+ 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
10
 
45
11
  - Flickering.
46
12
  - Cache misses.
47
13
  - Low performance loading from cache.
48
14
  - Low performance in general.
49
15
 
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).
16
+ `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
17
 
56
18
  ## Features
57
19
 
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.
20
+ - **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.
21
+ - **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)).
22
+ - **Preloading**, with a [result per image](#preloadsources) and the [cached file's path](#getcachepathsource).
23
+ - **Headers**, e.g. for authentication ([`headers`](#sourceheaders)).
24
+ - **Priorities** for which images load first ([`priority`](#sourcepriority)).
25
+ - **Responsive images**: give several sizes, and the one that fits the view loads ([`source`](#source)).
26
+ - **Animated images** (GIF, WebP, APNG and AVIF) that can [loop](#loop) and [pause](#paused).
27
+ - **Fades** in and between images ([`transition`](#transition)).
28
+ - [**SVG**](docs/formats.md#svg-images) and [**photo library**](#photo-library-images-ios) images.
29
+ - [**`FastImageBackground`**](#fastimagebackground) for content over an image.
30
+ - **Expo and web support**, with a [config plugin](#expo-config-plugin) for Expo.
31
+
32
+ ## Image formats
33
+
34
+ | Format | iOS | Android |
35
+ | ------ | :---------------: | :---------------: |
36
+ | JPEG | ![Yes][yes] | ![Yes][yes] |
37
+ | PNG | ![Yes][yes] | ![Yes][yes] |
38
+ | APNG | ![Yes][yes] | ![Yes][yes] |
39
+ | GIF | ![Yes][yes] | ![Yes][yes] |
40
+ | WebP | ![Yes][yes] | ![Yes][yes] |
41
+ | AVIF | ![Yes][yes] | ![Yes][yes] |
42
+ | HEIC | ![Yes][yes] | ![Yes][yes] |
43
+ | SVG | ![Yes][yes][^svg] | ![Yes][yes][^svg] |
44
+ | ICO | ![Yes][yes] | ![Yes][yes] |
45
+ | BMP | ![Yes][yes] | ![Yes][yes] |
46
+ | TIFF | ![Yes][yes] | ![No][no] |
47
+ | ICNS | ![Yes][yes] | ![No][no] |
48
+ | PSD | ![Yes][yes][^psd] | ![No][no] |
49
+
50
+ See [Formats](docs/formats.md) for the versions of iOS and Android each format needs, and what decodes it.
51
+
52
+ [yes]: docs/assets/yes.svg
53
+ [no]: docs/assets/no.svg
54
+
55
+ [^svg]: With an SVG library in the app: see [SVG images](docs/formats.md#svg-images).
56
+
57
+ [^psd]: Its composite image (the layers as Photoshop saved them flattened).
58
+
59
+ ## Installation
60
+
61
+ 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
62
 
69
63
  ```bash
70
64
  npm install react-native-fast-image
@@ -79,6 +73,12 @@ npx expo install react-native-fast-image
79
73
 
80
74
  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
75
 
76
+ To set the cache's size when the app starts, see [Native config](#native-config).
77
+
78
+ 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.
79
+
80
+ ## Usage
81
+
82
82
  ```jsx
83
83
  import FastImage from 'react-native-fast-image'
84
84
 
@@ -88,94 +88,98 @@ const YourImage = () => (
88
88
  source={{
89
89
  uri: 'https://example.com/image.jpg',
90
90
  headers: { Authorization: 'someAuthToken' },
91
- priority: FastImage.priority.normal,
91
+ priority: 'normal',
92
92
  }}
93
- resizeMode={FastImage.resizeMode.contain}
93
+ resizeMode="contain"
94
94
  />
95
95
  )
96
96
  ```
97
97
 
98
- ## If your app already has an AppGlideModule
98
+ ## Components
99
99
 
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.
100
+ ### `FastImage`
101
101
 
102
- ## Properties
102
+ It also takes React Native's View props, such as accessibility props, `testID`, `nativeID`, `onLayout` and `pointerEvents`.
103
103
 
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.
104
+ <!-- api:props start (generated from src/ by website/scripts/generate.mts) -->
109
105
 
110
- ---
106
+ #### `source`
111
107
 
112
- ### `source.uri?: string`
108
+ **Type:** `number | Source | Source[]`
113
109
 
114
- Remote url to load the image from. e.g. `'https://example.com/image.jpg'`.
110
+ Source for the remote image to load: a `Source`, a `require()`d image, or an array of the same image at different sizes.
115
111
 
116
- #### Photo library images (iOS)
112
+ 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
113
 
118
- A photo library url (`ph://<localIdentifier>`, as camera roll libraries give) loads with SDWebImagePhotosPlugin, which FastImage includes on iOS.
114
+ **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
115
 
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.
116
+ ```jsx
117
+ <FastImage
118
+ style={{ width: 120, height: 120 }}
119
+ source={[
120
+ { uri: 'https://example.com/photo-200.jpg', width: 200, height: 200 },
121
+ { uri: 'https://example.com/photo-800.jpg', width: 800, height: 800 },
122
+ ]}
123
+ />
124
+ ```
121
125
 
122
- #### SVG images
126
+ - The view picks once it has been laid out. One that has no size (e.g. sized from `onLoad`) loads the largest.
127
+ - 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`.
128
+ - 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.
129
+ - `FastImage.preload`, `getCachePath` and `writeToCache` take one size: pass the one a view will show. An array fails with `{ ok: false, error }`.
130
+ - An array of one is the same as that source.
123
131
 
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:
132
+ ---
125
133
 
126
- ```ruby
127
- # ios/Podfile
128
- pod 'SDWebImageSVGCoder'
129
- ```
134
+ ##### `source.uri`
130
135
 
131
- ```groovy
132
- // android/app/build.gradle
133
- dependencies {
134
- implementation 'com.caverock:androidsvg-aar:1.4'
135
- }
136
- ```
136
+ **Type:** `string`
137
137
 
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" }] } }`).
138
+ Remote url to load the image from. e.g. `'https://example.com/image.jpg'`.
139
139
 
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`).
140
+ 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
141
 
142
142
  ---
143
143
 
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.
144
+ ##### `source.headers`
147
145
 
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`
146
+ **Type:** `{ [key: string]: string }`
151
147
 
152
148
  Headers to load the image with. e.g. `{ Authorization: 'someAuthToken' }`.
153
149
 
154
150
  ---
155
151
 
156
- ### `source.priority?: enum`
152
+ ##### `source.priority`
153
+
154
+ **Type:** `Priority` · **Default:** `'normal'`
157
155
 
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.
156
+ 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
157
 
160
- - `FastImage.priority.low` - Low Priority.
161
- - `FastImage.priority.normal` **(Default)** - Normal Priority.
162
- - `FastImage.priority.high` - High Priority.
158
+ - `'low'`: e.g. images further down a list.
159
+ - `'normal'`: the default.
160
+ - `'high'`: e.g. the image the screen is about.
163
161
 
164
162
  ---
165
163
 
166
- ### `source.cache?: enum`
164
+ ##### `source.cache`
165
+
166
+ **Type:** `Cache` · **Default:** `'immutable'`
167
167
 
168
168
  How fresh the image must be. See [how caching is handled](docs/how-is-caching-handled.md) for how the options fit together.
169
169
 
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.
170
+ - `'immutable'`: loads the image once, then shows the cached copy until its url (or `cacheKey`) changes.
171
+ - `'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.
172
+ - `'cacheOnly'`: only shows a cached image, without making a request.
173
173
 
174
174
  ---
175
175
 
176
- ### `source.cacheKey?: string`
176
+ ##### `source.cacheKey`
177
+
178
+ **Type:** `string`
177
179
 
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:
180
+ 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
+
182
+ Not used with `cache: 'web'`, which follows the HTTP cache (keyed by url).
179
183
 
180
184
  ```jsx
181
185
  <FastImage
@@ -186,52 +190,75 @@ The key the image is cached under, instead of its uri. Use it for urls that chan
186
190
  />
187
191
  ```
188
192
 
189
- Not used with `cache: 'web'`, which follows the HTTP cache (keyed by url).
193
+ ---
194
+
195
+ ##### `source.memoryCache`
196
+
197
+ **Type:** `boolean` · **Default:** `true`
198
+
199
+ 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
200
 
191
201
  ---
192
202
 
193
- ### `source.memoryCache?: boolean`
203
+ ##### `source.width`
204
+
205
+ **Type:** `number`
194
206
 
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.
207
+ With several sources (`source` as an array), the image's width at this uri, in pixels (times `scale`, if given).
196
208
 
197
209
  ---
198
210
 
199
- ### Several sizes of an image
211
+ ##### `source.height`
200
212
 
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:
213
+ **Type:** `number`
202
214
 
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
- ```
215
+ With several sources (`source` as an array), the image's height at this uri, in pixels (times `scale`, if given).
217
216
 
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.
217
+ ---
218
+
219
+ ##### `source.scale`
220
+
221
+ **Type:** `number`
222
+
223
+ With several sources, the scale `width` and `height` are multiplied by.
224
+
225
+ ---
226
+
227
+ #### `defaultSource`
228
+
229
+ **Type:** `number`
230
+
231
+ 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`).
232
+
233
+ 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
234
 
224
235
  ---
225
236
 
226
- ### `defaultSource?: number`
237
+ #### `resizeMode`
238
+
239
+ **Type:** `ResizeMode` · **Default:** `'cover'`
240
+
241
+ How the image fills the view.
227
242
 
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.
243
+ - `'contain'`: scales it uniformly (keeping its aspect ratio) so all of it fits in the view (minus padding).
244
+ - `'cover'`: scales it uniformly (keeping its aspect ratio) so it covers the view (minus padding), cropping what doesn't fit.
245
+ - `'stretch'`: scales its width and height separately to fill the view, which can change its aspect ratio.
246
+ - `'center'`: centers it at its own size, scaled down uniformly to fit if it's larger than the view.
247
+ - `'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
248
 
232
249
  ---
233
250
 
234
- ### `recyclingKey?: string`
251
+ #### `fallback`
252
+
253
+ **Type:** `boolean`
254
+
255
+ 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.
256
+
257
+ ---
258
+
259
+ #### `recyclingKey`
260
+
261
+ **Type:** `string | null`
235
262
 
236
263
  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
264
 
@@ -241,55 +268,46 @@ For views that get reused for other content, such as rows in FlashList or recycl
241
268
 
242
269
  ---
243
270
 
244
- ### `resizeMode?: enum`
271
+ #### `loop`
245
272
 
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.
273
+ **Type:** `number | boolean`
251
274
 
252
- ---
275
+ How many times an animated image (GIF, animated WebP, APNG, or animated AVIF) plays:
253
276
 
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.
277
+ - Not set: as many times as the file says (like a browser).
278
+ - `true`: forever.
279
+ - `false`: once.
280
+ - A number: that many times.
262
281
 
263
282
  Changing it restarts the animation.
264
283
 
265
284
  ---
266
285
 
267
- ### `imageRendering?: 'auto' | 'smooth' | 'pixelated'`
286
+ #### `imageRendering`
287
+
288
+ **Type:** `'auto' | 'smooth' | 'pixelated'` · **Default:** `'auto'`
268
289
 
269
290
  How the image is filtered when it's drawn smaller or larger than its size (like CSS's `image-rendering`):
270
291
 
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.
292
+ - `'auto'`: the platform's usual filtering.
293
+ - `'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).
294
+ - `'pixelated'`: sharp pixels, without smoothing, e.g. for pixel art drawn larger than its size. On Android, animated images are still smoothed.
274
295
 
275
296
  ---
276
297
 
277
- ### `paused?: boolean`
298
+ #### `paused`
278
299
 
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.
300
+ **Type:** `boolean`
301
+
302
+ 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
303
 
281
304
  ---
282
305
 
283
- ### `transition?: boolean | number | Transition`
306
+ #### `transition`
284
307
 
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:
308
+ **Type:** `number | boolean | Transition | null` · **Default:** `false`
286
309
 
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.
310
+ 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
311
 
294
312
  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
313
 
@@ -301,12 +319,14 @@ Downloads, local files (`file://`, `content://`) and bundled images (`require()`
301
319
 
302
320
  ---
303
321
 
304
- ### `downsample?: boolean`
322
+ #### `downsample`
323
+
324
+ **Type:** `boolean` · **Default:** `true` · iOS only
305
325
 
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.
326
+ Decodes a large image at about the size it's shown at, instead of at full size, so it takes much less memory.
307
327
 
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.
328
+ - `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).
329
+ - `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
330
 
311
331
  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
332
 
@@ -314,9 +334,11 @@ If you control the images, serve them at the size they're shown (resized on your
314
334
 
315
335
  ---
316
336
 
317
- ### `blurRadius?: number`
337
+ #### `blurRadius`
318
338
 
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.
339
+ **Type:** `number` · **Default:** `0`
340
+
341
+ Blurs the image by this radius, in points (the same radius looks about the same on iOS and Android). `0` is no blur.
320
342
 
321
343
  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
344
 
@@ -330,37 +352,53 @@ To animate a blur, or to blur an animated image, use React Native's `filter` sty
330
352
 
331
353
  ---
332
354
 
333
- ### `onLoadStart?: () => void`
355
+ #### `onLoadStart`
356
+
357
+ **Type:** `() => void`
334
358
 
335
359
  Called when the image starts to load.
336
360
 
337
361
  ---
338
362
 
339
- ### `onProgress?: (event) => void`
363
+ #### `onProgress`
364
+
365
+ **Type:** `(event: OnProgressEvent) => void`
340
366
 
341
367
  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
368
 
343
- e.g. `onProgress={e => console.log(e.nativeEvent.progress)}`
369
+ ```jsx
370
+ onProgress={e => console.log(e.nativeEvent.progress)}
371
+ ```
344
372
 
345
373
  ---
346
374
 
347
- ### `onLoad?: (event) => void`
375
+ #### `onLoad`
376
+
377
+ **Type:** `(event: OnLoadEvent) => void`
348
378
 
349
379
  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
380
 
351
- e.g. `onLoad={e => console.log(e.nativeEvent.width, e.nativeEvent.height)}`
381
+ ```jsx
382
+ onLoad={e => console.log(e.nativeEvent.width, e.nativeEvent.height)}
383
+ ```
352
384
 
353
385
  ---
354
386
 
355
- ### `onError?: (event) => void`
387
+ #### `onError`
388
+
389
+ **Type:** `(event: OnErrorEvent) => void`
356
390
 
357
391
  Called on an image fetching error, with a message describing it (e.g. the HTTP status code).
358
392
 
359
- e.g. `onError={e => console.log(e.nativeEvent.error)}`
393
+ ```jsx
394
+ onError={e => console.log(e.nativeEvent.error)}
395
+ ```
360
396
 
361
397
  ---
362
398
 
363
- ### `onLoadEnd?: (result) => void`
399
+ #### `onLoadEnd`
400
+
401
+ **Type:** `(result: LoadResult) => void`
364
402
 
365
403
  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
404
 
@@ -376,23 +414,31 @@ Called when the image finishes loading, whether it was successful or an error, w
376
414
 
377
415
  ---
378
416
 
379
- ### `style`
417
+ #### `style`
418
+
419
+ **Type:** `StyleProp<ImageStyle>`
380
420
 
381
- A React Native style. Supports using `borderRadius`.
421
+ 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
422
 
383
423
  ---
384
424
 
385
- ### `fallback?: boolean`
425
+ #### `tintColor`
386
426
 
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.
427
+ **Type:** `ColorValue`
428
+
429
+ If supplied, changes the color of all the non-transparent pixels to the given color.
388
430
 
389
431
  ---
390
432
 
391
- ### `tintColor?: number | string`
433
+ #### `children`
392
434
 
393
- If supplied, changes the color of all the non-transparent pixels to the given color.
435
+ **Type:** `ReactNode`
394
436
 
395
- ## `FastImageBackground`
437
+ Render children within the image. In the next major version, `FastImage` won't render children: use `FastImageBackground`.
438
+
439
+ <!-- api:props end -->
440
+
441
+ ### `FastImageBackground`
396
442
 
397
443
  An image with content on top of it: a view that the image fills, with the children on top.
398
444
 
@@ -412,14 +458,47 @@ const Banner = () => (
412
458
  )
413
459
  ```
414
460
 
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.
461
+ 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).
462
+
463
+ <!-- api:background-props start (generated from src/ by website/scripts/generate.mts) -->
464
+
465
+ #### `style`
466
+
467
+ **Type:** `StyleProp<ViewStyle>`
468
+
469
+ The container's style; the image fills it.
470
+
471
+ ---
472
+
473
+ #### `imageStyle`
474
+
475
+ **Type:** `StyleProp<ImageStyle>`
419
476
 
420
- ## Static Methods
477
+ The image's style.
421
478
 
422
- ### `FastImage.preload: (source[]) => Promise<result[]>`
479
+ ---
480
+
481
+ #### `imageRef`
482
+
483
+ **Type:** `Ref<any>`
484
+
485
+ A ref to the image (the FastImage inside).
486
+
487
+ ---
488
+
489
+ #### `children`
490
+
491
+ **Type:** `ReactNode`
492
+
493
+ Content shown on top of the image.
494
+
495
+ <!-- api:background-props end -->
496
+
497
+ ## Methods
498
+
499
+ ### `preload(sources)`
500
+
501
+ **Parameters:** `sources: Source[]` · **Returns:** `Promise<PreloadResult[]>`
423
502
 
424
503
  Preload images to display later. e.g.
425
504
 
@@ -457,15 +536,21 @@ A source with `memoryCache: false` is only downloaded to the disk cache, without
457
536
  await FastImage.preload(photos.map((uri) => ({ uri, memoryCache: false })))
458
537
  ```
459
538
 
460
- ### `FastImage.clearMemoryCache: () => Promise<void>`
539
+ ### `clearMemoryCache()`
540
+
541
+ **Returns:** `Promise<void>`
542
+
543
+ 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
544
 
462
- Clear all images from memory cache.
545
+ ### `clearDiskCache()`
463
546
 
464
- ### `FastImage.clearDiskCache: () => Promise<void>`
547
+ **Returns:** `Promise<void>`
465
548
 
466
- Clear all images from disk cache.
549
+ 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
550
 
468
- ### `FastImage.getCachePath: (source: Source) => Promise<CachePathResult>`
551
+ ### `getCachePath(source)`
552
+
553
+ **Parameters:** `source: Source` · **Returns:** `Promise<CachePathResult>`
469
554
 
470
555
  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
556
 
@@ -481,7 +566,7 @@ With `cache: 'cacheOnly'` it doesn't download: use it to check whether an image
481
566
  ```js
482
567
  const { ok } = await FastImage.getCachePath({
483
568
  uri: photo.url,
484
- cache: FastImage.cacheControl.cacheOnly,
569
+ cache: 'cacheOnly',
485
570
  })
486
571
  ```
487
572
 
@@ -491,11 +576,13 @@ const { ok } = await FastImage.getCachePath({
491
576
  - A `file://` source is its own path. Other local images (`require()` in a release build, `content://`) have no file to give.
492
577
  - 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
578
 
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).
579
+ 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).
580
+
581
+ ### `writeToCache(source, file)`
495
582
 
496
- ### `FastImage.writeToCache: (source: Source, file: string) => Promise<CachePathResult>`
583
+ **Parameters:** `source: Source`, `file: string` · **Returns:** `Promise<CachePathResult>`
497
584
 
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.
585
+ 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
586
 
500
587
  ```js
501
588
  const result = await FastImage.writeToCache(
@@ -512,7 +599,9 @@ const result = await FastImage.writeToCache(
512
599
  - Not for `cache: 'web'` sources, which are kept in an HTTP cache.
513
600
  - Like any cached image, it can be removed from the cache later, and then it's downloaded from the source's url.
514
601
 
515
- ### `FastImage.configureCache: (limits?: CacheLimits) => Promise<CacheState>`
602
+ ### `configureCache(limits)`
603
+
604
+ **Parameters:** `limits?: CacheLimits` · **Returns:** `Promise<CacheState>`
516
605
 
517
606
  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
607
 
@@ -520,17 +609,180 @@ How much the image cache keeps. Set the limits your app starts with in its nativ
520
609
  | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- |
521
610
  | `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
611
  | `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. |
612
+ | `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
613
 
525
614
  `0` means no limit.
526
615
 
527
- **Starting limits.** With Expo, in `app.json`:
616
+ **Starting limits.** Set them in the app's [native config](#native-config).
617
+
618
+ **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.
619
+
620
+ ```js
621
+ await FastImage.configureCache({ maxDiskSize: 500 * 1024 * 1024 })
622
+ const { maxDiskSize, diskSize } = await FastImage.configureCache()
623
+ ```
624
+
625
+ 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.
626
+
627
+ 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.
628
+
629
+ ## Types
630
+
631
+ <!-- api:types start (generated from src/ by website/scripts/generate.mts) -->
632
+
633
+ ### `Cache`
634
+
635
+ **Type:** `'immutable' | 'web' | 'cacheOnly'`
636
+
637
+ How fresh an image must be: see [`source.cache`](#sourcecache).
638
+
639
+ ---
640
+
641
+ ### `CacheLimits`
642
+
643
+ `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`.
644
+
645
+ - `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.
646
+ - `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.
647
+ - `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).
648
+
649
+ ---
650
+
651
+ ### `CachePathResult`
652
+
653
+ **Type:** `{ ok: true; path: string } | { ok: false; error: string }`
654
+
655
+ `getCachePath`'s and `writeToCache`'s result: `ok` with the file's path, or not `ok` with the error.
656
+
657
+ ---
658
+
659
+ ### `CacheState`
660
+
661
+ `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`.
662
+
663
+ - `maxDiskSize?` (`number`)
664
+ - `maxDiskAge?` (`number`)
665
+ - `maxMemorySize?` (`number`)
666
+ - `diskSize?` (`number`): The bytes the disk cache uses now.
667
+
668
+ ---
669
+
670
+ ### `LoadResult`
671
+
672
+ **Type:** `{ ok: true; width: number; height: number } | { ok: false; error: string }`
673
+
674
+ 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).
675
+
676
+ ---
677
+
678
+ ### `OnErrorEvent`
679
+
680
+ `onError`'s event: `nativeEvent.error` says what went wrong, e.g. an HTTP status code or an image that can't be decoded.
681
+
682
+ - `nativeEvent` (`{ error: string }`)
683
+
684
+ ---
685
+
686
+ ### `OnLoadEvent`
687
+
688
+ `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).
689
+
690
+ - `nativeEvent` (`{ width: number; height: number; target?: number }`)
691
+
692
+ ---
693
+
694
+ ### `OnProgressEvent`
695
+
696
+ `onProgress`'s event: `nativeEvent` has the bytes `loaded` and the `total`, and `progress`, `loaded / total` from 0 to 1.
697
+
698
+ - `nativeEvent` (`{ loaded: number; total: number; progress: number }`)
699
+
700
+ ---
701
+
702
+ ### `PreloadFailure`
703
+
704
+ A preloaded source that failed to load.
705
+
706
+ - `uri?` (`string`): The source's uri (none for a source without one, e.g. `null`).
707
+ - `ok` (`false`)
708
+ - `error` (`string`): What went wrong.
709
+
710
+ ---
711
+
712
+ ### `PreloadResult`
713
+
714
+ **Type:** `PreloadSuccess | PreloadFailure`
715
+
716
+ `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.
717
+
718
+ ---
719
+
720
+ ### `PreloadSuccess`
721
+
722
+ A preloaded source that loaded (and is now cached).
723
+
724
+ - `uri` (`string`): The source's uri.
725
+ - `ok` (`true`)
726
+ - `width` (`number`): The image's width (as in `onLoad`).
727
+ - `height` (`number`): The image's height (as in `onLoad`).
728
+
729
+ ---
730
+
731
+ ### `Priority`
732
+
733
+ **Type:** `'low' | 'normal' | 'high'`
734
+
735
+ An image's load priority: see [`source.priority`](#sourcepriority).
736
+
737
+ ---
738
+
739
+ ### `ResizeMode`
740
+
741
+ **Type:** `'contain' | 'cover' | 'stretch' | 'center' | 'repeat'`
742
+
743
+ How the image fits the view: see [`resizeMode`](#resizemode).
744
+
745
+ ---
746
+
747
+ ### `Transition`
748
+
749
+ How the image fades in: see [`transition`](#transition).
750
+
751
+ - `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.
752
+ - `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.
753
+ - `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.
754
+
755
+ - `'memory'`: skips it for images from the memory cache.
756
+ - `'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).
757
+ - `'none'`: always fades.
758
+
759
+ Downloads, local files and bundled images (`require()`) fade in.
760
+
761
+ <!-- api:types end -->
762
+
763
+ ## Native config
764
+
765
+ 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.
766
+
767
+ | Limit | Unit | iOS (`Info.plist`) | Android (`AndroidManifest.xml`) |
768
+ | --------------- | ------- | ------------------------ | --------------------------------------------- |
769
+ | `maxDiskSize` | bytes | `FastImageMaxDiskSize` | `fastimage.MAX_DISK_SIZE` |
770
+ | `maxDiskAge` | seconds | `FastImageMaxDiskAge` | No age limit |
771
+ | `maxMemorySize` | bytes | `FastImageMaxMemorySize` | About two screenfuls of images[^glide-memory] |
772
+
773
+ ### Expo config plugin
774
+
775
+ With Expo, FastImage's config plugin sets them, from its options in `app.json` (or `app.config.js`):
528
776
 
529
777
  ```json
530
778
  "plugins": [["react-native-fast-image", { "maxDiskSize": 209715200, "maxDiskAge": 2592000 }]]
531
779
  ```
532
780
 
533
- Without Expo, in `ios/<App>/Info.plist`:
781
+ 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.
782
+
783
+ ### iOS
784
+
785
+ In `ios/<App>/Info.plist`:
534
786
 
535
787
  ```xml
536
788
  <key>FastImageMaxDiskSize</key>
@@ -539,22 +791,23 @@ Without Expo, in `ios/<App>/Info.plist`:
539
791
  <integer>2592000</integer>
540
792
  ```
541
793
 
542
- and in `android/app/src/main/AndroidManifest.xml`, inside `<application>`:
794
+ ### Android
795
+
796
+ In `android/app/src/main/AndroidManifest.xml`, inside `<application>`:
543
797
 
544
798
  ```xml
545
799
  <meta-data android:name="fastimage.MAX_DISK_SIZE" android:value="209715200" />
546
800
  ```
547
801
 
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.
802
+ 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.
549
803
 
550
- ```js
551
- await FastImage.configureCache({ maxDiskSize: 500 * 1024 * 1024 })
552
- const { maxDiskSize, diskSize } = await FastImage.configureCache()
553
- ```
804
+ [^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
805
 
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.
806
+ ## Photo library images (iOS)
556
807
 
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.
808
+ A photo library url (`ph://<localIdentifier>`, as camera roll libraries give) loads with SDWebImagePhotosPlugin, which FastImage includes on iOS.
809
+
810
+ 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
811
 
559
812
  ## Web
560
813
 
@@ -597,9 +850,3 @@ Thanks to [@mobinni](https://github.com/mobinni) for helping with the conceptual
597
850
  [npmtrends]: http://www.npmtrends.com/react-native-fast-image
598
851
  [package]: https://www.npmjs.com/package/react-native-fast-image
599
852
  [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