Skip to content

Commit 3e95d30

Browse files
author
Artem Burduk
committed
add video mp4 support
add video mp4 support
1 parent d7320ea commit 3e95d30

File tree

4 files changed

+240
-4
lines changed

4 files changed

+240
-4
lines changed

CachedVideo.js

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
'use strict';
2+
3+
const _ = require('lodash');
4+
const React = require('react');
5+
const ReactNative = require('react-native');
6+
7+
const PropTypes = require('prop-types');
8+
9+
const Video = require('react-native-video');
10+
11+
const ImageCacheManagerOptionsPropTypes = require('./ImageCacheManagerOptionsPropTypes');
12+
13+
const flattenStyle = ReactNative.StyleSheet.flatten;
14+
15+
const ImageCacheManager = require('./ImageCacheManager');
16+
17+
const {
18+
View,
19+
ImageBackground,
20+
ActivityIndicator,
21+
NetInfo,
22+
Platform,
23+
StyleSheet,
24+
} = ReactNative;
25+
26+
const styles = StyleSheet.create({
27+
image: {
28+
backgroundColor: 'transparent'
29+
},
30+
loader: {
31+
backgroundColor: 'transparent',
32+
},
33+
loaderPlaceholder: {
34+
backgroundColor: 'transparent',
35+
alignItems: 'center',
36+
justifyContent: 'center'
37+
}
38+
});
39+
40+
function getImageProps(props) {
41+
return _.omit(props, ['source', 'defaultSource', 'fallbackSource', 'LoadingIndicator', 'activityIndicatorProps', 'style', 'useQueryParamsInCacheKey', 'renderImage', 'resolveHeaders']);
42+
}
43+
44+
const CACHED_IMAGE_REF = 'cachedImage';
45+
46+
class CachedVideo extends React.Component {
47+
48+
static propTypes = {
49+
renderImage: PropTypes.func.isRequired,
50+
activityIndicatorProps: PropTypes.object.isRequired,
51+
52+
// ImageCacheManager options
53+
...ImageCacheManagerOptionsPropTypes,
54+
};
55+
56+
static defaultProps = {
57+
renderImage: props => (<Video imageStyle={props.style} ref={CACHED_IMAGE_REF} {...props} />),
58+
activityIndicatorProps: {},
59+
};
60+
61+
static contextTypes = {
62+
getImageCacheManager: PropTypes.func,
63+
};
64+
65+
constructor(props) {
66+
super(props);
67+
this._isMounted = false;
68+
this.state = {
69+
isCacheable: true,
70+
cachedImagePath: null,
71+
networkAvailable: true
72+
};
73+
74+
this.getImageCacheManagerOptions = this.getImageCacheManagerOptions.bind(this);
75+
this.getImageCacheManager = this.getImageCacheManager.bind(this);
76+
this.safeSetState = this.safeSetState.bind(this);
77+
this.handleConnectivityChange = this.handleConnectivityChange.bind(this);
78+
this.processSource = this.processSource.bind(this);
79+
this.renderLoader = this.renderLoader.bind(this);
80+
}
81+
82+
componentWillMount() {
83+
this._isMounted = true;
84+
NetInfo.isConnected.addEventListener('connectionChange', this.handleConnectivityChange);
85+
// initial
86+
NetInfo.isConnected.fetch()
87+
.then(isConnected => {
88+
this.safeSetState({
89+
networkAvailable: isConnected
90+
});
91+
});
92+
93+
this.processSource(this.props.source);
94+
}
95+
96+
componentWillUnmount() {
97+
this._isMounted = false;
98+
NetInfo.isConnected.removeEventListener('connectionChange', this.handleConnectivityChange);
99+
}
100+
101+
componentWillReceiveProps(nextProps) {
102+
if (!_.isEqual(this.props.source, nextProps.source)) {
103+
this.processSource(nextProps.source);
104+
}
105+
}
106+
107+
setNativeProps(nativeProps) {
108+
try {
109+
this.refs[CACHED_IMAGE_REF].setNativeProps(nativeProps);
110+
} catch (e) {
111+
console.error(e);
112+
}
113+
}
114+
115+
getImageCacheManagerOptions() {
116+
return _.pick(this.props, _.keys(ImageCacheManagerOptionsPropTypes));
117+
}
118+
119+
getImageCacheManager() {
120+
// try to get ImageCacheManager from context
121+
if (this.context && this.context.getImageCacheManager) {
122+
return this.context.getImageCacheManager();
123+
}
124+
// create a new one if context is not available
125+
const options = this.getImageCacheManagerOptions();
126+
return ImageCacheManager(options);
127+
}
128+
129+
safeSetState(newState) {
130+
if (!this._isMounted) {
131+
return;
132+
}
133+
return this.setState(newState);
134+
}
135+
136+
handleConnectivityChange(isConnected) {
137+
this.safeSetState({
138+
networkAvailable: isConnected
139+
});
140+
}
141+
142+
processSource(source) {
143+
const url = _.get(source, ['uri'], null);
144+
const options = this.getImageCacheManagerOptions();
145+
const imageCacheManager = this.getImageCacheManager();
146+
147+
imageCacheManager.downloadAndCacheUrl(url, options)
148+
.then(cachedImagePath => {
149+
this.safeSetState({
150+
cachedImagePath
151+
});
152+
})
153+
.catch(err => {
154+
// console.warn(err);
155+
this.safeSetState({
156+
cachedImagePath: null,
157+
isCacheable: false
158+
});
159+
});
160+
}
161+
162+
render() {
163+
if (this.state.isCacheable && !this.state.cachedImagePath) {
164+
return this.renderLoader();
165+
}
166+
const props = getImageProps(this.props);
167+
const style = this.props.style || styles.image;
168+
const source = (this.state.isCacheable && this.state.cachedImagePath) ? {
169+
uri: 'file://' + this.state.cachedImagePath
170+
} : this.props.source;
171+
if (this.props.fallbackSource && !this.state.cachedImagePath) {
172+
return this.props.renderImage({
173+
...props,
174+
key: `${props.key || source.uri}error`,
175+
style,
176+
source: this.props.fallbackSource
177+
});
178+
}
179+
return this.props.renderImage({
180+
...props,
181+
key: props.key || source.uri,
182+
style,
183+
source
184+
});
185+
}
186+
187+
renderLoader() {
188+
const imageProps = getImageProps(this.props);
189+
const imageStyle = [this.props.style, styles.loaderPlaceholder];
190+
191+
const activityIndicatorProps = _.omit(this.props.activityIndicatorProps, ['style']);
192+
const activityIndicatorStyle = this.props.activityIndicatorProps.style || styles.loader;
193+
194+
const LoadingIndicator = this.props.loadingIndicator;
195+
196+
const source = this.props.defaultSource;
197+
198+
// if the imageStyle has borderRadius it will break the loading image view on android
199+
// so we only show the ActivityIndicator
200+
if (!source || (Platform.OS === 'android' && flattenStyle(imageStyle).borderRadius)) {
201+
if (LoadingIndicator) {
202+
return (
203+
<View style={[imageStyle, activityIndicatorStyle]}>
204+
<LoadingIndicator {...activityIndicatorProps} />
205+
</View>
206+
);
207+
}
208+
return (
209+
<ActivityIndicator
210+
{...activityIndicatorProps}
211+
style={[imageStyle, activityIndicatorStyle]}/>
212+
);
213+
}
214+
// otherwise render an image with the defaultSource with the ActivityIndicator on top of it
215+
return this.props.renderImage({
216+
...imageProps,
217+
style: imageStyle,
218+
key: source.uri,
219+
source,
220+
children: (
221+
LoadingIndicator
222+
? <View style={[imageStyle, activityIndicatorStyle]}>
223+
<LoadingIndicator {...activityIndicatorProps} />
224+
</View>
225+
: <ActivityIndicator
226+
{...activityIndicatorProps}
227+
style={activityIndicatorStyle}/>
228+
)
229+
});
230+
}
231+
232+
}
233+
234+
module.exports = CachedVideo;

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
module.exports.CachedImage = require('./CachedImage');
4+
module.exports.CachedVideo = require('./CachedVideo');
45
module.exports.ImageCacheProvider = require('./ImageCacheProvider');
56
module.exports.ImageCacheManager = require('./ImageCacheManager');
67
module.exports.ImageCachePreloader = require('./ImageCachePreloader');

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,12 @@
4848
"typings": "./index.d.ts",
4949
"dependencies": {
5050
"crypto-js": "3.1.9-1",
51-
"lodash": "4.17.4",
51+
"lodash": "^4.17.11",
5252
"prop-types": "15.5.10",
5353
"react-native-clcasher": "1.0.0",
5454
"react-native-fetch-blob": "0.10.8",
55-
"url-parse": "1.1.9"
55+
"react-native-video": "^4.3.1",
56+
"url-parse": "^1.4.4"
5657
},
5758
"devDependencies": {
5859
"babel-jest": "^21.0.2",
@@ -61,7 +62,7 @@
6162
"jest": "^21.0.2",
6263
"jest-react-native": "^18.0.0",
6364
"react": "16.0.0-alpha.12",
64-
"react-native": "^0.48.3",
65+
"react-native": "^0.58.3",
6566
"react-test-renderer": "^15.6.1",
6667
"regenerator-runtime": "^0.11.0"
6768
}

utils/pathUtils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const _ = require('lodash');
44
const URL = require('url-parse');
55
const SHA1 = require("crypto-js/sha1");
66

7-
const defaultImageTypes = ['png', 'jpeg', 'jpg', 'gif', 'bmp', 'tiff', 'tif'];
7+
const defaultImageTypes = ['png', 'jpeg', 'jpg', 'gif', 'bmp', 'tiff', 'tif', 'mp4'];
88

99
function serializeObjectKeys(obj) {
1010
return _(obj)

0 commit comments

Comments
 (0)