import React from 'react'; import { Lbry } from 'lbry-redux'; import { NativeModules, PanResponder, Text, View, ScrollView, TouchableOpacity } from 'react-native'; import Video from 'react-native-video'; import Icon from 'react-native-vector-icons/FontAwesome'; import FileItemMedia from '../fileItemMedia'; import mediaPlayerStyle from '../../styles/mediaPlayer'; class MediaPlayer extends React.PureComponent { static ControlsTimeout = 3000; seekResponder = null; seekerWidth = 0; video = null; state = { rate: 1, volume: 1, muted: false, resizeMode: 'stretch', duration: 0.0, currentTime: 0.0, paused: true, fullscreenMode: false, areControlsVisible: true, controlsTimeout: -1, seekerOffset: 0, seekerPosition: 0, firstPlay: true }; formatTime(time) { let str = ''; let minutes = 0, hours = 0, seconds = parseInt(time, 10); if (seconds > 60) { minutes = parseInt(seconds / 60, 10); seconds = seconds % 60; if (minutes > 60) { hours = parseInt(minutes / 60, 10); minutes = minutes % 60; } str = (hours > 0 ? this.pad(hours) + ':' : '') + this.pad(minutes) + ':' + this.pad(seconds); } else { str = '00:' + this.pad(seconds); } return str; } pad(value) { if (value < 10) { return '0' + String(value); } return value; } onLoad = (data) => { this.setState({ duration: data.duration }); if (this.props.onMediaLoaded) { this.props.onMediaLoaded(); } } onProgress = (data) => { this.setState({ currentTime: data.currentTime }); if (!this.state.seeking) { this.setSeekerPosition(this.calculateSeekerPosition()); } if (this.state.firstPlay) { if (NativeModules.Mixpanel) { const { uri } = this.props; NativeModules.Mixpanel.track('Play', { uri }); } this.setState({ firstPlay: false }); this.hidePlayerControls(); } } clearControlsTimeout = () => { if (this.state.controlsTimeout > -1) { clearTimeout(this.state.controlsTimeout) } } showPlayerControls = () => { this.clearControlsTimeout(); if (!this.state.areControlsVisible) { this.setState({ areControlsVisible: true }); } this.hidePlayerControls(); } hidePlayerControls() { const player = this; let timeout = setTimeout(() => { player.setState({ areControlsVisible: false }); }, MediaPlayer.ControlsTimeout); player.setState({ controlsTimeout: timeout }); } togglePlay = () => { this.showPlayerControls(); this.setState({ paused: !this.state.paused }); } toggleFullscreenMode = () => { this.showPlayerControls(); const { onFullscreenToggled } = this.props; this.setState({ fullscreenMode: !this.state.fullscreenMode }, () => { this.setState({ resizeMode: this.state.fullscreenMode ? 'contain' : 'stretch' }); if (onFullscreenToggled) { onFullscreenToggled(this.state.fullscreenMode); } }); } onEnd = () => { this.setState({ paused: true }); this.video.seek(0); } setSeekerPosition(position = 0) { position = this.checkSeekerPosition(position); this.setState({ seekerPosition: position }); if (!this.state.seeking) { this.setState({ seekerOffset: position }); } } checkSeekerPosition(val = 0) { if (val < 0) { val = 0; } else if (val >= this.seekerWidth) { return this.seekerWidth; } return val; } seekTo(time = 0) { if (time > this.state.duration) { return; } this.video.seek(time); this.setState({ currentTime: time }); } initSeeker() { this.seekResponder = PanResponder.create({ onStartShouldSetPanResponder: (evt, gestureState) => true, onMoveShouldSetPanResponder: (evt, gestureState) => true, onPanResponderGrant: (evt, gestureState) => { this.clearControlsTimeout(); this.setState({ seeking: true }); }, onPanResponderMove: (evt, gestureState) => { const position = this.state.seekerOffset + gestureState.dx; this.setSeekerPosition(position); }, onPanResponderRelease: (evt, gestureState) => { const time = this.getCurrentTimeForSeekerPosition(); if (time >= this.state.duration) { this.setState({ paused: true }); this.onEnd(); } else { this.seekTo(time); this.setState({ seeking: false }); } this.hidePlayerControls(); } }); } getCurrentTimeForSeekerPosition() { return this.state.duration * (this.state.seekerPosition / this.seekerWidth); } calculateSeekerPosition() { return this.seekerWidth * this.getCurrentTimePercentage(); } getCurrentTimePercentage() { if (this.state.currentTime > 0) { return parseFloat(this.state.currentTime) / parseFloat(this.state.duration); } return 0; }; componentWillMount() { this.initSeeker(); } componentWillUnmount() { this.clearControlsTimeout(); this.setState({ paused: true, fullscreenMode: false }); const { onFullscreenToggled } = this.props; if (onFullscreenToggled) { onFullscreenToggled(false); } } renderPlayerControls() { if (this.state.areControlsVisible) { return ( {this.state.paused && } {!this.state.paused && } {this.state.fullscreenMode && } {!this.state.fullscreenMode && } {this.formatTime(this.state.currentTime)} {this.formatTime(this.state.duration)} ); } return null; } render() { const { fileInfo, thumbnail, style, fullScreenStyle } = this.props; const flexCompleted = this.getCurrentTimePercentage() * 100; const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100; return (