react-native-expo-image-cache icon indicating copy to clipboard operation
react-native-expo-image-cache copied to clipboard

Image caching improvements

Open davidminor opened this issue 5 years ago • 9 comments

Some improvements that I suggested in #126 & #127 -

The first commit adds an optional cache key property to Image to use instead of the uri as the cache key.

The second commit avoids repeat downloads if multiple Image components reference the same uri.

davidminor avatar Aug 26 '19 21:08 davidminor

+1 to this. This feature is sooooo good!

jeffreybello avatar Sep 17 '19 06:09 jeffreybello

@wcandillon any chance of getting this merged soon?

davidminor avatar Oct 09 '19 17:10 davidminor

Hey man you are AMAZING!

mo-hummus avatar Dec 02 '19 06:12 mo-hummus

@davidminor Thks for that, can you look into the merge conflicts?

wcandillon avatar Dec 02 '19 06:12 wcandillon

Before merging this it needs some work though, there is an edge case where if you delete a cached image then change the component's key the promise is never deleted it wont redownload/load the image, i resolved this by adding a check if the path has been resolved before

export class CacheEntry {
  uri;

  options;

  downloadPromise;

  pathResolved = false;

  constructor(uri, options) {
    this.uri = uri;
    this.options = options;
  }

  async getPath() {
    const { uri, options } = this;
    const { path, exists, tmpPath } = await getCacheEntry(uri);

    if (exists) {
      return path;
    }

    if (!this.downloadPromise) {
      this.pathResolved = false;
      this.downloadPromise = this.download(path, tmpPath);
    }

    if(this.downloadPromise && this.pathResolved) {
      this.pathResolved = false;
      this.downloadPromise = this.download(path, tmpPath);
    }

    return this.downloadPromise;
  }


  async download(path, tmpPath){
    const { uri, options } = this;
    const result = await FileSystem.createDownloadResumable(uri, tmpPath, options).downloadAsync();

    // If the image download failed, we don't cache anything
    if (result && result.status !== 200) {
      this.downloadPromise = undefined;
      return undefined;
    }
    await FileSystem.moveAsync({ from: tmpPath, to: path }).then(()=> {
      this.pathResolved = true
    });
    return path;
  }
}

mo-hummus avatar Dec 02 '19 08:12 mo-hummus

Just curious if this feature or something similar made its way into the library. I see there's been no activity for 6 months.

Aryk avatar May 10 '20 18:05 Aryk

We've been using a custom build and it fell off my radar. Probably won't have time to pick it back up for awhile.

davidminor avatar May 10 '20 18:05 davidminor

Got it, I implemented caching of the signed s3 urls on the server side. I have it set to cache for 5 days whereas the urls are good for 7 days. The mobile app itself reloads data from the server everytime it loads a page so I don't think there is a chance for the url to get stale. Anyways, thanks for your response.

Aryk avatar May 11 '20 09:05 Aryk

Hi guys, we are using a patched version of the library to use the feature. Is there any chance that this could make its way in the mainline code anytime soon? @davidminor Thanks for all the work guys!

obax avatar Dec 06 '20 00:12 obax