Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 39 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ A performant way to render images in React Native with a focus on speed and memo

- [ ] GIF support


## Installation

```sh
Expand All @@ -48,7 +47,11 @@ yarn add @candlefinance/faster-image
## Usage

```js
import { FasterImageView, clearCache, prefetch } from '@candlefinance/faster-image';
import {
FasterImageView,
clearCache,
prefetch,
} from '@candlefinance/faster-image';

<FasterImageView
style={styles.image}
Expand All @@ -69,47 +72,52 @@ import { FasterImageView, clearCache, prefetch } from '@candlefinance/faster-ima
await clearCache();

// Prefetch
await prefetch(['https://picsum.photos/200/200?random=0'])
await prefetch(['https://picsum.photos/200/200?random=0']);

// Prefetch with headers
const token = 'your-token';
await prefetch(['https://picsum.photos/200/200?random=0'], {
headers: {
Authorization: `Bearer ${token}`,
},
cachePolicy: 'discWithCacheControl',
ignoreQueryParamsForCacheKey: true,
});

// Prefetch accepts `headers`, `cachePolicy`, and
// `ignoreQueryParamsForCacheKey` options
```

## Props

| Prop | Type | Default | Description |
| ------------------------- | ---------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------- |
| url | string | | The URL of the image |
| style | object | | The style of the image |
| resizeMode | string | contain | The resize mode of the image |
| thumbhash | string | | The thumbhash of the image as a base64 encoded string to show while loading (Android not tested) |
| blurhash | string | | The blurhash of the image to show while loading (iOS only) |
| showActivityIndicator | boolean | false (iOS only) | Whether to show the UIActivityIndicatorView indicator when the image is loading
| activityColor | ColorValue | undefined (iOS only) | Activity indicator color. Changed default activity indicator color. Only hex supported |
| base64Placeholder | string | | The base64 encoded placeholder image to show while the image is loading |
| cachePolicy | string | memory | The cache policy of the image |
| transitionDuration | number | 0.75 (iOS) Android (100) | The transition duration of the image |
| borderRadius | number | 0 | border radius of image |
| borderTopLeftRadius | number | 0 | top left border radius of image |
| borderTopRightRadius | number | 0 | top right border radius of image |
| borderBottomLeftRadius | number | 0 | bottom left border radius of image |
| borderBottomRightRadius | number | 0 | bottom right border radius of image |
| failureImage | string | | If the image fails to download this will be set (blurhash, thumbhash, base64) |
| progressiveLoadingEnabled | boolean | false | Progressively load images (iOS only) |
| onError | function | | The function to call when an error occurs. The error is passed as the first argument of the function |
| onSuccess | function | | The function to call when the image is successfully loaded |
| grayscale | number | 0 | Filter or transformation that converts the image into shades of gray (0-1). |
| colorMatrix | number[][] | | Color matrix that is applied to image |
| ignoreQueryParamsForCacheKey | boolean | false | Ignore URL query parameters in cache keys |
| allowHardware | boolean | true | Allow hardware rendering (Android only) |
| headers | Record<string, string> | undefined | Pass in headers |
| accessibilityLabel | string | undefined | accessibility label |
| accessible | boolean | undefined | is accessible |
| Prop | Type | Default | Description |
| ---------------------------- | ---------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------- |
| url | string | | The URL of the image |
| style | object | | The style of the image |
| resizeMode | string | contain | The resize mode of the image |
| thumbhash | string | | The thumbhash of the image as a base64 encoded string to show while loading (Android not tested) |
| blurhash | string | | The blurhash of the image to show while loading (iOS only) |
| showActivityIndicator | boolean | false (iOS only) | Whether to show the UIActivityIndicatorView indicator when the image is loading |
| activityColor | ColorValue | undefined (iOS only) | Activity indicator color. Changed default activity indicator color. Only hex supported |
| base64Placeholder | string | | The base64 encoded placeholder image to show while the image is loading |
| cachePolicy | string | memory | The cache policy of the image |
| transitionDuration | number | 0.75 (iOS) Android (100) | The transition duration of the image |
| borderRadius | number | 0 | border radius of image |
| borderTopLeftRadius | number | 0 | top left border radius of image |
| borderTopRightRadius | number | 0 | top right border radius of image |
| borderBottomLeftRadius | number | 0 | bottom left border radius of image |
| borderBottomRightRadius | number | 0 | bottom right border radius of image |
| failureImage | string | | If the image fails to download this will be set (blurhash, thumbhash, base64) |
| progressiveLoadingEnabled | boolean | false | Progressively load images (iOS only) |
| onError | function | | The function to call when an error occurs. The error is passed as the first argument of the function |
| onSuccess | function | | The function to call when the image is successfully loaded |
| grayscale | number | 0 | Filter or transformation that converts the image into shades of gray (0-1). |
| colorMatrix | number[][] | | Color matrix that is applied to image |
| ignoreQueryParamsForCacheKey | boolean | false | Ignore URL query parameters in cache keys |
| allowHardware | boolean | true | Allow hardware rendering (Android only) |
| headers | Record<string, string> | undefined | Pass in headers |
| accessibilityLabel | string | undefined | accessibility label |
| accessible | boolean | undefined | is accessible |

## Contributing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class FasterImageModule(reactContext: ReactApplicationContext) :
try {
val imageLoader = reactApplicationContext.imageLoader
val headers = options?.getMap("headers")
val cachePolicy = options?.getString("cachePolicy") ?: "memory"
val ignoreQuery = options?.getBoolean("ignoreQueryParamsForCacheKey") ?: false

val requests = sources.toArrayList().mapNotNull { url ->
if (url !is String) {
Expand All @@ -83,6 +85,31 @@ class FasterImageModule(reactContext: ReactApplicationContext) :
}
}

if (ignoreQuery) {
val uri = Uri.parse(url)
val keyUri = uri.buildUpon().clearQuery().build()
val cacheKey = keyUri.toString()
val memoryCacheKey = MemoryCache.Key(cacheKey)
requestBuilder = requestBuilder.memoryCacheKey(memoryCacheKey)
if (!cachePolicy.equals("memory")) {
requestBuilder = requestBuilder.diskCacheKey(cacheKey)
}
}

requestBuilder = requestBuilder
.memoryCachePolicy(
when (cachePolicy) {
"memory", "memoryAndDisc" -> CachePolicy.ENABLED
else -> CachePolicy.DISABLED
}
)
.diskCachePolicy(
when (cachePolicy) {
"discWithCacheControl", "discNoCacheControl", "memoryAndDisc" -> CachePolicy.ENABLED
else -> CachePolicy.DISABLED
}
)

requestBuilder.build()
}

Expand Down
26 changes: 21 additions & 5 deletions ios/FasterImageViewManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,39 @@ final class FasterImageViewManager: RCTViewManager {
}

@objc(prefetch:withOptions:withResolver:withRejecter:)
func prefetch(sources: [String],
func prefetch(sources: [String],
options: NSDictionary? = nil,
resolve: @escaping RCTPromiseResolveBlock,
reject: @escaping RCTPromiseRejectBlock) {

let prefetcher = ImagePrefetcher()

let urls = sources.compactMap(URL.init(string:))
let cachePolicy = options?["cachePolicy"] as? String ?? "memory"
let ignoreQuery = options?["ignoreQueryParamsForCacheKey"] as? Bool ?? false
let headers = options?["headers"] as? [String: String]

let imageRequests = urls.map { url in
let prefetcher = ImagePrefetcher(
pipeline: CachePolicy(rawValue: cachePolicy)?.pipeline ?? .shared,
destination: cachePolicy == "memory" ? .memoryCache : .diskCache
)

let imageRequests = sources.compactMap { urlString -> ImageRequest? in
guard let url = URL(string: urlString) else { return nil }
var request = URLRequest(url: url)
if let headers = headers {
for (key, value) in headers {
request.addValue(value, forHTTPHeaderField: key)
}
}

if ignoreQuery {
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
components?.query = nil
let cacheKey = components?.url?.absoluteString ?? url.absoluteString
return ImageRequest(
urlRequest: request,
userInfo: [.imageIdKey: cacheKey]
)
}

return ImageRequest(urlRequest: request)
}

Expand Down
7 changes: 6 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,14 @@ export const clearCache = async () => {
}
};

export type PrefetchOptions = Pick<
ImageOptions,
'headers' | 'cachePolicy' | 'ignoreQueryParamsForCacheKey'
>;

export const prefetch = (
sources: string[],
options?: Pick<ImageOptions, 'headers'>
options?: PrefetchOptions
): Promise<void> => {
if (Platform.OS === 'ios') {
const { FasterImageViewManager } = NativeModules;
Expand Down