Skip to content

Commit 6aac317

Browse files
authored
Merge pull request #38 from sladkoff/master
Allow changing the cache root directory
2 parents c984ff6 + 50fbb5b commit 6aac317

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

CachedImage.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ const CachedImage = React.createClass({
4747
React.PropTypes.bool,
4848
React.PropTypes.array
4949
]).isRequired,
50-
resolveHeaders: React.PropTypes.func
50+
resolveHeaders: React.PropTypes.func,
51+
cacheLocation: React.PropTypes.string
5152
},
5253

5354
getDefaultProps() {
5455
return {
5556
renderImage: props => (<Image ref={CACHED_IMAGE_REF} {...props}/>),
5657
activityIndicatorProps: {},
5758
useQueryParamsInCacheKey: false,
58-
resolveHeaders: () => Promise.resolve({})
59+
resolveHeaders: () => Promise.resolve({}),
60+
cacheLocation: ImageCacheProvider.LOCATION.CACHE
5961
};
6062
},
6163

@@ -117,7 +119,8 @@ const CachedImage = React.createClass({
117119
processSource(source) {
118120
const url = _.get(source, ['uri'], null);
119121
if (ImageCacheProvider.isCacheable(url)) {
120-
const options = _.pick(this.props, ['useQueryParamsInCacheKey', 'cacheGroup']);
122+
const options = _.pick(this.props, ['useQueryParamsInCacheKey', 'cacheGroup', 'cacheLocation']);
123+
121124
// try to get the image path from cache
122125
ImageCacheProvider.getCachedImagePath(url, options)
123126
// try to put the image in cache if

ImageCacheProvider.js

+31-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ const {
88
fs
99
} = RNFetchBlob;
1010

11-
const baseCacheDir = fs.dirs.CacheDir + '/imagesCacheDir';
11+
const LOCATION = {
12+
CACHE: fs.dirs.CacheDir + '/imagesCacheDir',
13+
BUNDLE: fs.dirs.MainBundleDir + '/imagesCacheDir'
14+
};
1215

1316
const SHA1 = require("crypto-js/sha1");
1417
const URL = require('url-parse');
@@ -18,7 +21,8 @@ const defaultImageTypes = ['png', 'jpeg', 'jpg', 'gif', 'bmp', 'tiff', 'tif'];
1821
const defaultResolveHeaders = _.constant(defaultHeaders);
1922

2023
const defaultOptions = {
21-
useQueryParamsInCacheKey: false
24+
useQueryParamsInCacheKey: false,
25+
cacheLocation: LOCATION.CACHE
2226
};
2327

2428
const activeDownloads = {};
@@ -58,6 +62,10 @@ function generateCacheKey(url, options) {
5862
return SHA1(cacheable) + '.' + type;
5963
}
6064

65+
function getBaseDir(cacheLocation) {
66+
return cacheLocation || LOCATION.CACHE;
67+
}
68+
6169
function getCachePath(url, options) {
6270
if (options.cacheGroup) {
6371
return options.cacheGroup;
@@ -72,7 +80,7 @@ function getCachedImageFilePath(url, options) {
7280
const cachePath = getCachePath(url, options);
7381
const cacheKey = generateCacheKey(url, options);
7482

75-
return `${baseCacheDir}/${cachePath}/${cacheKey}`;
83+
return `${getBaseDir(options.cacheLocation)}/${cachePath}/${cacheKey}`;
7684
}
7785

7886
function deleteFile(filePath) {
@@ -90,9 +98,16 @@ function getDirPath(filePath) {
9098

9199
function ensurePath(dirPath) {
92100
return fs.isDir(dirPath)
93-
.then(exists =>
94-
!exists && fs.mkdir(dirPath)
95-
)
101+
.then(isDir => {
102+
if (!isDir) {
103+
return fs.mkdir(dirPath)
104+
.then(() => fs.exists(dirPath).then(exists => {
105+
// Check if dir has indeed been created because
106+
// there's no exception on incorrect user-defined paths (?)...
107+
if (!exists) throw new Error('Invalid cacheLocation');
108+
}))
109+
}
110+
})
96111
.catch(err => {
97112
// swallow folder already exists errors
98113
if (err.message.includes('folder already exists')) {
@@ -304,23 +319,25 @@ function seedCache(local, url, options = defaultOptions) {
304319

305320
/**
306321
* Clear the entire cache.
322+
* @param cacheLocation
307323
* @returns {Promise}
308324
*/
309-
function clearCache() {
310-
return fs.unlink(baseCacheDir)
325+
function clearCache(cacheLocation) {
326+
return fs.unlink(getBaseDir(cacheLocation))
311327
.catch(() => {
312328
// swallow exceptions if path doesn't exist
313329
})
314-
.then(() => ensurePath(baseCacheDir));
330+
.then(() => ensurePath(getBaseDir(cacheLocation)));
315331
}
316332

317333
/**
318334
* Return info about the cache, list of files and the total size of the cache.
335+
* @param cacheLocation
319336
* @returns {Promise.<{size}>}
320337
*/
321-
function getCacheInfo() {
322-
return ensurePath(baseCacheDir)
323-
.then(() => collectFilesInfo(baseCacheDir))
338+
function getCacheInfo(cacheLocation) {
339+
return ensurePath(getBaseDir(cacheLocation))
340+
.then(() => collectFilesInfo(getBaseDir(cacheLocation)))
324341
.then(cache => {
325342
const files = _.flattenDeep(cache);
326343
const size = _.sumBy(files, 'size');
@@ -341,5 +358,6 @@ module.exports = {
341358
deleteMultipleCachedImages,
342359
clearCache,
343360
seedCache,
344-
getCacheInfo
361+
getCacheInfo,
362+
LOCATION
345363
};

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ When providing `source={{uri: 'https://example.com/path/to/remote/image.jpg'}}`
5050
* `useQueryParamsInCacheKey` - _array|bool_ an array of keys to use from the `source.uri` query string or a bool value stating whether to use the entire query string or not. **(default: false)**
5151
* `defaultSource` - prop to display a background image while the source image is downloaded. This will work even in android, but will not display background image if there you set borderRadius on this component style prop
5252
* `resolveHeaders` - _function_ when provided, the returned object will be used as the headers object when sending the request to download the image. **(default: () => Promise.resolve({}))**
53+
* `cacheLocation` - _string_ allows changing the root directory to use for caching. The default directory is sufficient for most use-cases. Images in this directory may be purged by Android automatically to free up space. Use `ImageCacheProvider.LOCATION.BUNDLE` if the cached images are critical (you will have to manage cleanup manually). **(default: ImageCacheProvider.LOCATION.CACHE)**
5354
* `loadingIndicator` - _component_ prop to set custom `ActivityIndicator`.
5455
* `fallbackSource` - prop to set placeholder image. when `source.uri` is null or cached failed, the `fallbackSource` will be display.
5556

57+
5658
### ImageCacheProvider
5759
`ImageCacheProvider` exposes interaction with the cache layer that is used by `CachedImage` so you can use it to prefetch some urls in the background while you app is starting,
5860
or remove some outdated images from the cache to free some space up if needed.
@@ -80,9 +82,10 @@ ImageCacheProvider.deleteMultipleCachedImages([
8082

8183
#### `type: CacheOptions`
8284
```
83-
type ReadDirItem = {
85+
type CacheOptions = {
8486
useQueryParamsInCacheKey: string[]|bool; // same as the CachedImage props
8587
cacheGroup: string; // the directory to save cached images in, defaults to the url hostname
88+
cacheLocation: string; // the root directory to use for caching, corresponds to CachedImage prop of same name, defaults to system cache directory
8689
};
8790
```
8891

0 commit comments

Comments
 (0)