Browse Source

add offline videoplayer

David 9 years ago
parent
commit
01ea23e3f4

+ 2 - 0
src/Router.js

@@ -13,6 +13,7 @@ import Teoria from './scenes/Clase/Teoria';
 import LSListaClases from './scenes/LSListaClases';
 import LSListaClases from './scenes/LSListaClases';
 import MyAbout from './scenes/MyAbout';
 import MyAbout from './scenes/MyAbout';
 import Splash from './scenes/Splash';
 import Splash from './scenes/Splash';
+import MyVideoPlayer from './scenes/Clase/VideoPlayer';
 
 
 const scenes = Actions.create(
 const scenes = Actions.create(
 	<Scene key='container'>
 	<Scene key='container'>
@@ -42,6 +43,7 @@ const scenes = Actions.create(
 			<Scene key='ViewClase' component={Clase} title='Clase' />
 			<Scene key='ViewClase' component={Clase} title='Clase' />
 			<Scene key='ViewProf' component={Profesor} title='Profesor' />
 			<Scene key='ViewProf' component={Profesor} title='Profesor' />
 			<Scene key='Live' title='Curso en vivo' component={LiveVideo} />
 			<Scene key='Live' title='Curso en vivo' component={LiveVideo} />
+			<Scene key='ViewVideo' component={MyVideoPlayer} title='VideoP' />
 		</Scene>
 		</Scene>
 
 
 
 

+ 1 - 1
src/api/api.js

@@ -19,7 +19,7 @@ export async function post(path, data) {
       return Promise.reject(json.error);
       return Promise.reject(json.error);
 
 
   } catch(error) {
   } catch(error) {
-    //console.log('rejecting', path);
+    console.log('rejecting', path, data);
     return Promise.reject('Error indefinido');
     return Promise.reject('Error indefinido');
   }
   }
 }
 }

+ 0 - 3
src/components/Socket.js

