1 | import React from 'react';
|
2 | import ReactNative from 'react-native';
|
3 |
|
4 | import Asset from './Asset';
|
5 |
|
6 | const {
|
7 | Component,
|
8 | PropTypes,
|
9 | } = React;
|
10 |
|
11 | const {
|
12 | StyleSheet,
|
13 | requireNativeComponent,
|
14 | NativeModules,
|
15 | View,
|
16 | } = ReactNative;
|
17 |
|
18 | const styles = StyleSheet.create({
|
19 | base: {
|
20 | overflow: 'hidden',
|
21 | },
|
22 | });
|
23 |
|
24 | export default class Video extends Component {
|
25 | static RESIZE_MODE_CONTAIN = 'contain';
|
26 | static RESIZE_MODE_COVER = 'cover';
|
27 | static RESIZE_MODE_STRETCH = 'stretch';
|
28 |
|
29 | setNativeProps(nativeProps) {
|
30 | this._root.setNativeProps(nativeProps);
|
31 | }
|
32 |
|
33 | seek = (time) => {
|
34 | this.setNativeProps({ seek: time });
|
35 | };
|
36 |
|
37 | presentFullscreenPlayer = () => {
|
38 | this.setNativeProps({ fullscreen: true });
|
39 | };
|
40 |
|
41 | dismissFullscreenPlayer = () => {
|
42 | this.setNativeProps({ fullscreen: false });
|
43 | };
|
44 |
|
45 | _assignRoot = (component) => {
|
46 | this._root = component;
|
47 | };
|
48 |
|
49 | _onLoadStart = (event) => {
|
50 | if (this.props.onLoadStart) {
|
51 | this.props.onLoadStart(event.nativeEvent);
|
52 | }
|
53 | };
|
54 |
|
55 | _onLoad = (event) => {
|
56 | if (this.props.onLoad) {
|
57 | this.props.onLoad(event.nativeEvent);
|
58 | }
|
59 | };
|
60 |
|
61 | _onError = (event) => {
|
62 | if (this.props.onError) {
|
63 | this.props.onError(event.nativeEvent);
|
64 | }
|
65 | };
|
66 |
|
67 | _onProgress = (event) => {
|
68 | if (this.props.onProgress) {
|
69 | this.props.onProgress(event.nativeEvent);
|
70 | }
|
71 | };
|
72 |
|
73 | _onSeek = (event) => {
|
74 | if (this.props.onSeek) {
|
75 | this.props.onSeek(event.nativeEvent);
|
76 | }
|
77 | };
|
78 |
|
79 | _onEnd = (event) => {
|
80 | if (this.props.onEnd) {
|
81 | this.props.onEnd(event.nativeEvent);
|
82 | }
|
83 | };
|
84 |
|
85 | _onFullscreenPlayerWillPresent = (event) => {
|
86 | if (this.props.onFullscreenPlayerWillPresent) {
|
87 | this.props.onFullscreenPlayerWillPresent(event.nativeEvent);
|
88 | }
|
89 | };
|
90 |
|
91 | _onFullscreenPlayerDidPresent = (event) => {
|
92 | if (this.props.onFullscreenPlayerDidPresent) {
|
93 | this.props.onFullscreenPlayerDidPresent(event.nativeEvent);
|
94 | }
|
95 | };
|
96 |
|
97 | _onFullscreenPlayerWillDismiss = (event) => {
|
98 | if (this.props.onFullscreenPlayerWillDismiss) {
|
99 | this.props.onFullscreenPlayerWillDismiss(event.nativeEvent);
|
100 | }
|
101 | };
|
102 |
|
103 | _onFullscreenPlayerDidDismiss = (event) => {
|
104 | if (this.props.onFullscreenPlayerDidDismiss) {
|
105 | this.props.onFullscreenPlayerDidDismiss(event.nativeEvent);
|
106 | }
|
107 | };
|
108 |
|
109 | _onReadyForDisplay = (event) => {
|
110 | if (this.props.onReadyForDisplay) {
|
111 | this.props.onReadyForDisplay(event.nativeEvent);
|
112 | }
|
113 | };
|
114 |
|
115 | _onPlaybackStalled = (event) => {
|
116 | if (this.props.onPlaybackStalled) {
|
117 | this.props.onPlaybackStalled(event.nativeEvent);
|
118 | }
|
119 | };
|
120 |
|
121 | _onPlaybackResume = (event) => {
|
122 | if (this.props.onPlaybackResume) {
|
123 | this.props.onPlaybackResume(event.nativeEvent);
|
124 | }
|
125 | };
|
126 |
|
127 | _onPlaybackRateChange = (event) => {
|
128 | if (this.props.onPlaybackRateChange) {
|
129 | this.props.onPlaybackRateChange(event.nativeEvent);
|
130 | }
|
131 | };
|
132 |
|
133 | render() {
|
134 | let {
|
135 | source,
|
136 | resizeMode,
|
137 | } = this.props;
|
138 |
|
139 |
|
140 | if (typeof source === 'number') {
|
141 | let asset = Asset.fromModule(source);
|
142 | source = { uri: asset.localUri || asset.uri };
|
143 | }
|
144 |
|
145 | let uri = source.uri;
|
146 | if (uri && uri.match(/^\//)) {
|
147 | uri = `file://${uri}`;
|
148 | }
|
149 |
|
150 | const isNetwork = !!(uri && uri.match(/^https?:/));
|
151 | const isAsset = !!(uri && uri.match(/^(assets-library|file|content):/));
|
152 |
|
153 | let nativeResizeMode;
|
154 | if (resizeMode === Video.RESIZE_MODE_STRETCH) {
|
155 | nativeResizeMode = NativeModules.UIManager.ExponentVideo.Constants.ScaleToFill;
|
156 | } else if (resizeMode === Video.RESIZE_MODE_CONTAIN) {
|
157 | nativeResizeMode = NativeModules.UIManager.ExponentVideo.Constants.ScaleAspectFit;
|
158 | } else if (resizeMode === Video.RESIZE_MODE_COVER) {
|
159 | nativeResizeMode = NativeModules.UIManager.ExponentVideo.Constants.ScaleAspectFill;
|
160 | } else {
|
161 | nativeResizeMode = NativeModules.UIManager.ExponentVideo.Constants.ScaleNone;
|
162 | }
|
163 |
|
164 | const nativeProps = Object.assign({}, this.props);
|
165 | Object.assign(nativeProps, {
|
166 | style: [styles.base, nativeProps.style],
|
167 | resizeMode: nativeResizeMode,
|
168 | src: {
|
169 | uri,
|
170 | isNetwork,
|
171 | isAsset,
|
172 | type: source.type || 'mp4',
|
173 | },
|
174 | onVideoLoadStart: this._onLoadStart,
|
175 | onVideoLoad: this._onLoad,
|
176 | onVideoError: this._onError,
|
177 | onVideoProgress: this._onProgress,
|
178 | onVideoSeek: this._onSeek,
|
179 | onVideoEnd: this._onEnd,
|
180 | onVideoFullscreenPlayerWillPresent: this._onFullscreenPlayerWillPresent,
|
181 | onVideoFullscreenPlayerDidPresent: this._onFullscreenPlayerDidPresent,
|
182 | onVideoFullscreenPlayerWillDismiss: this._onFullscreenPlayerWillDismiss,
|
183 | onVideoFullscreenPlayerDidDismiss: this._onFullscreenPlayerDidDismiss,
|
184 | onReadyForDisplay: this._onReadyForDisplay,
|
185 | onPlaybackStalled: this._onPlaybackStalled,
|
186 | onPlaybackResume: this._onPlaybackResume,
|
187 | onPlaybackRateChange: this._onPlaybackRateChange,
|
188 | });
|
189 |
|
190 | return (
|
191 | <ExponentVideo
|
192 | ref={this._assignRoot}
|
193 | {...nativeProps}
|
194 | />
|
195 | );
|
196 | }
|
197 | }
|
198 |
|
199 | Video.propTypes = {
|
200 |
|
201 | src: PropTypes.object,
|
202 | seek: PropTypes.number,
|
203 | fullscreen: PropTypes.bool,
|
204 |
|
205 |
|
206 | source: PropTypes.oneOfType([
|
207 | PropTypes.object,
|
208 | PropTypes.number,
|
209 | ]),
|
210 | resizeMode: PropTypes.string,
|
211 | repeat: PropTypes.bool,
|
212 | paused: PropTypes.bool,
|
213 | muted: PropTypes.bool,
|
214 | volume: PropTypes.number,
|
215 | rate: PropTypes.number,
|
216 | controls: PropTypes.bool,
|
217 | currentTime: PropTypes.number,
|
218 | onLoadStart: PropTypes.func,
|
219 | onLoad: PropTypes.func,
|
220 | onError: PropTypes.func,
|
221 | onProgress: PropTypes.func,
|
222 | onSeek: PropTypes.func,
|
223 | onEnd: PropTypes.func,
|
224 | onFullscreenPlayerWillPresent: PropTypes.func,
|
225 | onFullscreenPlayerDidPresent: PropTypes.func,
|
226 | onFullscreenPlayerWillDismiss: PropTypes.func,
|
227 | onFullscreenPlayerDidDismiss: PropTypes.func,
|
228 | onReadyForDisplay: PropTypes.func,
|
229 | onPlaybackStalled: PropTypes.func,
|
230 | onPlaybackResume: PropTypes.func,
|
231 | onPlaybackRateChange: PropTypes.func,
|
232 |
|
233 |
|
234 | scaleX: React.PropTypes.number,
|
235 | scaleY: React.PropTypes.number,
|
236 | translateX: React.PropTypes.number,
|
237 | translateY: React.PropTypes.number,
|
238 | rotation: React.PropTypes.number,
|
239 | ...View.propTypes,
|
240 | };
|
241 |
|
242 | const ExponentVideo = requireNativeComponent('ExponentVideo', Video, {
|
243 | nativeOnly: {
|
244 | src: true,
|
245 | seek: true,
|
246 | fullscreen: true,
|
247 | onVideoLoadStart: true,
|
248 | onVideoLoad: true,
|
249 | onVideoError: true,
|
250 | onVideoProgress: true,
|
251 | onVideoSeek: true,
|
252 | onVideoEnd: true,
|
253 | onVideoFullscreenPlayerWillPresent: true,
|
254 | onVideoFullscreenPlayerDidPresent: true,
|
255 | onVideoFullscreenPlayerWillDismiss: true,
|
256 | onVideoFullscreenPlayerDidDismiss: true,
|
257 | },
|
258 | });
|