Skip to content
This repository was archived by the owner on Apr 15, 2025. It is now read-only.

Commit cb35ac6

Browse files
committed
Allow local file paths to be loaded
1 parent 103f8db commit cb35ac6

File tree

1 file changed

+42
-21
lines changed

1 file changed

+42
-21
lines changed

src/index.tsx

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import uuid from 'react-native-uuid'
2323
import { Image, ImageStyle, Platform, StyleProp } from 'react-native'
2424
import { BehaviorSubject, Subscription } from 'rxjs'
2525
import { skip, takeUntil } from 'rxjs/operators'
26+
import URL from 'url-parse'
2627

2728
export type CacheStrategy = 'immutable' | 'mutable'
2829

@@ -235,17 +236,25 @@ const imageCacheHoc = <P extends object>(
235236
// Set url from source prop
236237
const url = traverse(this.props).get(['source', 'uri'])
237238
const cacheStrategy = traverse(this.props).get(['source', 'cache']) || 'immutable'
238-
239-
// Add a cache lock to file with this name (prevents concurrent <CacheableImage> components from pruning a file with this name from cache).
240-
const fileName = this.fileSystem.getFileNameFromUrl(url)
241-
FileSystem.lockCacheFile(fileName, this.componentId)
242-
243-
// Init the image cache logic
244-
if (!this.invalidUrl) {
245-
this.subscription = this.fileSystem
246-
.observable(url, this.componentId, cacheStrategy)
247-
.pipe(takeUntil(this.unmounted$.pipe(skip(1))))
248-
.subscribe((info) => this.onSourceLoaded(info))
239+
const isFile = new URL(url).protocol === 'file:'
240+
241+
if (isFile || !this.invalidUrl) {
242+
if (isFile) {
243+
this.onSourceLoaded({
244+
path: url,
245+
fileName: this.fileSystem.getFileNameFromUrl(url),
246+
})
247+
} else {
248+
// Add a cache lock to file with this name (prevents concurrent <CacheableImage> components from pruning a file with this name from cache).
249+
const fileName = this.fileSystem.getFileNameFromUrl(url)
250+
FileSystem.lockCacheFile(fileName, this.componentId)
251+
252+
// Init the image cache logic
253+
this.subscription = this.fileSystem
254+
.observable(url, this.componentId, cacheStrategy)
255+
.pipe(takeUntil(this.unmounted$.pipe(skip(1))))
256+
.subscribe((info) => this.onSourceLoaded(info))
257+
}
249258
}
250259
}
251260

@@ -260,27 +269,39 @@ const imageCacheHoc = <P extends object>(
260269
// Set urls from source prop data
261270
const url = traverse(prevProps).get(['source', 'uri'])
262271
const nextUrl = traverse(this.props).get(['source', 'uri'])
272+
const isFile = new URL(nextUrl).protocol === 'file:'
263273

264274
// Do nothing if url has not changed.
265275
if (url === nextUrl) return
266276

267277
// Remove component cache lock on old image file, and add cache lock to new image file.
268278
const fileName = this.fileSystem.getFileNameFromUrl(url)
269-
const nextFileName = this.fileSystem.getFileNameFromUrl(nextUrl)
279+
const cacheStrategy = traverse(this.props).get(['source', 'cache']) || 'immutable'
270280

271281
FileSystem.unlockCacheFile(fileName, this.componentId)
272-
FileSystem.lockCacheFile(nextFileName, this.componentId)
282+
this.subscription?.unsubscribe()
273283

274284
this.invalidUrl = !this._validateImageComponent()
275-
const cacheStrategy = traverse(this.props).get(['source', 'cache']) || 'immutable'
276285

277286
// Init the image cache logic
278-
this.subscription?.unsubscribe()
279-
if (!this.invalidUrl) {
280-
this.subscription = this.fileSystem
281-
.observable(nextUrl, this.componentId, cacheStrategy)
282-
.pipe(takeUntil(this.unmounted$.pipe(skip(1))))
283-
.subscribe((info) => this.onSourceLoaded(info))
287+
if (isFile || !this.invalidUrl) {
288+
if (isFile) {
289+
this.onSourceLoaded({
290+
path: url,
291+
fileName: this.fileSystem.getFileNameFromUrl(url),
292+
})
293+
} else {
294+
// Add a cache lock to file with this name (prevents concurrent <CacheableImage> components from pruning a file with this name from cache).
295+
const nextFileName = this.fileSystem.getFileNameFromUrl(nextUrl)
296+
FileSystem.lockCacheFile(nextFileName, this.componentId)
297+
298+
this.subscription = this.fileSystem
299+
.observable(nextUrl, this.componentId, cacheStrategy)
300+
.pipe(takeUntil(this.unmounted$.pipe(skip(1))))
301+
.subscribe((info) => this.onSourceLoaded(info))
302+
}
303+
} else {
304+
this.setState({ localFilePath: null })
284305
}
285306
}
286307

@@ -310,7 +331,7 @@ const imageCacheHoc = <P extends object>(
310331

311332
render() {
312333
// If media loaded, render full image component, else render placeholder.
313-
if (this.state.localFilePath && !this.invalidUrl) {
334+
if (this.state.localFilePath) {
314335
// Android caches images in memory, if we are rendering the image should have changed locally so appending a timestamp to the path forces it to be loaded from disk
315336
// The internals of te Android behaviour have not been investigated but perhaps it would be beneficial to use the last modified date instead
316337
const props = Object.assign({}, this.props, {

0 commit comments

Comments
 (0)