Skip to content

Commit

Permalink
feat: BREAKING CHANGE: added Global Config
Browse files Browse the repository at this point in the history
docs: updated README.md
chore: updated dependencies
  • Loading branch information
efstathiosntonas committed May 11, 2021
1 parent c8bb643 commit b7cb4be
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 41 deletions.
52 changes: 39 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# React Native Image Cache with Progressive Loading
# React Native Image Cache on File System with Progressive Loading

[![npm version](https://badge.fury.io/js/%40georstat%2Freact-native-image-cache.svg)](https://badge.fury.io/js/%40georstat%2Freact-native-image-cache)

Expand Down Expand Up @@ -37,8 +37,34 @@ npm:
npm i @georstat/react-native-image-cache
```



## Usage

#### Put this Global config on your app entry eg. `App.tsx` or `index.js` (**Required**):

```tsx
import { CacheManager } from '@georstat/react-native-image-cache';
import {Dirs} from 'react-native-file-access';

CacheManager.config = {
sourceAnimationDuration: 1000,
thumbnailAnimationDuration: 1000,
BASE_DIR: `${Dirs.CacheDir}/images_cache/`,
};
```

#### Directory constants, choose wisely:

- `Dirs.CacheDir`
- `Dirs.DatabaseDir` (Android only)
- `Dirs.DocumentDir`
- `Dirs.LibraryDir` (iOS only)
- `Dirs.MainBundleDir`
- `Dirs.SDCardDir` (Android only)
- Prefer `FileSystem.cpExternal()` when possible.

#### Component:
```tsx
import { CachedImage } from '@georstat/react-native-image-cache';

Expand All @@ -49,42 +75,42 @@ import { CachedImage } from '@georstat/react-native-image-cache';
/>;
```

You can also clear the local cache:
#### Clear local cache:

```tsx
import { CacheManager } from '@georstat/react-native-image-cache';

await CacheManager.clearCache();
```

Or get local cache size:
#### Get local cache size:

```tsx
await CacheManager.getCacheSize();
```

## Props

CachedImage accepts the following props:
#### `CachedImage` accepts the following props:

| Properties | PropType | Description |
| ---------------------------- | ------------ | ---------------------------------------------------------------------------------------- |
| `source` | `String` | (**Required**) Uri of remote image. |
| `sourceAnimationDuration` | `Number` | `source` image animation duration when loading, defaults to `200` ms |
| `sourceAnimationDuration` | `Number` | `source` image animation duration when loading, defaults to `1000`ms (overrides config) |
| `thumbnailSource` | `String` | (**Required**) Uri of the thumbnail image |
| `thumbnailAnimationDuration` | `Number` | Animation duration for thumbnail, defaults to `200` ms |
| `loadingImageComponent` | `React.Node` | Defaults to an image with the loadingSource prop |
| `loadingImageStyle` | `Object` | Style for loading image component. Works if you don't provide a loadingImageComponent |
| `loadingSource` | `object` | Source for loading Image component. Works if you don't provide loadingImageComponent |
| `thumbnailAnimationDuration` | `Number` | Animation duration for thumbnail, defaults to `1000`ms (overrides config) |
| `loadingImageComponent` | `React.Node` | Defaults to an image with the `loadingSource` prop |
| `loadingImageStyle` | `Object` | Style for loading image component. Works if you don't provide a `loadingImageComponent` |
| `loadingSource` | `object` | Source for loading Image component. Works if you don't provide `loadingImageComponent` |
| `onError` | `Func` | Runs when there is an error loading the image from cache |
| `resizeMode` | `String` | React native Image component [resizeMode](https://reactnative.dev/docs/image#resizemode) |
| `style` | `Object` | `source` image style |
| `options` | `Object` | custom options for the fetch image http request .Eg `{headers:{} , body:{}}` |
| `resizeMode` | `String` | React native Image component [resizeMode](https://reactnative.dev/docs/image#resizemode) defaults to `contain` |
| `style` | `Object` | `source` AND `thumbnailSource` image style |
| `options` | `Object` | custom options for the fetch image http request eg. `{headers:{}, body:{}}` |

## Todo:

- ~~Convert library to React Hooks~~
- Make `BASE_DIR` configurable
- ~~Make `BASE_DIR` configurable~~

## Authors:

Expand Down
4 changes: 2 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^2.0.0",
"@types/jest": "^26.0.20",
"@types/react-native": "^0.64.4",
"@types/react-native": "^0.64.5",
"@types/react-test-renderer": "^17.0.1",
"babel-jest": "^26.6.3",
"eslint": "^7.14.0",
"jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.64.0",
"react-test-renderer": "17.0.1",
"react-test-renderer": "17.0.2",
"typescript": "4.2.4"
},
"resolutions": {
Expand Down
7 changes: 7 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import {
View,
} from 'react-native';
import {CachedImage, CacheManager} from '@georstat/react-native-image-cache';
import {Dirs} from 'react-native-file-access';

CacheManager.config = {
sourceAnimationDuration: 1000,
thumbnailAnimationDuration: 1000,
BASE_DIR: `${Dirs.CacheDir}/images_cache/`,
};

const App = () => {
const clearCache = useCallback(async () => {
Expand Down
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,24 @@
"crypto-js": "^4.0.0"
},
"devDependencies": {
"@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0",
"@react-native-community/bob": "^0.16.2",
"@commitlint/cli": "^12.1.1",
"@commitlint/config-conventional": "^12.1.1",
"@react-native-community/bob": "^0.17.1",
"@react-native-community/eslint-config": "^2.0.0",
"@release-it/conventional-changelog": "^2.0.0",
"@types/react": "^16.9.19",
"@release-it/conventional-changelog": "^2.0.1",
"@types/react": "^17.0.5",
"@types/lodash": "^4.14.168",
"@types/react-native": "0.61.10",
"@types/react-native": "0.64.5",
"auto-changelog": "^2.2.1",
"copyfiles": "^2.4.1",
"eslint": "^7.21.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"husky": "^4.3.4",
"prettier": "^2.2.1",
"react": "~16.9.0",
"react-native": "^0.62.2",
"release-it": "^14.2.2",
"husky": "^6.0.0",
"prettier": "^2.3.0",
"react": "~17.0.2",
"react-native": "^0.64.1",
"release-it": "^14.6.2",
"typescript": "^4.2.3"
},
"peerDependencies": {
Expand Down
33 changes: 22 additions & 11 deletions src/CacheManager.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// @ts-ignore
import SHA1 from 'crypto-js/sha1';
import uniqueId from 'lodash/uniqueId';
import { Dirs, FileSystem } from 'react-native-file-access';
import { FileSystem } from 'react-native-file-access';

import { DownloadOptions } from './types';

const BASE_DIR = `${Dirs.CacheDir}/images_cache/`;
import { Config, DownloadOptions } from './types';
import defaultConfiguration from './defaultConfiguration';

export class CacheEntry {
source: string;
Expand All @@ -30,6 +29,7 @@ export class CacheEntry {
if (exists) {
return path;
}

if (!this.downloadPromise) {
this.pathResolved = false;
this.downloadPromise = this.download(path, tmpPath);
Expand Down Expand Up @@ -66,6 +66,17 @@ export class CacheEntry {
}

export default class CacheManager {
static defaultConfig: Config = defaultConfiguration;
static config: Config;

get config() {
return CacheManager.defaultConfig;
}

set config(newConfig) {
CacheManager.defaultConfig = newConfig;
}

static entries: { [uri: string]: CacheEntry } = {};

static get(
Expand All @@ -85,20 +96,20 @@ export default class CacheManager {
}

static async clearCache(): Promise<void> {
const files = await FileSystem.ls(BASE_DIR);
const files = await FileSystem.ls(CacheManager.config.BASE_DIR);
for (const file of files) {
try {
await FileSystem.unlink(`${BASE_DIR}${file}`);
await FileSystem.unlink(`${CacheManager.config.BASE_DIR}${file}`);
} catch (e) {
console.log(`error while clearing images cache, error: ${e}`);
}
}
}

static async getCacheSize(): Promise<number> {
const result = await FileSystem.stat(BASE_DIR);
const result = await FileSystem.stat(CacheManager.config.BASE_DIR);
if (!result) {
throw new Error(`${BASE_DIR} not found`);
throw new Error(`${CacheManager.config.BASE_DIR} not found`);
}
return result.size;
}
Expand All @@ -116,11 +127,11 @@ const getCacheEntry = async (
? '.jpg'
: filename.substring(filename.lastIndexOf('.'));
const sha = SHA1(cacheKey);
const path = `${BASE_DIR}${sha}${ext}`;
const tmpPath = `${BASE_DIR}${sha}-${uniqueId()}${ext}`;
const path = `${CacheManager.config.BASE_DIR}${sha}${ext}`;
const tmpPath = `${CacheManager.config.BASE_DIR}${sha}-${uniqueId()}${ext}`;
// TODO: maybe we don't have to do this every time
try {
await FileSystem.mkdir(BASE_DIR);
await FileSystem.mkdir(CacheManager.config.BASE_DIR);
} catch (e) {
// do nothing
}
Expand Down
10 changes: 6 additions & 4 deletions src/CachedImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import { ImageProps, IProps } from './types';
const AnimatedImage = Animated.createAnimatedComponent(RNImage);

const defaultProps = {
sourceAnimationDuration: 1500,
onError: () => {},
thumbnailAnimationDuration: 1500,
};

const CachedImage = (props: IProps & typeof defaultProps) => {
Expand Down Expand Up @@ -70,7 +68,9 @@ const CachedImage = (props: IProps & typeof defaultProps) => {
}).start(() => {
Animated.timing(animatedThumbnailImage, {
toValue: 1,
duration: props.thumbnailAnimationDuration,
duration:
props.thumbnailAnimationDuration ||
CacheManager.config.thumbnailAnimationDuration,
useNativeDriver: true,
}).start();
});
Expand All @@ -81,7 +81,9 @@ const CachedImage = (props: IProps & typeof defaultProps) => {
const onImageLoad = (): void => {
Animated.timing(animatedImage, {
toValue: 1,
duration: props.sourceAnimationDuration,
duration:
props.thumbnailAnimationDuration ||
CacheManager.config.thumbnailAnimationDuration,
useNativeDriver: true,
}).start();
};
Expand Down
7 changes: 7 additions & 0 deletions src/defaultConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Dirs } from 'react-native-file-access';

export default {
sourceAnimationDuration: 1000,
thumbnailAnimationDuration: 1000,
BASE_DIR: `${Dirs.CacheDir}/images_cache/`,
};
6 changes: 6 additions & 0 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@ export interface IProps {
thumbnailAnimationDuration?: number;
thumbnailSource: string;
}

export interface Config {
sourceAnimationDuration: number;
thumbnailAnimationDuration: number;
BASE_DIR: string;
}

0 comments on commit b7cb4be

Please sign in to comment.