@@ -12,9 +12,6 @@ class Socket extends Component {
 			const msg = JSON.parse(e.data);
 			const msg = JSON.parse(e.data);
 			console.log(msg);
 			console.log(msg);
 			switch (msg.type) {
 			switch (msg.type) {
-				case 'diapo':
-					this.props.onDiapoChanged(msg.PDF, msg.slide);
-					return;
 				case 'chat':
 				case 'chat':
 					this.props.onMessage(msg.user, msg.text);
 					this.props.onMessage(msg.user, msg.text);
 					return;
 					return;

+ 1 - 0
src/components/common/Button.js

@@ -24,6 +24,7 @@ const styles = {
   },
   },
   buttonStyle: {
   buttonStyle: {
     flex: 1,
     flex: 1,
+	minHeight: 30,
     maxHeight: 40,
     maxHeight: 40,
     justifyContent: 'center',
     justifyContent: 'center',
     alignSelf: 'stretch',
     alignSelf: 'stretch',

+ 237 - 0
src/scenes/Clase/VideoPlayer.js

@@ -0,0 +1,237 @@
+'use strict';
+
+import React, {
+  Component
+} from 'react';
+
+import {
+  StyleSheet,
+  Text,
+  TouchableOpacity,
+  View,
+} from 'react-native';
+
+import Video from 'react-native-video';
+import StatusBarAndroid from 'react-native-android-statusbar';
+
+class MyVideoPlayer extends Component {
+
+  state = {
+    rate: 1,
+    volume: 1,
+    muted: false,
+    resizeMode: 'contain',
+    duration: 0.0,
+    currentTime: 0.0,
+    paused: true,
+  };
+
+  video: Video;
+
+  onLoad = (data) => {
+	console.log("load", data);
+    this.setState({ duration: data.duration });
+  };
+
+  onProgress = (data) => {
+	  console.log("progress", data);
+    this.setState({ currentTime: data.currentTime });
+  };
+
+  onEnd = () => {
+    this.setState({ paused: true })
+    this.video.seek(0)
+  };
+
+  onAudioBecomingNoisy = () => {
+    this.setState({ paused: true })
+  };
+
+  onAudioFocusChanged = (event: { hasAudioFocus: boolean }) => {
+    this.setState({ paused: !event.hasAudioFocus })
+  };
+
+  getCurrentTimePercentage() {
+    if (this.state.currentTime > 0) {
+      return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
+    }
+    return 0;
+  };
+
+  renderRateControl(rate) {
+    const isSelected = (this.state.rate === rate);
+
+    return (
+      <TouchableOpacity onPress={() => { this.setState({ rate }) }}>
+        <Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}>
+          {rate}x
+        </Text>
+      </TouchableOpacity>
+    );
+  }
+
+  renderResizeModeControl(resizeMode) {
+    const isSelected = (this.state.resizeMode === resizeMode);
+
+    return (
+      <TouchableOpacity onPress={() => { this.setState({ resizeMode }) }}>
+        <Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}>
+          {resizeMode}
+        </Text>
+      </TouchableOpacity>
+    )
+  }
+
+  renderVolumeControl(volume) {
+    const isSelected = (this.state.volume === volume);
+
+    return (
+      <TouchableOpacity onPress={() => { this.setState({ volume }) }}>
+        <Text style={[styles.controlOption, { fontWeight: isSelected ? 'bold' : 'normal' }]}>
+          {volume * 100}%
+        </Text>
+      </TouchableOpacity>
+    )
+  }
+  componentDidMount() {
+  	StatusBarAndroid.hideStatusBar()
+  }
+  componentWillUnmount() {
+  	StatusBarAndroid.showStatusBar()
+  }
+  render() {
+    const flexCompleted = this.getCurrentTimePercentage() * 100;
+    const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
+
+    return (
+      <View style={styles.container}>
+        <TouchableOpacity
+          style={styles.fullScreen}
+          onPress={() => this.setState({ paused: !this.state.paused })}
+        >
+          <Video
+            ref={(ref: Video) => { this.video = ref }}
+            /* For ExoPlayer */
+            /* source={{ uri: 'http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0', type: 'mpd' }} */
+            source={{ uri: 'https://f001.backblazeb2.com/file/videos-storage/test3.mp4'}}
+            style={styles.fullScreen}
+            rate={this.state.rate}
+            paused={this.state.paused}
+            volume={this.state.volume}
+            muted={this.state.muted}
+            resizeMode={this.state.resizeMode}
+            onLoad={this.onLoad}
+            onProgress={this.onProgress}
+            onEnd={this.onEnd}
+            onAudioBecomingNoisy={this.onAudioBecomingNoisy}
+            onAudioFocusChanged={this.onAudioFocusChanged}
+            repeat={false}
+          />
+        </TouchableOpacity>
+
+        <View style={styles.controls}>
+          <View style={styles.generalControls}>
+            <View style={styles.rateControl}>
+              {this.renderRateControl(0.25)}
+              {this.renderRateControl(0.5)}
+              {this.renderRateControl(1.0)}
+              {this.renderRateControl(1.5)}
+              {this.renderRateControl(2.0)}
+            </View>
+
+            <View style={styles.volumeControl}>
+              {this.renderVolumeControl(0.5)}
+              {this.renderVolumeControl(1)}
+              {this.renderVolumeControl(1.5)}
+            </View>
+
+            <View style={styles.resizeModeControl}>
+              {this.renderResizeModeControl('cover')}
+              {this.renderResizeModeControl('contain')}
+              {this.renderResizeModeControl('stretch')}
+            </View>
+          </View>
+
+          <View style={styles.trackingControls}>
+            <View style={styles.progress}>
+              <View style={[styles.innerProgressCompleted, { flex: flexCompleted }]} />
+              <View style={[styles.innerProgressRemaining, { flex: flexRemaining }]} />
+            </View>
+          </View>
+        </View>
+      </View>
+    );
+  }
+}
+
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+    justifyContent: 'center',
+    alignItems: 'center',
+    backgroundColor: 'black',
+  },
+  fullScreen: {
+    position: 'absolute',
+    top: 0,
+    left: 0,
+    bottom: 0,
+    right: 0,
+  },
+  controls: {
+    backgroundColor: 'transparent',
+    borderRadius: 5,
+    position: 'absolute',
+    bottom: 20,
+    left: 20,
+    right: 20,
+  },
+  progress: {
+    flex: 1,
+    flexDirection: 'row',
+    borderRadius: 3,
+    overflow: 'hidden',
+  },
+  innerProgressCompleted: {
+    height: 20,
+    backgroundColor: '#cccccc',
+  },
+  innerProgressRemaining: {
+    height: 20,
+    backgroundColor: '#2C2C2C',
+  },
+  generalControls: {
+    flex: 1,
+    flexDirection: 'row',
+    borderRadius: 4,
+    overflow: 'hidden',
+    paddingBottom: 10,
+  },
+  rateControl: {
+    flex: 1,
+    flexDirection: 'row',
+    justifyContent: 'center',
+  },
+  volumeControl: {
+    flex: 1,
+    flexDirection: 'row',
+    justifyContent: 'center',
+  },
+  resizeModeControl: {
+    flex: 1,
+    flexDirection: 'row',
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  controlOption: {
+    alignSelf: 'center',
+    fontSize: 11,
+    color: 'white',
+    paddingLeft: 2,
+    paddingRight: 2,
+    lineHeight: 12,
+  },
+});
+
+export default MyVideoPlayer;

+ 31 - 51
src/scenes/Clase/Videos.js

@@ -1,69 +1,49 @@
 import React, { Component } from 'react';
 import React, { Component } from 'react';
 import { Text, ListView, View } from 'react-native';
 import { Text, ListView, View } from 'react-native';
 import { Card, CardSection, Button } from '../../components/common';
 import { Card, CardSection, Button } from '../../components/common';
+import { Actions } from 'react-native-router-flux';
+
 import Header from './Header';
 import Header from './Header';
