react-native-media-kit
Version:
Video and Audio component for react-native apps, supporting both iOS and Android.
173 lines (151 loc) • 4.54 kB
JavaScript
import React, {PropTypes} from 'react';
import ReactNative, {
StyleSheet,
Text,
View,
TouchableOpacity,
NativeModules,
requireNativeComponent,
Dimensions,
ScrollView,
Image,
Platform,
ActivityIndicator,
} from 'react-native';
import Slider from '@ldn0x7dc/react-native-slider';
/**
* format as --:-- or --:--:--
* @param timeSec
* @param containHours
* @returns {string}
*/
function formatProgress(timeSec, containHours) {
function zeroPad(s) {
if (s.length === 1) {
return '0' + s;
}
return s;
}
let hours = Math.floor(timeSec / 60.0 / 60.0).toFixed(0);
let minutes = Math.floor(timeSec / 60.0 % 60.0).toFixed(0);
let seconds = Math.floor(timeSec % 60.0).toFixed(0);
if(hours < 0) {
hours = 0;
}
if (minutes < 0) {
minutes = 0;
}
if(seconds < 0) {
seconds = 0;
}
hours = zeroPad(hours);
minutes = zeroPad(minutes);
seconds = zeroPad(seconds);
if (containHours) {
return hours + ':' + minutes + ':' + seconds;
}
return minutes + ':' + seconds;
}
export default class Controls extends React.Component {
defaultProps = {
current: 0,
total: 0,
buffering: false,
playing: false
}
constructor(props) {
super(props);
this.state = {
sliding: false,
current: this.props.current,
};
}
componentWillReceiveProps(nextProps) {
if (!this.state.sliding) {
if (this.props.current != nextProps.current) {
this.setState({
current: nextProps.current,
});
}
}
}
render() {
const containHours = this.props.total >= 60 * 60 * 1000;
const currentFormated = formatProgress(this.state.current / 1000, containHours);
const totalFormated = formatProgress(this.props.total / 1000, containHours);
let bufferIndicator;
if(this.props.buffering) {
bufferIndicator = (
<ActivityIndicator
color={'#f2f2f2'}
size={'large'}/>
);
}
let tracks = [];
if(this.props.bufferRanges) {
tracks = this.props.bufferRanges.map((range) => {
let startValue = range.start;
let endValue = startValue + range.duration;
return {
key: 'bufferTrack:' + startValue + '-' + endValue,
startValue, endValue,
style: {backgroundColor: '#eeeeee66'}
}
});
}
tracks.push(
{
key: 'thumbTrack',
style: {backgroundColor: 'white'}
}
);
return (
<View
style={{position: 'absolute', left: 0, top: 0, right: 0, bottom: 0, flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}>
{bufferIndicator}
<View
style={{position: 'absolute', left: 0, right: 0, bottom: 0, height: 40, backgroundColor: '#00000033', flexDirection: 'row'}}>
<TouchableOpacity
onPress={this.props.onPauseOrPlay}
style={{width: 40, height: 40, alignItems: 'center', justifyContent: 'center'}}>
<Image
style={{width: 20, height: 20, resizeMode: 'contain'}}
source={this.props.playing ? require('./img/media-player-pause.png') : require('./img/media-player-play.png')}/>
</TouchableOpacity>
<Text
style={{alignSelf: 'center', fontSize: 12, color: 'white', width: currentFormated.length == 5 ? 35:56, textAlign: 'right'}}>
{currentFormated}
</Text>
<Slider
style={{flex: 1, marginHorizontal: 5, height: 40}}
trackContainerStyle={{height: 2, backgroundColor: 'gray'}}
thumbImage={require('./img/media-player-thumb.png')}
thumbStyle={{width: 10, height: 10}}
onSlidingComplete={(value) => {
this.setState({
sliding: false,
current: value
});
this.props.onSeekTo && this.props.onSeekTo(value);
}}
onValueChange={(value) => {
this.setState({
sliding: true,
current: value
});
}}
maximumValue={this.props.total}
minimumValue={0}
value={this.state.current}
disabled={this.props.total > 0}
tracks={tracks}
/>
<Text
style={{alignSelf: 'center', fontSize: 12, color: 'white', width: totalFormated.length == 5 ? 35:56, marginRight: 10}}>
{totalFormated}
</Text>
</View>
</View>
);
}
}