@@ -23,6 +23,7 @@ import uuid from 'react-native-uuid'
23
23
import { Image , ImageStyle , Platform , StyleProp } from 'react-native'
24
24
import { BehaviorSubject , Subscription } from 'rxjs'
25
25
import { skip , takeUntil } from 'rxjs/operators'
26
+ import URL from 'url-parse'
26
27
27
28
export type CacheStrategy = 'immutable' | 'mutable'
28
29
@@ -235,17 +236,25 @@ const imageCacheHoc = <P extends object>(
235
236
// Set url from source prop
236
237
const url = traverse ( this . props ) . get ( [ 'source' , 'uri' ] )
237
238
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
+ }
249
258
}
250
259
}
251
260
@@ -260,27 +269,39 @@ const imageCacheHoc = <P extends object>(
260
269
// Set urls from source prop data
261
270
const url = traverse ( prevProps ) . get ( [ 'source' , 'uri' ] )
262
271
const nextUrl = traverse ( this . props ) . get ( [ 'source' , 'uri' ] )
272
+ const isFile = new URL ( nextUrl ) . protocol === 'file:'
263
273
264
274
// Do nothing if url has not changed.
265
275
if ( url === nextUrl ) return
266
276
267
277
// Remove component cache lock on old image file, and add cache lock to new image file.
268
278
const fileName = this . fileSystem . getFileNameFromUrl ( url )
269
- const nextFileName = this . fileSystem . getFileNameFromUrl ( nextUrl )
279
+ const cacheStrategy = traverse ( this . props ) . get ( [ 'source' , 'cache' ] ) || 'immutable'
270
280
271
281
FileSystem . unlockCacheFile ( fileName , this . componentId )
272
- FileSystem . lockCacheFile ( nextFileName , this . componentId )
282
+ this . subscription ?. unsubscribe ( )
273
283
274
284
this . invalidUrl = ! this . _validateImageComponent ( )
275
- const cacheStrategy = traverse ( this . props ) . get ( [ 'source' , 'cache' ] ) || 'immutable'
276
285
277
286
// 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 } )
284
305
}
285
306
}
286
307
@@ -310,7 +331,7 @@ const imageCacheHoc = <P extends object>(
310
331
311
332
render ( ) {
312
333
// If media loaded, render full image component, else render placeholder.
313
- if ( this . state . localFilePath && ! this . invalidUrl ) {
334
+ if ( this . state . localFilePath ) {
314
335
// 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
315
336
// The internals of te Android behaviour have not been investigated but perhaps it would be beneficial to use the last modified date instead
316
337
const props = Object . assign ( { } , this . props , {
0 commit comments