-import Video from 'react-native-video';
-import VideoPlayer from 'react-native-video-controls';
+//import VideoPlayer from 'react-native-video-controls';
 
 
 class Videos extends Component {
 class Videos extends Component {
 
 
-  componentWillMount() {
-    this.createDataSource(this.props);
+	componentWillMount() {
+		this.createDataSource(this.props);
 	}
 	}
-
 	componentWillReceiveProps(nextProps) {
 	componentWillReceiveProps(nextProps) {
 		this.createDataSource(nextProps);
 		this.createDataSource(nextProps);
 	}
 	}
 
 
-  createDataSource({ videos }) {
-    const ds = new ListView.DataSource({
-      rowHasChanged: (r1, r2) => r1 !== r2
-    });
+	createDataSource({ videos }) {
+		const ds = new ListView.DataSource({
+			rowHasChanged: (r1, r2) => r1 !== r2
+		});
 
 
-    console.log(videos);
-    this.dataSource = ds.cloneWithRows(videos);
+		console.log(videos);
+		this.dataSource = ds.cloneWithRows(videos);
 	}
 	}
 
 
-
-
-  renderHeader() {
-	   return <Header titulo={this.props.titulo} profesor={this.props.profesor} fecha={this.props.fecha} />;
-  }
-  playVideo(id) {
-    console.log("Playing", id);
-    this.refs.youtubePlayer.videoId = id;
-    //player.play = true;
-    this.refs.youtubePlayer.seekTo(1);
-  }
-  renderVideo({ video, titulo }) {
-    console.log(video, titulo);
-
-    return ( <Text onPress={this.playVideo.bind(this, video) }>{titulo}</Text> );
-  }
-  render() {
-    return (
-      <View>
-        <ListView
-          dataSource={this.dataSource}
-          renderRow={this.renderVideo.bind(this)}
-        />
-        <VideoPlayer
-          source={{ uri: 'https://f001.backblazeb2.com/file/videos-storage/test.mp4' }}
-          ref={(ref) => { this.player = ref; }}
-          volume={1}
-          resizeMode={'contain'}
-          videoStyle={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
-          navigator={ this.props.navigator }
-          rate={ 1 }
-          controlTimeout={ 15000 }
-          resizeMode="cover"
-          playInBackground={true}
-          playWhenInactive={true}
-
-        />
-      </View>
-   );
-  }
+	renderHeader() {
+		return <Header titulo={this.props.titulo} profesor={this.props.profesor} fecha={this.props.fecha} />;
+	}
+	playVideo(id) {
+		Actions.ViewVideo({ id:id });
+	}
+	renderVideo({ video, titulo }) {
+		return ( <Button onPress={this.playVideo.bind(this, video) }>{titulo}</Button> );
+	}
+	render() {
+		return (
+			<View>
+			<ListView
+			dataSource={this.dataSource}
+			renderRow={this.renderVideo.bind(this)}
+			/>
+
+			</View>
+		);
+	}
 }
 }
 
 
 const styles = {
 const styles = {

+ 10 - 6
src/scenes/LiveVideo.js

@@ -10,18 +10,23 @@ import VideoPlayer from 'react-native-video-controls';
 import Socket from '../components/Socket';
 import Socket from '../components/Socket';
 import Chat from './Live/Chat';
 import Chat from './Live/Chat';
 
 
+import StatusBarAndroid from 'react-native-android-statusbar';
+
+
 class LiveVideo extends Component {
 class LiveVideo extends Component {
 	bienvenida = { time: this.getTime(), user: "Sistema", text: "Conectado" };
 	bienvenida = { time: this.getTime(), user: "Sistema", text: "Conectado" };
 	state = { pdf: 'EBA', diapo: 1, messages: [ this.bienvenida ] };
 	state = { pdf: 'EBA', diapo: 1, messages: [ this.bienvenida ] };
 
 
+	componentDidMount() {
+		StatusBarAndroid.hideStatusBar()
+	}
+	componentWillUnmount() {
+		StatusBarAndroid.showStatusBar()
+	}
 	onMessage(user, text) {
 	onMessage(user, text) {
 		this.setState({ messages: [...this.state.messages, { time: this.getTime(), user, text }] });
 		this.setState({ messages: [...this.state.messages, { time: this.getTime(), user, text }] });
 	}
 	}
 
 
-	onDiapoChanged(pdf, diapo) {
-		console.log('Diapo changed!', pdf, diapo);
-		this.setState({ pdf, diapo });
-	}
 	getTime() {
 	getTime() {
 		const d = new Date();
 		const d = new Date();
 		const currHour = d.getHours();
 		const currHour = d.getHours();
@@ -52,7 +57,7 @@ class LiveVideo extends Component {
 								resizeMode="cover"
 								resizeMode="cover"
 								playInBackground={true}
 								playInBackground={true}
 								playWhenInactive={true}
 								playWhenInactive={true}
-								
+
 							/>
 							/>
 						</View>
 						</View>
 					</View>
 					</View>
@@ -62,7 +67,6 @@ class LiveVideo extends Component {
 					</View>
 					</View>
 				</ScrollableTabView>
 				</ScrollableTabView>
 				<Socket
 				<Socket
-					onDiapoChanged={this.onDiapoChanged.bind(this)}
 					onMessage={this.onMessage.bind(this)}
 					onMessage={this.onMessage.bind(this)}
 				/>
 				/>
 			</View>
 			</View>