diff --git a/app/src/component/fileDownloadButton/view.js b/app/src/component/fileDownloadButton/view.js
index 883d7b78..c7901fe1 100644
--- a/app/src/component/fileDownloadButton/view.js
+++ b/app/src/component/fileDownloadButton/view.js
@@ -7,14 +7,14 @@ class FileDownloadButton extends React.PureComponent {
const { costInfo, fetchCostInfo, uri } = this.props;
if (costInfo === undefined) {
fetchCostInfo(uri);
- }
+ }
}
-
+
componentWillReceiveProps(nextProps) {
//this.checkAvailability(nextProps.uri);
this.restartDownload(nextProps);
}
-
+
restartDownload(props) {
const { downloading, fileInfo, uri, restartDownload } = props;
@@ -28,7 +28,7 @@ class FileDownloadButton extends React.PureComponent {
restartDownload(uri, fileInfo.outpoint);
}
}
-
+
render() {
const {
fileInfo,
@@ -36,6 +36,8 @@ class FileDownloadButton extends React.PureComponent {
uri,
purchaseUri,
costInfo,
+ isPlayable,
+ onPlay,
loading,
doPause,
style,
@@ -46,7 +48,7 @@ class FileDownloadButton extends React.PureComponent {
const progress =
fileInfo && fileInfo.written_bytes ? fileInfo.written_bytes / fileInfo.total_bytes * 100 : 0,
label = fileInfo ? progress.toFixed(0) + '% complete' : 'Connecting...';
-
+
return (
@@ -67,8 +69,11 @@ class FileDownloadButton extends React.PureComponent {
NativeModules.Mixpanel.track('Purchase Uri', { Uri: uri });
}
purchaseUri(uri);
+ if (isPlayable && onPlay) {
+ this.props.onPlay();
+ }
}}>
- Download
+ {isPlayable ? 'Play' : 'Download'}
);
} else if (fileInfo && fileInfo.download_path) {
diff --git a/app/src/component/mediaPlayer/view.js b/app/src/component/mediaPlayer/view.js
index 2b74661c..5e13674b 100644
--- a/app/src/component/mediaPlayer/view.js
+++ b/app/src/component/mediaPlayer/view.js
@@ -11,21 +11,21 @@ import {
import Video from 'react-native-video';
import Icon from 'react-native-vector-icons/FontAwesome';
import FileItemMedia from '../fileItemMedia';
-import mediaPlayerStyle from '../../styles/mediaPlayer';
+import mediaPlayerStyle from '../../styles/mediaPlayer';
class MediaPlayer extends React.PureComponent {
static ControlsTimeout = 3000;
-
+
seekResponder = null;
-
+
seekerWidth = 0;
-
+
trackingOffset = 0;
-
+
tracking = null;
-
+
video = null;
-
+
constructor(props) {
super(props);
this.state = {
@@ -35,7 +35,7 @@ class MediaPlayer extends React.PureComponent {
resizeMode: 'stretch',
duration: 0.0,
currentTime: 0.0,
- paused: true,
+ paused: !props.autoPlay,
fullscreenMode: false,
areControlsVisible: true,
controlsTimeout: -1,
@@ -44,51 +44,51 @@ class MediaPlayer extends React.PureComponent {
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();
+ 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;
@@ -98,13 +98,13 @@ class MediaPlayer extends React.PureComponent {
this.hidePlayerControls();
}
}
-
+
clearControlsTimeout = () => {
if (this.state.controlsTimeout > -1) {
clearTimeout(this.state.controlsTimeout)
}
}
-
+
showPlayerControls = () => {
this.clearControlsTimeout();
if (!this.state.areControlsVisible) {
@@ -112,7 +112,7 @@ class MediaPlayer extends React.PureComponent {
}
this.hidePlayerControls();
}
-
+
hidePlayerControls() {
const player = this;
let timeout = setTimeout(() => {
@@ -120,12 +120,12 @@ class MediaPlayer extends React.PureComponent {
}, MediaPlayer.ControlsTimeout);
player.setState({ controlsTimeout: timeout });
}
-
+
togglePlay = () => {
this.showPlayerControls();
this.setState({ paused: !this.state.paused });
}
-
+
toggleFullscreenMode = () => {
this.showPlayerControls();
const { onFullscreenToggled } = this.props;
@@ -136,12 +136,12 @@ class MediaPlayer extends React.PureComponent {
}
});
}
-
+
onEnd = () => {
this.setState({ paused: true });
this.video.seek(0);
}
-
+
setSeekerPosition(position = 0) {
position = this.checkSeekerPosition(position);
this.setState({ seekerPosition: position });
@@ -149,7 +149,7 @@ class MediaPlayer extends React.PureComponent {
this.setState({ seekerOffset: position });
}
}
-
+
checkSeekerPosition(val = 0) {
const offset = this.getTrackingOffset();
if (val < offset) {
@@ -157,10 +157,10 @@ class MediaPlayer extends React.PureComponent {
} else if (val >= (offset + this.seekerWidth)) {
return offset + this.seekerWidth;
}
-
+
return val;
}
-
+
seekTo(time = 0) {
if (time > this.state.duration) {
return;
@@ -168,22 +168,22 @@ class MediaPlayer extends React.PureComponent {
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) {
@@ -197,37 +197,37 @@ class MediaPlayer extends React.PureComponent {
}
});
}
-
+
getTrackingOffset() {
return this.state.fullscreenMode ? this.trackingOffset : 0;
}
-
+
getCurrentTimeForSeekerPosition() {
return this.state.duration * (this.state.seekerPosition / this.seekerWidth);
}
-
+
calculateSeekerPosition() {
if (this.state.fullscreenMode) {
return this.getTrackingOffset() + (this.seekerWidth * this.getCurrentTimePercentage());
}
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();
}
-
+
componentDidMount() {
-
+
}
-
+
componentWillUnmount() {
this.clearControlsTimeout();
this.setState({ paused: true, fullscreenMode: false });
@@ -236,7 +236,7 @@ class MediaPlayer extends React.PureComponent {
onFullscreenToggled(false);
}
}
-
+
renderPlayerControls() {
if (this.state.areControlsVisible) {
return (
@@ -246,18 +246,18 @@ class MediaPlayer extends React.PureComponent {
{this.state.paused && }
{!this.state.paused && }
-
+
{this.state.fullscreenMode && }
{!this.state.fullscreenMode && }
-
+
{this.formatTime(this.state.currentTime)}
{this.formatTime(this.state.duration)}
);
}
-
+
return null;
}
@@ -273,10 +273,10 @@ class MediaPlayer extends React.PureComponent {
styles.push(style);
}
}
-
+
const trackingStyle = [mediaPlayerStyle.trackingControls, this.state.fullscreenMode ?
mediaPlayerStyle.fullscreenTrackingControls : mediaPlayerStyle.containedTrackingControls];
-
+
return (
-
+
{this.renderPlayerControls()}
-
+
{(!this.state.fullscreenMode || (this.state.fullscreenMode && this.state.areControlsVisible)) &&
{
this.trackingOffset = evt.nativeEvent.layout.x;
@@ -306,7 +306,7 @@ class MediaPlayer extends React.PureComponent {
}
-
+
{this.state.areControlsVisible &&
diff --git a/app/src/page/file/view.js b/app/src/page/file/view.js
index d5dac95e..2ed49b98 100644
--- a/app/src/page/file/view.js
+++ b/app/src/page/file/view.js
@@ -30,25 +30,26 @@ class FilePage extends React.PureComponent {
static navigationOptions = {
title: ''
};
-
+
constructor(props) {
super(props);
this.state = {
mediaLoaded: false,
+ autoplayMedia: false,
fullscreenMode: false,
showImageViewer: false,
showWebView: false,
imageUrls: null
};
}
-
+
componentDidMount() {
StatusBar.setHidden(false);
-
+
const { isResolvingUri, resolveUri, navigation } = this.props;
const { uri } = navigation.state.params;
if (!isResolvingUri) resolveUri(uri);
-
+
this.fetchFileInfo(this.props);
this.fetchCostInfo(this.props);
@@ -78,7 +79,7 @@ class FilePage extends React.PureComponent {
props.fetchCostInfo(props.navigation.state.params.uri);
}
}
-
+
handleFullscreenToggle = (mode) => {
this.setState({ fullscreenMode: mode });
StatusBar.setHidden(mode);
@@ -91,10 +92,10 @@ class FilePage extends React.PureComponent {
}
}
}
-
+
onDeletePressed = () => {
const { deleteFile, fileInfo } = this.props;
-
+
Alert.alert(
'Delete file',
'Are you sure you want to remove this file from your device?',
@@ -105,10 +106,10 @@ class FilePage extends React.PureComponent {
{ cancelable: true }
);
}
-
+
onStopDownloadPressed = () => {
const { deleteFile, stopDownload, fileInfo, navigation } = this.props;
-
+
Alert.alert(
'Stop download',
'Are you sure you want to stop downloading this file?',
@@ -119,21 +120,21 @@ class FilePage extends React.PureComponent {
{ cancelable: true }
);
}
-
+
componentWillUnmount() {
StatusBar.setHidden(false);
if (NativeModules.ScreenOrientation) {
NativeModules.ScreenOrientation.unlockOrientation();
}
}
-
+
localUriForFileInfo = (fileInfo) => {
if (!fileInfo) {
return null;
}
return 'file:///' + fileInfo.download_path;
}
-
+
linkify = (text) => {
let linkifiedContent = [];
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 hasSpace = j !== (tokens.length - 1);
let space = hasSpace ? ' ' : '';
-
+
if (token.match(/^(lbry|https?):\/\//g)) {
return (
{lineContent});
});
-
+
return linkifiedContent;
}
-
+
render() {
const {
claim,
@@ -175,12 +176,12 @@ class FilePage extends React.PureComponent {
navigation
} = this.props;
const { uri } = navigation.state.params;
-
+
let innerContent = null;
if ((isResolvingUri && !claim) || !claim) {
innerContent = (
- {isResolvingUri &&
+ {isResolvingUri &&
Loading decentralized data...
@@ -198,7 +199,7 @@ class FilePage extends React.PureComponent {
);
} else if (claim) {
- const completed = fileInfo && fileInfo.completed;
+ const completed = fileInfo && fileInfo.completed;
const title = metadata.title;
const isRewardContent = rewardedContentClaimIds.includes(claim.claim_id);
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));
const channelClaimId =
value && value.publisherSignature && value.publisherSignature.certificateId;
-
+
const playerStyle = [filePageStyle.player, this.state.fullscreenMode ?
filePageStyle.fullscreenPlayer : filePageStyle.containedPlayer];
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
const canLoadMedia = fileInfo &&
(fileInfo.written_bytes >= 2097152 || fileInfo.written_bytes == fileInfo.total_bytes); // 2MB = 1024*1024*2
const canOpen = (mediaType === 'image' || mediaType === 'text') && completed;
const isWebViewable = mediaType === 'text';
const localFileUri = this.localUriForFileInfo(fileInfo);
-
+
const openFile = () => {
if (mediaType === 'image') {
// use image viewer
@@ -243,28 +244,33 @@ class FilePage extends React.PureComponent {
{this.state.showWebView && isWebViewable && }
-
+
{this.state.showImageViewer && null} />}
-
+
{!this.state.showWebView && (
-
+
{(canOpen || (!fileInfo || (isPlayable && !canLoadMedia))) &&
}
{(canOpen || (isPlayable && !this.state.mediaLoaded)) && }
{((isPlayable && !completed && !canLoadMedia) || !completed || canOpen) &&
- }
+ this.setState({ autoPlayMedia: true })} />}
{!fileInfo && }
{canLoadMedia && }
{canLoadMedia && { this.setState({ mediaLoaded: true }); }}/>}
-
+ uri={uri}
+ style={playerStyle}
+ autoPlay={this.state.autoPlayMedia}
+ onFullscreenToggled={this.handleFullscreenToggle}
+ onMediaLoaded={() => { this.setState({ mediaLoaded: true }); }}/>}
+
{ showActions &&
{completed && }
@@ -290,7 +296,7 @@ class FilePage extends React.PureComponent {
);
}
-
+
return innerContent;
}
}