Use Play as button text on the file page for audio/video #190
3 changed files with 99 additions and 88 deletions
|
@ -7,14 +7,14 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
const { costInfo, fetchCostInfo, uri } = this.props;
|
const { costInfo, fetchCostInfo, uri } = this.props;
|
||||||
if (costInfo === undefined) {
|
if (costInfo === undefined) {
|
||||||
fetchCostInfo(uri);
|
fetchCostInfo(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
//this.checkAvailability(nextProps.uri);
|
//this.checkAvailability(nextProps.uri);
|
||||||
this.restartDownload(nextProps);
|
this.restartDownload(nextProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
restartDownload(props) {
|
restartDownload(props) {
|
||||||
const { downloading, fileInfo, uri, restartDownload } = props;
|
const { downloading, fileInfo, uri, restartDownload } = props;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
restartDownload(uri, fileInfo.outpoint);
|
restartDownload(uri, fileInfo.outpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
fileInfo,
|
fileInfo,
|
||||||
|
@ -36,6 +36,8 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
uri,
|
uri,
|
||||||
purchaseUri,
|
purchaseUri,
|
||||||
costInfo,
|
costInfo,
|
||||||
|
isPlayable,
|
||||||
|
onPlay,
|
||||||
loading,
|
loading,
|
||||||
doPause,
|
doPause,
|
||||||
style,
|
style,
|
||||||
|
@ -46,7 +48,7 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
const progress =
|
const progress =
|
||||||
fileInfo && fileInfo.written_bytes ? fileInfo.written_bytes / fileInfo.total_bytes * 100 : 0,
|
fileInfo && fileInfo.written_bytes ? fileInfo.written_bytes / fileInfo.total_bytes * 100 : 0,
|
||||||
label = fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...';
|
label = fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[style, fileDownloadButtonStyle.container]}>
|
<View style={[style, fileDownloadButtonStyle.container]}>
|
||||||
<View style={{ width: `${progress}%`, backgroundColor: '#ff0000', position: 'absolute', left: 0, top: 0 }}></View>
|
<View style={{ width: `${progress}%`, backgroundColor: '#ff0000', position: 'absolute', left: 0, top: 0 }}></View>
|
||||||
|
@ -67,8 +69,11 @@ class FileDownloadButton extends React.PureComponent {
|
||||||
NativeModules.Mixpanel.track('Purchase Uri', { Uri: uri });
|
NativeModules.Mixpanel.track('Purchase Uri', { Uri: uri });
|
||||||
}
|
}
|
||||||
purchaseUri(uri);
|
purchaseUri(uri);
|
||||||
|
if (isPlayable && onPlay) {
|
||||||
|
this.props.onPlay();
|
||||||
|
}
|
||||||
}}>
|
}}>
|
||||||
<Text style={fileDownloadButtonStyle.text}>Download</Text>
|
<Text style={fileDownloadButtonStyle.text}>{isPlayable ? 'Play' : 'Download'}</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
} else if (fileInfo && fileInfo.download_path) {
|
} else if (fileInfo && fileInfo.download_path) {
|
||||||
|
|
|
@ -11,21 +11,21 @@ import {
|
||||||
import Video from 'react-native-video';
|
import Video from 'react-native-video';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||||
import FileItemMedia from '../fileItemMedia';
|
import FileItemMedia from '../fileItemMedia';
|
||||||
import mediaPlayerStyle from '../../styles/mediaPlayer';
|
import mediaPlayerStyle from '../../styles/mediaPlayer';
|
||||||
|
|
||||||
class MediaPlayer extends React.PureComponent {
|
class MediaPlayer extends React.PureComponent {
|
||||||
static ControlsTimeout = 3000;
|
static ControlsTimeout = 3000;
|
||||||
|
|
||||||
seekResponder = null;
|
seekResponder = null;
|
||||||
|
|
||||||
seekerWidth = 0;
|
seekerWidth = 0;
|
||||||
|
|
||||||
trackingOffset = 0;
|
trackingOffset = 0;
|
||||||
|
|
||||||
tracking = null;
|
tracking = null;
|
||||||
|
|
||||||
video = null;
|
video = null;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -35,7 +35,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
resizeMode: 'stretch',
|
resizeMode: 'stretch',
|
||||||
duration: 0.0,
|
duration: 0.0,
|
||||||
currentTime: 0.0,
|
currentTime: 0.0,
|
||||||
paused: true,
|
paused: !props.autoPlay,
|
||||||
fullscreenMode: false,
|
fullscreenMode: false,
|
||||||
areControlsVisible: true,
|
areControlsVisible: true,
|
||||||
controlsTimeout: -1,
|
controlsTimeout: -1,
|
||||||
|
@ -44,51 +44,51 @@ class MediaPlayer extends React.PureComponent {
|
||||||
firstPlay: true
|
firstPlay: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
formatTime(time) {
|
formatTime(time) {
|
||||||
let str = '';
|
let str = '';
|
||||||
let minutes = 0, hours = 0, seconds = parseInt(time, 10);
|
let minutes = 0, hours = 0, seconds = parseInt(time, 10);
|
||||||
if (seconds > 60) {
|
if (seconds > 60) {
|
||||||
minutes = parseInt(seconds / 60, 10);
|
minutes = parseInt(seconds / 60, 10);
|
||||||
seconds = seconds % 60;
|
seconds = seconds % 60;
|
||||||
|
|
||||||
if (minutes > 60) {
|
if (minutes > 60) {
|
||||||
hours = parseInt(minutes / 60, 10);
|
hours = parseInt(minutes / 60, 10);
|
||||||
minutes = minutes % 60;
|
minutes = minutes % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = (hours > 0 ? this.pad(hours) + ':' : '') + this.pad(minutes) + ':' + this.pad(seconds);
|
str = (hours > 0 ? this.pad(hours) + ':' : '') + this.pad(minutes) + ':' + this.pad(seconds);
|
||||||
} else {
|
} else {
|
||||||
str = '00:' + this.pad(seconds);
|
str = '00:' + this.pad(seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
pad(value) {
|
pad(value) {
|
||||||
if (value < 10) {
|
if (value < 10) {
|
||||||
return '0' + String(value);
|
return '0' + String(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad = (data) => {
|
onLoad = (data) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
duration: data.duration
|
duration: data.duration
|
||||||
});
|
});
|
||||||
if (this.props.onMediaLoaded) {
|
if (this.props.onMediaLoaded) {
|
||||||
this.props.onMediaLoaded();
|
this.props.onMediaLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onProgress = (data) => {
|
onProgress = (data) => {
|
||||||
this.setState({ currentTime: data.currentTime });
|
this.setState({ currentTime: data.currentTime });
|
||||||
|
|
||||||
if (!this.state.seeking) {
|
if (!this.state.seeking) {
|
||||||
this.setSeekerPosition(this.calculateSeekerPosition());
|
this.setSeekerPosition(this.calculateSeekerPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state.firstPlay) {
|
if (this.state.firstPlay) {
|
||||||
if (NativeModules.Mixpanel) {
|
if (NativeModules.Mixpanel) {
|
||||||
const { uri } = this.props;
|
const { uri } = this.props;
|
||||||
|
@ -98,13 +98,13 @@ class MediaPlayer extends React.PureComponent {
|
||||||
this.hidePlayerControls();
|
this.hidePlayerControls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearControlsTimeout = () => {
|
clearControlsTimeout = () => {
|
||||||
if (this.state.controlsTimeout > -1) {
|
if (this.state.controlsTimeout > -1) {
|
||||||
clearTimeout(this.state.controlsTimeout)
|
clearTimeout(this.state.controlsTimeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showPlayerControls = () => {
|
showPlayerControls = () => {
|
||||||
this.clearControlsTimeout();
|
this.clearControlsTimeout();
|
||||||
if (!this.state.areControlsVisible) {
|
if (!this.state.areControlsVisible) {
|
||||||
|
@ -112,7 +112,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
this.hidePlayerControls();
|
this.hidePlayerControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
hidePlayerControls() {
|
hidePlayerControls() {
|
||||||
const player = this;
|
const player = this;
|
||||||
let timeout = setTimeout(() => {
|
let timeout = setTimeout(() => {
|
||||||
|
@ -120,12 +120,12 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}, MediaPlayer.ControlsTimeout);
|
}, MediaPlayer.ControlsTimeout);
|
||||||
player.setState({ controlsTimeout: timeout });
|
player.setState({ controlsTimeout: timeout });
|
||||||
}
|
}
|
||||||
|
|
||||||
togglePlay = () => {
|
togglePlay = () => {
|
||||||
this.showPlayerControls();
|
this.showPlayerControls();
|
||||||
this.setState({ paused: !this.state.paused });
|
this.setState({ paused: !this.state.paused });
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleFullscreenMode = () => {
|
toggleFullscreenMode = () => {
|
||||||
this.showPlayerControls();
|
this.showPlayerControls();
|
||||||
const { onFullscreenToggled } = this.props;
|
const { onFullscreenToggled } = this.props;
|
||||||
|
@ -136,12 +136,12 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnd = () => {
|
onEnd = () => {
|
||||||
this.setState({ paused: true });
|
this.setState({ paused: true });
|
||||||
this.video.seek(0);
|
this.video.seek(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSeekerPosition(position = 0) {
|
setSeekerPosition(position = 0) {
|
||||||
position = this.checkSeekerPosition(position);
|
position = this.checkSeekerPosition(position);
|
||||||
this.setState({ seekerPosition: position });
|
this.setState({ seekerPosition: position });
|
||||||
|
@ -149,7 +149,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
this.setState({ seekerOffset: position });
|
this.setState({ seekerOffset: position });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkSeekerPosition(val = 0) {
|
checkSeekerPosition(val = 0) {
|
||||||
const offset = this.getTrackingOffset();
|
const offset = this.getTrackingOffset();
|
||||||
if (val < offset) {
|
if (val < offset) {
|
||||||
|
@ -157,10 +157,10 @@ class MediaPlayer extends React.PureComponent {
|
||||||
} else if (val >= (offset + this.seekerWidth)) {
|
} else if (val >= (offset + this.seekerWidth)) {
|
||||||
return offset + this.seekerWidth;
|
return offset + this.seekerWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
seekTo(time = 0) {
|
seekTo(time = 0) {
|
||||||
if (time > this.state.duration) {
|
if (time > this.state.duration) {
|
||||||
return;
|
return;
|
||||||
|
@ -168,22 +168,22 @@ class MediaPlayer extends React.PureComponent {
|
||||||
this.video.seek(time);
|
this.video.seek(time);
|
||||||
this.setState({ currentTime: time });
|
this.setState({ currentTime: time });
|
||||||
}
|
}
|
||||||
|
|
||||||
initSeeker() {
|
initSeeker() {
|
||||||
this.seekResponder = PanResponder.create({
|
this.seekResponder = PanResponder.create({
|
||||||
onStartShouldSetPanResponder: (evt, gestureState) => true,
|
onStartShouldSetPanResponder: (evt, gestureState) => true,
|
||||||
onMoveShouldSetPanResponder: (evt, gestureState) => true,
|
onMoveShouldSetPanResponder: (evt, gestureState) => true,
|
||||||
|
|
||||||
onPanResponderGrant: (evt, gestureState) => {
|
onPanResponderGrant: (evt, gestureState) => {
|
||||||
this.clearControlsTimeout();
|
this.clearControlsTimeout();
|
||||||
this.setState({ seeking: true });
|
this.setState({ seeking: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
onPanResponderMove: (evt, gestureState) => {
|
onPanResponderMove: (evt, gestureState) => {
|
||||||
const position = this.state.seekerOffset + gestureState.dx;
|
const position = this.state.seekerOffset + gestureState.dx;
|
||||||
this.setSeekerPosition(position);
|
this.setSeekerPosition(position);
|
||||||
},
|
},
|
||||||
|
|
||||||
onPanResponderRelease: (evt, gestureState) => {
|
onPanResponderRelease: (evt, gestureState) => {
|
||||||
const time = this.getCurrentTimeForSeekerPosition();
|
const time = this.getCurrentTimeForSeekerPosition();
|
||||||
if (time >= this.state.duration) {
|
if (time >= this.state.duration) {
|
||||||
|
@ -197,37 +197,37 @@ class MediaPlayer extends React.PureComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getTrackingOffset() {
|
getTrackingOffset() {
|
||||||
return this.state.fullscreenMode ? this.trackingOffset : 0;
|
return this.state.fullscreenMode ? this.trackingOffset : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentTimeForSeekerPosition() {
|
getCurrentTimeForSeekerPosition() {
|
||||||
return this.state.duration * (this.state.seekerPosition / this.seekerWidth);
|
return this.state.duration * (this.state.seekerPosition / this.seekerWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateSeekerPosition() {
|
calculateSeekerPosition() {
|
||||||
if (this.state.fullscreenMode) {
|
if (this.state.fullscreenMode) {
|
||||||
return this.getTrackingOffset() + (this.seekerWidth * this.getCurrentTimePercentage());
|
return this.getTrackingOffset() + (this.seekerWidth * this.getCurrentTimePercentage());
|
||||||
}
|
}
|
||||||
return this.seekerWidth * this.getCurrentTimePercentage();
|
return this.seekerWidth * this.getCurrentTimePercentage();
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentTimePercentage() {
|
getCurrentTimePercentage() {
|
||||||
if (this.state.currentTime > 0) {
|
if (this.state.currentTime > 0) {
|
||||||
return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
|
return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
this.initSeeker();
|
this.initSeeker();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.clearControlsTimeout();
|
this.clearControlsTimeout();
|
||||||
this.setState({ paused: true, fullscreenMode: false });
|
this.setState({ paused: true, fullscreenMode: false });
|
||||||
|
@ -236,7 +236,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
onFullscreenToggled(false);
|
onFullscreenToggled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderPlayerControls() {
|
renderPlayerControls() {
|
||||||
if (this.state.areControlsVisible) {
|
if (this.state.areControlsVisible) {
|
||||||
return (
|
return (
|
||||||
|
@ -246,18 +246,18 @@ class MediaPlayer extends React.PureComponent {
|
||||||
{this.state.paused && <Icon name="play" size={32} color="#ffffff" />}
|
{this.state.paused && <Icon name="play" size={32} color="#ffffff" />}
|
||||||
{!this.state.paused && <Icon name="pause" size={32} color="#ffffff" />}
|
{!this.state.paused && <Icon name="pause" size={32} color="#ffffff" />}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<TouchableOpacity style={mediaPlayerStyle.toggleFullscreenButton} onPress={this.toggleFullscreenMode}>
|
<TouchableOpacity style={mediaPlayerStyle.toggleFullscreenButton} onPress={this.toggleFullscreenMode}>
|
||||||
{this.state.fullscreenMode && <Icon name="compress" size={16} color="#ffffff" />}
|
{this.state.fullscreenMode && <Icon name="compress" size={16} color="#ffffff" />}
|
||||||
{!this.state.fullscreenMode && <Icon name="expand" size={16} color="#ffffff" />}
|
{!this.state.fullscreenMode && <Icon name="expand" size={16} color="#ffffff" />}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<Text style={mediaPlayerStyle.elapsedDuration}>{this.formatTime(this.state.currentTime)}</Text>
|
<Text style={mediaPlayerStyle.elapsedDuration}>{this.formatTime(this.state.currentTime)}</Text>
|
||||||
<Text style={mediaPlayerStyle.totalDuration}>{this.formatTime(this.state.duration)}</Text>
|
<Text style={mediaPlayerStyle.totalDuration}>{this.formatTime(this.state.duration)}</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,10 +273,10 @@ class MediaPlayer extends React.PureComponent {
|
||||||
styles.push(style);
|
styles.push(style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const trackingStyle = [mediaPlayerStyle.trackingControls, this.state.fullscreenMode ?
|
const trackingStyle = [mediaPlayerStyle.trackingControls, this.state.fullscreenMode ?
|
||||||
mediaPlayerStyle.fullscreenTrackingControls : mediaPlayerStyle.containedTrackingControls];
|
mediaPlayerStyle.fullscreenTrackingControls : mediaPlayerStyle.containedTrackingControls];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles}>
|
<View style={styles}>
|
||||||
<Video source={{ uri: 'file:///' + fileInfo.download_path }}
|
<Video source={{ uri: 'file:///' + fileInfo.download_path }}
|
||||||
|
@ -291,11 +291,11 @@ class MediaPlayer extends React.PureComponent {
|
||||||
onProgress={this.onProgress}
|
onProgress={this.onProgress}
|
||||||
onEnd={this.onEnd}
|
onEnd={this.onEnd}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TouchableOpacity style={mediaPlayerStyle.playerControls} onPress={this.showPlayerControls}>
|
<TouchableOpacity style={mediaPlayerStyle.playerControls} onPress={this.showPlayerControls}>
|
||||||
{this.renderPlayerControls()}
|
{this.renderPlayerControls()}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
{(!this.state.fullscreenMode || (this.state.fullscreenMode && this.state.areControlsVisible)) &&
|
{(!this.state.fullscreenMode || (this.state.fullscreenMode && this.state.areControlsVisible)) &&
|
||||||
<View style={trackingStyle} onLayout={(evt) => {
|
<View style={trackingStyle} onLayout={(evt) => {
|
||||||
this.trackingOffset = evt.nativeEvent.layout.x;
|
this.trackingOffset = evt.nativeEvent.layout.x;
|
||||||
|
@ -306,7 +306,7 @@ class MediaPlayer extends React.PureComponent {
|
||||||
<View style={[mediaPlayerStyle.innerProgressRemaining, { flex: flexRemaining }]} />
|
<View style={[mediaPlayerStyle.innerProgressRemaining, { flex: flexRemaining }]} />
|
||||||
</View>
|
</View>
|
||||||
</View>}
|
</View>}
|
||||||
|
|
||||||
{this.state.areControlsVisible &&
|
{this.state.areControlsVisible &&
|
||||||
<View style={[mediaPlayerStyle.seekerHandle, { left: this.state.seekerPosition }]} { ...this.seekResponder.panHandlers }>
|
<View style={[mediaPlayerStyle.seekerHandle, { left: this.state.seekerPosition }]} { ...this.seekResponder.panHandlers }>
|
||||||
<View style={this.state.seeking ? mediaPlayerStyle.bigSeekerCircle : mediaPlayerStyle.seekerCircle} />
|
<View style={this.state.seeking ? mediaPlayerStyle.bigSeekerCircle : mediaPlayerStyle.seekerCircle} />
|
||||||
|
|
|
@ -30,25 +30,26 @@ class FilePage extends React.PureComponent {
|
||||||
static navigationOptions = {
|
static navigationOptions = {
|
||||||
title: ''
|
title: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
mediaLoaded: false,
|
mediaLoaded: false,
|
||||||
|
autoplayMedia: false,
|
||||||
fullscreenMode: false,
|
fullscreenMode: false,
|
||||||
I suppose that would be a different setting entirely. This state variable is related to the action that should be performed when the user clicks on the "Play" (download) button on the file page, instead of the usual "Download". I suppose that would be a different setting entirely. This state variable is related to the action that should be performed when the user clicks on the "Play" (download) button on the file page, instead of the usual "Download".
Ah I gotcha. Ah I gotcha.
|
|||||||
showImageViewer: false,
|
showImageViewer: false,
|
||||||
showWebView: false,
|
showWebView: false,
|
||||||
imageUrls: null
|
imageUrls: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
StatusBar.setHidden(false);
|
StatusBar.setHidden(false);
|
||||||
|
|
||||||
const { isResolvingUri, resolveUri, navigation } = this.props;
|
const { isResolvingUri, resolveUri, navigation } = this.props;
|
||||||
const { uri } = navigation.state.params;
|
const { uri } = navigation.state.params;
|
||||||
if (!isResolvingUri) resolveUri(uri);
|
if (!isResolvingUri) resolveUri(uri);
|
||||||
|
|
||||||
this.fetchFileInfo(this.props);
|
this.fetchFileInfo(this.props);
|
||||||
this.fetchCostInfo(this.props);
|
this.fetchCostInfo(this.props);
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@ class FilePage extends React.PureComponent {
|
||||||
props.fetchCostInfo(props.navigation.state.params.uri);
|
props.fetchCostInfo(props.navigation.state.params.uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFullscreenToggle = (mode) => {
|
handleFullscreenToggle = (mode) => {
|
||||||
this.setState({ fullscreenMode: mode });
|
this.setState({ fullscreenMode: mode });
|
||||||
StatusBar.setHidden(mode);
|
StatusBar.setHidden(mode);
|
||||||
|
@ -91,10 +92,10 @@ class FilePage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeletePressed = () => {
|
onDeletePressed = () => {
|
||||||
const { deleteFile, fileInfo } = this.props;
|
const { deleteFile, fileInfo } = this.props;
|
||||||
|
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'Delete file',
|
'Delete file',
|
||||||
'Are you sure you want to remove this file from your device?',
|
'Are you sure you want to remove this file from your device?',
|
||||||
|
@ -105,10 +106,10 @@ class FilePage extends React.PureComponent {
|
||||||
{ cancelable: true }
|
{ cancelable: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onStopDownloadPressed = () => {
|
onStopDownloadPressed = () => {
|
||||||
const { deleteFile, stopDownload, fileInfo, navigation } = this.props;
|
const { deleteFile, stopDownload, fileInfo, navigation } = this.props;
|
||||||
|
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'Stop download',
|
'Stop download',
|
||||||
'Are you sure you want to stop downloading this file?',
|
'Are you sure you want to stop downloading this file?',
|
||||||
|
@ -119,21 +120,21 @@ class FilePage extends React.PureComponent {
|
||||||
{ cancelable: true }
|
{ cancelable: true }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
StatusBar.setHidden(false);
|
StatusBar.setHidden(false);
|
||||||
if (NativeModules.ScreenOrientation) {
|
if (NativeModules.ScreenOrientation) {
|
||||||
NativeModules.ScreenOrientation.unlockOrientation();
|
NativeModules.ScreenOrientation.unlockOrientation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localUriForFileInfo = (fileInfo) => {
|
localUriForFileInfo = (fileInfo) => {
|
||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return 'file:///' + fileInfo.download_path;
|
return 'file:///' + fileInfo.download_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
linkify = (text) => {
|
linkify = (text) => {
|
||||||
let linkifiedContent = [];
|
let linkifiedContent = [];
|
||||||
let lines = text.split(/\n/g);
|
let lines = text.split(/\n/g);
|
||||||
|
@ -142,7 +143,7 @@ class FilePage extends React.PureComponent {
|
||||||
let lineContent = tokens.length === 0 ? '' : tokens.map((token, j) => {
|
let lineContent = tokens.length === 0 ? '' : tokens.map((token, j) => {
|
||||||
let hasSpace = j !== (tokens.length - 1);
|
let hasSpace = j !== (tokens.length - 1);
|
||||||
let space = hasSpace ? ' ' : '';
|
let space = hasSpace ? ' ' : '';
|
||||||
|
|
||||||
if (token.match(/^(lbry|https?):\/\//g)) {
|
if (token.match(/^(lbry|https?):\/\//g)) {
|
||||||
return (
|
return (
|
||||||
<Link key={j}
|
<Link key={j}
|
||||||
|
@ -154,14 +155,14 @@ class FilePage extends React.PureComponent {
|
||||||
return token + space;
|
return token + space;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
lineContent.push("\n");
|
lineContent.push("\n");
|
||||||
return (<Text key={i}>{lineContent}</Text>);
|
return (<Text key={i}>{lineContent}</Text>);
|
||||||
});
|
});
|
||||||
|
|
||||||
return linkifiedContent;
|
return linkifiedContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
claim,
|
claim,
|
||||||
|
@ -175,12 +176,12 @@ class FilePage extends React.PureComponent {
|
||||||
navigation
|
navigation
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { uri } = navigation.state.params;
|
const { uri } = navigation.state.params;
|
||||||
|
|
||||||
let innerContent = null;
|
let innerContent = null;
|
||||||
if ((isResolvingUri && !claim) || !claim) {
|
if ((isResolvingUri && !claim) || !claim) {
|
||||||
innerContent = (
|
innerContent = (
|
||||||
<View style={filePageStyle.container}>
|
<View style={filePageStyle.container}>
|
||||||
{isResolvingUri &&
|
{isResolvingUri &&
|
||||||
<View style={filePageStyle.busyContainer}>
|
<View style={filePageStyle.busyContainer}>
|
||||||
<ActivityIndicator size="large" color={Colors.LbryGreen} />
|
<ActivityIndicator size="large" color={Colors.LbryGreen} />
|
||||||
<Text style={filePageStyle.infoText}>Loading decentralized data...</Text>
|
<Text style={filePageStyle.infoText}>Loading decentralized data...</Text>
|
||||||
|
@ -198,7 +199,7 @@ class FilePage extends React.PureComponent {
|
||||||
<ChannelPage uri={uri} navigation={navigation} />
|
<ChannelPage uri={uri} navigation={navigation} />
|
||||||
);
|
);
|
||||||
} else if (claim) {
|
} else if (claim) {
|
||||||
const completed = fileInfo && fileInfo.completed;
|
const completed = fileInfo && fileInfo.completed;
|
||||||
const title = metadata.title;
|
const title = metadata.title;
|
||||||
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
|
||||||
const description = metadata.description ? metadata.description : null;
|
const description = metadata.description ? metadata.description : null;
|
||||||
|
@ -209,18 +210,18 @@ class FilePage extends React.PureComponent {
|
||||||
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
||||||
const channelClaimId =
|
const channelClaimId =
|
||||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||||
|
|
||||||
const playerStyle = [filePageStyle.player, this.state.fullscreenMode ?
|
const playerStyle = [filePageStyle.player, this.state.fullscreenMode ?
|
||||||
filePageStyle.fullscreenPlayer : filePageStyle.containedPlayer];
|
filePageStyle.fullscreenPlayer : filePageStyle.containedPlayer];
|
||||||
const playerBgStyle = [filePageStyle.playerBackground, this.state.fullscreenMode ?
|
const playerBgStyle = [filePageStyle.playerBackground, this.state.fullscreenMode ?
|
||||||
filePageStyle.fullscreenPlayerBackground : filePageStyle.containedPlayerBackground];
|
filePageStyle.fullscreenPlayerBackground : filePageStyle.containedPlayerBackground];
|
||||||
// at least 2MB (or the full download) before media can be loaded
|
// at least 2MB (or the full download) before media can be loaded
|
||||||
const canLoadMedia = fileInfo &&
|
const canLoadMedia = fileInfo &&
|
||||||
(fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes == fileInfo.total_bytes); // 2MB = 1024*1024*2
|
(fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes == fileInfo.total_bytes); // 2MB = 1024*1024*2
|
||||||
const canOpen = (mediaType === 'image' || mediaType === 'text') && completed;
|
const canOpen = (mediaType === 'image' || mediaType === 'text') && completed;
|
||||||
const isWebViewable = mediaType === 'text';
|
const isWebViewable = mediaType === 'text';
|
||||||
const localFileUri = this.localUriForFileInfo(fileInfo);
|
const localFileUri = this.localUriForFileInfo(fileInfo);
|
||||||
|
|
||||||
const openFile = () => {
|
const openFile = () => {
|
||||||
if (mediaType === 'image') {
|
if (mediaType === 'image') {
|
||||||
// use image viewer
|
// use image viewer
|
||||||
|
@ -243,28 +244,33 @@ class FilePage extends React.PureComponent {
|
||||||
<View style={filePageStyle.pageContainer}>
|
<View style={filePageStyle.pageContainer}>
|
||||||
{this.state.showWebView && isWebViewable && <WebView source={{ uri: localFileUri }}
|
{this.state.showWebView && isWebViewable && <WebView source={{ uri: localFileUri }}
|
||||||
style={filePageStyle.viewer} />}
|
style={filePageStyle.viewer} />}
|
||||||
|
|
||||||
{this.state.showImageViewer && <ImageViewer style={StyleSheet.flatten(filePageStyle.viewer)}
|
{this.state.showImageViewer && <ImageViewer style={StyleSheet.flatten(filePageStyle.viewer)}
|
||||||
imageUrls={this.state.imageUrls}
|
imageUrls={this.state.imageUrls}
|
||||||
renderIndicator={() => null} />}
|
renderIndicator={() => null} />}
|
||||||
|
|
||||||
{!this.state.showWebView && (
|
{!this.state.showWebView && (
|
||||||
<View style={filePageStyle.innerPageContainer}>
|
<View style={filePageStyle.innerPageContainer}>
|
||||||
<View style={filePageStyle.mediaContainer}>
|
<View style={filePageStyle.mediaContainer}>
|
||||||
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia))) &&
|
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia))) &&
|
||||||
<FileItemMedia style={filePageStyle.thumbnail} title={title} thumbnail={metadata.thumbnail} />}
|
<FileItemMedia style={filePageStyle.thumbnail} title={title} thumbnail={metadata.thumbnail} />}
|
||||||
{(canOpen || (isPlayable && !this.state.mediaLoaded)) && <ActivityIndicator size="large" color={Colors.LbryGreen} style={filePageStyle.loading} />}
|
{(canOpen || (isPlayable && !this.state.mediaLoaded)) && <ActivityIndicator size="large" color={Colors.LbryGreen} style={filePageStyle.loading} />}
|
||||||
{((isPlayable && !completed && !canLoadMedia) || !completed || canOpen) &&
|
{((isPlayable && !completed && !canLoadMedia) || !completed || canOpen) &&
|
||||||
<FileDownloadButton uri={uri} style={filePageStyle.downloadButton} openFile={openFile} />}
|
<FileDownloadButton uri={uri}
|
||||||
|
style={filePageStyle.downloadButton}
|
||||||
|
openFile={openFile}
|
||||||
|
isPlayable={isPlayable}
|
||||||
|
onPlay={() => this.setState({ autoPlayMedia: true })} />}
|
||||||
{!fileInfo && <FilePrice uri={uri} style={filePageStyle.filePriceContainer} textStyle={filePageStyle.filePriceText} />}
|
{!fileInfo && <FilePrice uri={uri} style={filePageStyle.filePriceContainer} textStyle={filePageStyle.filePriceText} />}
|
||||||
</View>
|
</View>
|
||||||
{canLoadMedia && <View style={playerBgStyle} />}
|
{canLoadMedia && <View style={playerBgStyle} />}
|
||||||
{canLoadMedia && <MediaPlayer fileInfo={fileInfo}
|
{canLoadMedia && <MediaPlayer fileInfo={fileInfo}
|
||||||
uri={uri}
|
uri={uri}
|
||||||
style={playerStyle}
|
style={playerStyle}
|
||||||
onFullscreenToggled={this.handleFullscreenToggle}
|
autoPlay={this.state.autoPlayMedia}
|
||||||
onMediaLoaded={() => { this.setState({ mediaLoaded: true }); }}/>}
|
onFullscreenToggled={this.handleFullscreenToggle}
|
||||||
|
onMediaLoaded={() => { this.setState({ mediaLoaded: true }); }}/>}
|
||||||
|
|
||||||
{ showActions &&
|
{ showActions &&
|
||||||
<View style={filePageStyle.actions}>
|
<View style={filePageStyle.actions}>
|
||||||
{completed && <Button color="red" title="Delete" onPress={this.onDeletePressed} />}
|
{completed && <Button color="red" title="Delete" onPress={this.onDeletePressed} />}
|
||||||
|
@ -290,7 +296,7 @@ class FilePage extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return innerContent;
|
return innerContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue
Should autoplay be a separate setting so the value is saved if they leave the page?