Merge pull request #190 from lbryio/media-play-button
Use Play as button text on the file page for audio/video
This commit is contained in:
commit
a133f7d82d
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,
|
||||||
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…
Reference in a new issue