@plusscommunities/pluss-core-app 1.1.4 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plusscommunities/pluss-core-app",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Core extension package for Pluss Communities platform",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
"react-native-elements": "^0.17.0",
|
|
36
36
|
"react-native-image-zoom-viewer": "^3.0.1",
|
|
37
37
|
"react-native-iphone-x-helper": "^1.3.1",
|
|
38
|
+
"react-native-vimeo-iframe": "^1.0.4",
|
|
38
39
|
"react-native-webview": "11.2.3",
|
|
40
|
+
"react-native-youtube-iframe": "^2.2.1",
|
|
39
41
|
"react-redux": "^5.0.5"
|
|
40
42
|
},
|
|
41
43
|
"peerDependencies": {
|
package/src/components/Header.js
CHANGED
|
@@ -276,6 +276,7 @@ class Header extends Component {
|
|
|
276
276
|
<Animated.View
|
|
277
277
|
style={[
|
|
278
278
|
styles.container,
|
|
279
|
+
!this.props.noShadow && styles.containerShadow,
|
|
279
280
|
this.props.transparent && styles.transparentContainer,
|
|
280
281
|
this.props.style,
|
|
281
282
|
{ backgroundColor: this.props.headerColourOffset, elevation: this.props.headerElev, shadowColor: this.props.headerShadow },
|
|
@@ -297,6 +298,7 @@ class Header extends Component {
|
|
|
297
298
|
<View
|
|
298
299
|
style={[
|
|
299
300
|
styles.container,
|
|
301
|
+
!this.props.noShadow && styles.containerShadow,
|
|
300
302
|
this.props.transparent && styles.transparentContainer,
|
|
301
303
|
this.props.lineSeparated && styles.lineSeparated,
|
|
302
304
|
this.props.popupHeader && styles.popupHeader,
|
|
@@ -331,6 +333,9 @@ const styles = {
|
|
|
331
333
|
container: {
|
|
332
334
|
alignSelf: 'stretch',
|
|
333
335
|
backgroundColor: '#fff',
|
|
336
|
+
zIndex: 10,
|
|
337
|
+
},
|
|
338
|
+
containerShadow: {
|
|
334
339
|
shadowColor: '#000',
|
|
335
340
|
shadowOffset: {
|
|
336
341
|
width: 0,
|
|
@@ -339,7 +344,6 @@ const styles = {
|
|
|
339
344
|
shadowOpacity: 0.1,
|
|
340
345
|
shadowRadius: 6,
|
|
341
346
|
elevation: 3,
|
|
342
|
-
zIndex: 10,
|
|
343
347
|
},
|
|
344
348
|
lineSeparated: {
|
|
345
349
|
borderBottomWidth: 1,
|
|
@@ -1,27 +1,17 @@
|
|
|
1
1
|
import React, { Component } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { StyleSheet, Animated, Dimensions } from 'react-native';
|
|
3
|
+
import { connect } from 'react-redux';
|
|
4
|
+
import { getMainBrandingColourFromState } from '../colours';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const OPACITY_END2 = 0.7;
|
|
8
|
-
const OPACITY_END3 = 1;
|
|
9
|
-
const LEFT_START = 1;
|
|
10
|
-
const LEFT_END1 = 16;
|
|
11
|
-
const LEFT_END2 = 32;
|
|
12
|
-
const CIRCLE_SIZE = 8;
|
|
13
|
-
const DEFAULT_HEIGHT = 38;
|
|
6
|
+
const DEFAULT_HEIGHT = 4;
|
|
7
|
+
const DEFAULT_WIDTH = Dimensions.get('window').width;
|
|
14
8
|
|
|
15
9
|
class LoadingIndicator extends Component {
|
|
16
10
|
constructor(props) {
|
|
17
11
|
super(props);
|
|
18
12
|
this.state = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
animatedOpacity3: new Animated.Value(OPACITY_START),
|
|
22
|
-
animatedOpacity4: new Animated.Value(0),
|
|
23
|
-
animatedLeft4: new Animated.Value(LEFT_START),
|
|
24
|
-
animatedHeight: new Animated.Value(this.props.visible ? DEFAULT_HEIGHT : 0),
|
|
13
|
+
animatedLeft: new Animated.Value(-DEFAULT_WIDTH),
|
|
14
|
+
animatedOpacity: new Animated.Value(0),
|
|
25
15
|
};
|
|
26
16
|
this.height = 0;
|
|
27
17
|
}
|
|
@@ -36,8 +26,8 @@ class LoadingIndicator extends Component {
|
|
|
36
26
|
|
|
37
27
|
componentDidUpdate(prevProps) {
|
|
38
28
|
if (prevProps.visible !== this.props.visible) {
|
|
39
|
-
Animated.timing(this.state.
|
|
40
|
-
toValue: this.props.visible ?
|
|
29
|
+
Animated.timing(this.state.animatedOpacity, {
|
|
30
|
+
toValue: this.props.visible ? 0.8 : 0,
|
|
41
31
|
duration: 300,
|
|
42
32
|
useNativeDriver: false,
|
|
43
33
|
}).start();
|
|
@@ -46,95 +36,32 @@ class LoadingIndicator extends Component {
|
|
|
46
36
|
|
|
47
37
|
animate = () => {
|
|
48
38
|
Animated.sequence([
|
|
49
|
-
Animated.timing(this.state.
|
|
50
|
-
toValue:
|
|
51
|
-
duration:
|
|
39
|
+
Animated.timing(this.state.animatedLeft, {
|
|
40
|
+
toValue: DEFAULT_WIDTH,
|
|
41
|
+
duration: 1500,
|
|
52
42
|
useNativeDriver: false,
|
|
53
43
|
}),
|
|
54
|
-
Animated.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
useNativeDriver: false,
|
|
59
|
-
}),
|
|
60
|
-
Animated.timing(this.state.animatedLeft4, {
|
|
61
|
-
toValue: LEFT_END1,
|
|
62
|
-
duration: 250,
|
|
63
|
-
useNativeDriver: false,
|
|
64
|
-
}),
|
|
65
|
-
]),
|
|
66
|
-
Animated.timing(this.state.animatedOpacity4, {
|
|
67
|
-
toValue: OPACITY_END2,
|
|
68
|
-
duration: 250,
|
|
69
|
-
useNativeDriver: false,
|
|
70
|
-
}),
|
|
71
|
-
Animated.parallel([
|
|
72
|
-
Animated.timing(this.state.animatedOpacity2, {
|
|
73
|
-
toValue: OPACITY_END2,
|
|
74
|
-
duration: 250,
|
|
75
|
-
useNativeDriver: false,
|
|
76
|
-
}),
|
|
77
|
-
Animated.timing(this.state.animatedLeft4, {
|
|
78
|
-
toValue: LEFT_END2,
|
|
79
|
-
duration: 250,
|
|
80
|
-
useNativeDriver: false,
|
|
81
|
-
}),
|
|
82
|
-
]),
|
|
83
|
-
Animated.parallel([
|
|
84
|
-
Animated.timing(this.state.animatedOpacity4, {
|
|
85
|
-
toValue: OPACITY_END3,
|
|
86
|
-
duration: 250,
|
|
87
|
-
useNativeDriver: false,
|
|
88
|
-
}),
|
|
89
|
-
Animated.timing(this.state.animatedOpacity3, {
|
|
90
|
-
toValue: OPACITY_END3,
|
|
91
|
-
duration: 250,
|
|
92
|
-
useNativeDriver: false,
|
|
93
|
-
}),
|
|
94
|
-
]),
|
|
95
|
-
Animated.parallel([
|
|
96
|
-
Animated.timing(this.state.animatedLeft4, {
|
|
97
|
-
toValue: LEFT_START,
|
|
98
|
-
duration: 1,
|
|
99
|
-
useNativeDriver: false,
|
|
100
|
-
}),
|
|
101
|
-
Animated.timing(this.state.animatedOpacity4, {
|
|
102
|
-
toValue: 0,
|
|
103
|
-
duration: 1,
|
|
104
|
-
useNativeDriver: false,
|
|
105
|
-
}),
|
|
106
|
-
]),
|
|
107
|
-
Animated.timing(this.state.animatedOpacity3, {
|
|
108
|
-
toValue: OPACITY_START,
|
|
109
|
-
duration: 250,
|
|
110
|
-
useNativeDriver: false,
|
|
111
|
-
}),
|
|
112
|
-
Animated.timing(this.state.animatedOpacity2, {
|
|
113
|
-
toValue: OPACITY_START,
|
|
114
|
-
duration: 250,
|
|
115
|
-
useNativeDriver: false,
|
|
116
|
-
}),
|
|
117
|
-
Animated.timing(this.state.animatedOpacity1, {
|
|
118
|
-
toValue: OPACITY_START,
|
|
119
|
-
duration: 250,
|
|
44
|
+
Animated.delay(500),
|
|
45
|
+
Animated.timing(this.state.animatedLeft, {
|
|
46
|
+
toValue: -DEFAULT_WIDTH,
|
|
47
|
+
duration: 1500,
|
|
120
48
|
useNativeDriver: false,
|
|
121
49
|
}),
|
|
50
|
+
Animated.delay(500),
|
|
122
51
|
]).start(() => {
|
|
123
52
|
this.animate();
|
|
124
53
|
});
|
|
125
54
|
};
|
|
126
55
|
|
|
127
56
|
render() {
|
|
128
|
-
const { animatedOpacity1, animatedOpacity2, animatedOpacity3, animatedOpacity4, animatedLeft4, animatedHeight } = this.state;
|
|
129
|
-
|
|
130
57
|
return (
|
|
131
|
-
<Animated.View
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
58
|
+
<Animated.View
|
|
59
|
+
style={[styles.container, this.props.style, { height: DEFAULT_HEIGHT, opacity: this.state.animatedOpacity }]}
|
|
60
|
+
onLayout={this.onLayout}
|
|
61
|
+
>
|
|
62
|
+
<Animated.View
|
|
63
|
+
style={[styles.line, { backgroundColor: this.props.colourBrandingMain, left: this.state.animatedLeft, height: DEFAULT_HEIGHT }]}
|
|
64
|
+
/>
|
|
138
65
|
</Animated.View>
|
|
139
66
|
);
|
|
140
67
|
}
|
|
@@ -145,20 +72,23 @@ const styles = StyleSheet.create({
|
|
|
145
72
|
alignItems: 'center',
|
|
146
73
|
justifyContent: 'center',
|
|
147
74
|
overflow: 'hidden',
|
|
148
|
-
backgroundColor: '#
|
|
75
|
+
backgroundColor: '#fff',
|
|
149
76
|
width: '100%',
|
|
150
77
|
height: 38,
|
|
151
78
|
},
|
|
152
79
|
innerContainer: {
|
|
153
80
|
flexDirection: 'row',
|
|
154
81
|
},
|
|
155
|
-
|
|
156
|
-
width:
|
|
157
|
-
height: CIRCLE_SIZE,
|
|
158
|
-
borderRadius: CIRCLE_SIZE / 2,
|
|
159
|
-
backgroundColor: TEXT_BLUEGREY,
|
|
160
|
-
marginHorizontal: 4,
|
|
82
|
+
line: {
|
|
83
|
+
width: DEFAULT_WIDTH,
|
|
161
84
|
},
|
|
162
85
|
});
|
|
163
86
|
|
|
164
|
-
|
|
87
|
+
const mapStateToProps = state => {
|
|
88
|
+
return {
|
|
89
|
+
colourBrandingMain: getMainBrandingColourFromState(state),
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default connect(mapStateToProps, {})(LoadingIndicator);
|
|
94
|
+
// export { loadingIndicator as Default };
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import { View, StyleSheet, Dimensions } from 'react-native';
|
|
3
|
+
import YoutubePlayer, { getYoutubeMeta } from 'react-native-youtube-iframe';
|
|
4
|
+
// import { Vimeo } from 'react-native-vimeo-iframe';
|
|
5
|
+
import WebView from 'react-native-webview';
|
|
6
|
+
import { Video } from 'expo-av';
|
|
7
|
+
import { Spinner } from './Spinner';
|
|
8
|
+
|
|
9
|
+
const SCREEN_HEIGHT = Dimensions.get('window').height;
|
|
10
|
+
const SCREEN_WIDTH = Dimensions.get('window').width;
|
|
11
|
+
const EXPO_VIDEO_PROPS = { rate: 1, isMuted: false, volume: 1, shouldPlay: true };
|
|
12
|
+
const RETRY_RECOVER = 30000;
|
|
13
|
+
const RETRY_LOADING = 10000;
|
|
14
|
+
|
|
15
|
+
class MediaPlayer extends Component {
|
|
16
|
+
constructor(props) {
|
|
17
|
+
super(props);
|
|
18
|
+
this.state = {
|
|
19
|
+
isUrlLink: true,
|
|
20
|
+
isYoutube: false,
|
|
21
|
+
forceWebview: false,
|
|
22
|
+
heightFactor: 0.565,
|
|
23
|
+
playbackLoaded: false,
|
|
24
|
+
playbackBuffering: false,
|
|
25
|
+
playbackPlaying: false,
|
|
26
|
+
};
|
|
27
|
+
this.youtubePlayer = null;
|
|
28
|
+
this.videoPlayer = null;
|
|
29
|
+
this.checkStreamLoaded = null;
|
|
30
|
+
this.retryLoading = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
componentDidMount() {
|
|
34
|
+
this.setupForLiveStreaming();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
componentWillUnmount() {
|
|
38
|
+
if (this.checkStreamLoaded) clearInterval(this.checkStreamLoaded);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getYoutubeVideoId = url => {
|
|
42
|
+
url = url.replace(/(>|<)/gi, '').split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
|
|
43
|
+
if (url[2] !== undefined) {
|
|
44
|
+
const ids = url[2].split(/[^0-9a-z_\-]/i);
|
|
45
|
+
return ids[0];
|
|
46
|
+
} else {
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
setupForLiveStreaming = async () => {
|
|
52
|
+
// Extract live stream info
|
|
53
|
+
const { streamUrl } = this.props.streamInfo;
|
|
54
|
+
const isUrlLink = streamUrl.startsWith('http');
|
|
55
|
+
const isYoutube = streamUrl.includes('youtube.com/watch?v=') || streamUrl.includes('youtu.be/');
|
|
56
|
+
this.setState({ isUrlLink, isYoutube });
|
|
57
|
+
|
|
58
|
+
// if (isYoutube) {
|
|
59
|
+
// const metadata = await getYoutubeMeta(this.getYoutubeVideoId(streamUrl));
|
|
60
|
+
// this.setState({ heightFactor: metadata.height / metadata.width });
|
|
61
|
+
// console.log('youtube metadata', metadata);
|
|
62
|
+
// }
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
getStreamPlaybackUrl = () => {
|
|
66
|
+
// return 'https://stream.mux.com/nflNhyFQMlrSt00II01Hjh2BLSW009PH1tl023pdpJ01s1vc.m3u8';
|
|
67
|
+
return `https://stream.mux.com/${this.props.streamInfo.playbackId}.m3u8`;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
checkReloadStream = (wait = RETRY_LOADING, force = false) => {
|
|
71
|
+
if (!force && this.retryLoading) return;
|
|
72
|
+
|
|
73
|
+
console.log(`Check loading in ${wait} milliseconds...`);
|
|
74
|
+
this.retryLoading = true;
|
|
75
|
+
setTimeout(async () => {
|
|
76
|
+
const { playbackLoaded, playbackBuffering } = this.state;
|
|
77
|
+
try {
|
|
78
|
+
if (playbackLoaded === false || playbackBuffering === true) {
|
|
79
|
+
console.log('Reloading started');
|
|
80
|
+
await this.videoPlayer.loadAsync(
|
|
81
|
+
{ uri: this.getStreamPlaybackUrl(), overrideFileExtensionAndroid: 'm3u8' },
|
|
82
|
+
EXPO_VIDEO_PROPS,
|
|
83
|
+
false,
|
|
84
|
+
);
|
|
85
|
+
} else {
|
|
86
|
+
console.log('Already loaded - not reloading');
|
|
87
|
+
}
|
|
88
|
+
this.retryLoading = false;
|
|
89
|
+
} catch {}
|
|
90
|
+
}, wait);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
onStreamLoadStart = () => {
|
|
94
|
+
console.log('Stream load started');
|
|
95
|
+
this.checkStreamLoaded = setInterval(() => {
|
|
96
|
+
const { playbackLoaded } = this.state;
|
|
97
|
+
if (playbackLoaded === false) {
|
|
98
|
+
console.log('Stream loading failed unexpectedly');
|
|
99
|
+
this.checkReloadStream(1000, true);
|
|
100
|
+
} else {
|
|
101
|
+
clearInterval(this.checkStreamLoaded);
|
|
102
|
+
}
|
|
103
|
+
}, RETRY_RECOVER);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
onStreamLoaded = status => {
|
|
107
|
+
console.log(`Stream loaded - isLoaded:${status.isLoaded}, isBuffering:${status.isBuffering}, isPlaying:${status.isPlaying}`);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
onStreamError = error => {
|
|
111
|
+
console.log('Stream error', error);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
onStreamStatusUpdate = status => {
|
|
115
|
+
this.setState(
|
|
116
|
+
{
|
|
117
|
+
playbackLoaded: status.isLoaded,
|
|
118
|
+
playbackBuffering: status.isBuffering,
|
|
119
|
+
playbackPlaying: status.isPlaying,
|
|
120
|
+
},
|
|
121
|
+
() => {
|
|
122
|
+
const { playbackLoaded, playbackBuffering, playbackPlaying, shouldPlay } = this.state;
|
|
123
|
+
// console.log(`Status updated - isLoaded:${playbackLoaded}, isBuffering:${playbackBuffering}, isPlaying:${playbackPlaying}`);
|
|
124
|
+
if (playbackLoaded === false && playbackBuffering === undefined && playbackPlaying === undefined) {
|
|
125
|
+
this.checkReloadStream();
|
|
126
|
+
} else if (playbackLoaded === true && playbackBuffering === true) {
|
|
127
|
+
this.checkReloadStream(RETRY_RECOVER);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
onYoutubeError = e => {
|
|
134
|
+
// console.log('onYoutubeError', e);
|
|
135
|
+
this.setState({ forceWebview: true });
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
onYoutubeReady = () => {
|
|
139
|
+
// console.log('onYoutubeReady');
|
|
140
|
+
this.setState({ playbackLoaded: true });
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
getYoutubePlayer = (youtubeId, width, height) => (
|
|
144
|
+
<YoutubePlayer
|
|
145
|
+
ref={ref => (this.youtubePlayer = ref)}
|
|
146
|
+
height={height}
|
|
147
|
+
width={width}
|
|
148
|
+
videoId={youtubeId}
|
|
149
|
+
play
|
|
150
|
+
// onChangeState={event => console.log('onChangeState', event)}
|
|
151
|
+
onReady={this.onYoutubeReady}
|
|
152
|
+
onError={this.onYoutubeError}
|
|
153
|
+
// onPlaybackQualityChange={q => console.log('onPlaybackQualityChange', q)}
|
|
154
|
+
volume={50}
|
|
155
|
+
playbackRate={1}
|
|
156
|
+
playerParams={{
|
|
157
|
+
cc_lang_pref: 'us',
|
|
158
|
+
showClosedCaptions: true,
|
|
159
|
+
}}
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
getWebviewPlayer = embedUrl => (
|
|
164
|
+
<WebView
|
|
165
|
+
startInLoadingState
|
|
166
|
+
javaScriptEnabled
|
|
167
|
+
scrollEnabled={false}
|
|
168
|
+
automaticallyAdjustContentInsets={false}
|
|
169
|
+
mediaPlaybackRequiresUserAction
|
|
170
|
+
style={styles.webView}
|
|
171
|
+
source={{ uri: embedUrl }}
|
|
172
|
+
/>
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
getVideoPlayer = (embedUrl, width, height) => (
|
|
176
|
+
<Video
|
|
177
|
+
ref={vp => {
|
|
178
|
+
this.videoPlayer = vp;
|
|
179
|
+
}}
|
|
180
|
+
source={{ uri: embedUrl }}
|
|
181
|
+
{...EXPO_VIDEO_PROPS}
|
|
182
|
+
resizeMode={Video.RESIZE_MODE_CONTAIN}
|
|
183
|
+
useNativeControls
|
|
184
|
+
style={{ width, height }}
|
|
185
|
+
onLoadStart={this.onStreamLoadStart}
|
|
186
|
+
onLoad={this.onStreamLoaded}
|
|
187
|
+
onError={this.onStreamError}
|
|
188
|
+
onPlaybackStatusUpdate={this.onStreamStatusUpdate}
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
render() {
|
|
193
|
+
let width, height;
|
|
194
|
+
const { landscape, streamInfo } = this.props;
|
|
195
|
+
if (landscape) {
|
|
196
|
+
width = SCREEN_HEIGHT;
|
|
197
|
+
height = SCREEN_WIDTH;
|
|
198
|
+
} else {
|
|
199
|
+
width = SCREEN_WIDTH;
|
|
200
|
+
height = SCREEN_WIDTH * this.state.heightFactor;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const { isUrlLink, isYoutube, forceWebview, playbackLoaded, playbackBuffering } = this.state;
|
|
204
|
+
const { playbackId, streamUrl } = streamInfo;
|
|
205
|
+
let embedUrl, player;
|
|
206
|
+
if (isYoutube && !forceWebview) {
|
|
207
|
+
const youtubeId = this.getYoutubeVideoId(streamUrl);
|
|
208
|
+
embedUrl = youtubeId ? `https://www.youtube.com/embed/${youtubeId}` : streamUrl;
|
|
209
|
+
player = this.getYoutubePlayer(youtubeId, width, height);
|
|
210
|
+
} else if (isUrlLink) {
|
|
211
|
+
embedUrl = streamUrl;
|
|
212
|
+
player = this.getWebviewPlayer(embedUrl);
|
|
213
|
+
} else if (playbackId) {
|
|
214
|
+
embedUrl = this.getStreamPlaybackUrl();
|
|
215
|
+
player = this.getVideoPlayer(embedUrl, width, height);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// console.log('Streaming:', embedUrl, 'landscape', landscape, 'playbackLoaded', playbackLoaded, 'playbackBuffering', playbackBuffering);
|
|
219
|
+
return (
|
|
220
|
+
<View style={[styles.container, !isUrlLink && { alignItems: 'center' }, { width, height }]}>
|
|
221
|
+
{player}
|
|
222
|
+
{(!playbackLoaded || playbackBuffering) && (
|
|
223
|
+
<View style={styles.loadingContainer}>
|
|
224
|
+
<Spinner color={'#fff'} />
|
|
225
|
+
</View>
|
|
226
|
+
)}
|
|
227
|
+
</View>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const styles = StyleSheet.create({
|
|
233
|
+
container: {
|
|
234
|
+
backgroundColor: '#000',
|
|
235
|
+
},
|
|
236
|
+
webView: {
|
|
237
|
+
flex: 1,
|
|
238
|
+
},
|
|
239
|
+
loadingContainer: {
|
|
240
|
+
position: 'absolute',
|
|
241
|
+
top: 50,
|
|
242
|
+
left: 0,
|
|
243
|
+
right: 0,
|
|
244
|
+
bottom: 50,
|
|
245
|
+
justifyContent: 'center',
|
|
246
|
+
alignItems: 'center',
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
export default MediaPlayer;
|
package/src/components/index.js
CHANGED
|
@@ -47,3 +47,4 @@ export { default as UserListing } from './UserListing';
|
|
|
47
47
|
export { default as PlussChat } from './PlussChat';
|
|
48
48
|
export { default as PositionedImage } from './PositionedImage';
|
|
49
49
|
export { default as FormattedText } from './FormattedText';
|
|
50
|
+
export { default as MediaPlayer } from './MediaPlayer';
|