Save audio/video files (#564)
* add save file button for audio/video * set state for downloads initiated using the save file button * allow actions to be shown if there's a download_path in fileInfo * do not auto play downloaded media
This commit is contained in:
parent
a2c0851ac7
commit
044947d4ae
4 changed files with 44 additions and 11 deletions
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { normalizeURI, parseURI } from 'lbry-redux';
|
import { normalizeURI, parseURI } from 'lbry-redux';
|
||||||
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
|
import { NativeModules, Text, View, TouchableOpacity } from 'react-native';
|
||||||
import Button from '../button';
|
import Button from 'component/button';
|
||||||
import Colors from '../../styles/colors';
|
import Colors from 'styles/colors';
|
||||||
|
|
||||||
class SubscribeButton extends React.PureComponent {
|
class SubscribeButton extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
|
@ -11,7 +11,8 @@ class SubscribeButton extends React.PureComponent {
|
||||||
isSubscribed,
|
isSubscribed,
|
||||||
doChannelSubscribe,
|
doChannelSubscribe,
|
||||||
doChannelUnsubscribe,
|
doChannelUnsubscribe,
|
||||||
style
|
style,
|
||||||
|
hideText
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let styles = [];
|
let styles = [];
|
||||||
|
@ -35,7 +36,7 @@ class SubscribeButton extends React.PureComponent {
|
||||||
icon={isSubscribed ? "heart-broken" : "heart"}
|
icon={isSubscribed ? "heart-broken" : "heart"}
|
||||||
iconColor={iconColor}
|
iconColor={iconColor}
|
||||||
solid={isSubscribed ? false : true}
|
solid={isSubscribed ? false : true}
|
||||||
text={subscriptionLabel}
|
text={hideText ? null : subscriptionLabel}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
subscriptionHandler({
|
subscriptionHandler({
|
||||||
channelName: claimName,
|
channelName: claimName,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
doFetchFileInfo,
|
doFetchFileInfo,
|
||||||
|
doFileGet,
|
||||||
doPurchaseUri,
|
doPurchaseUri,
|
||||||
doDeletePurchasedUri,
|
doDeletePurchasedUri,
|
||||||
doResolveUri,
|
doResolveUri,
|
||||||
|
@ -70,6 +71,7 @@ const perform = dispatch => ({
|
||||||
},
|
},
|
||||||
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
fetchFileInfo: uri => dispatch(doFetchFileInfo(uri)),
|
||||||
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
||||||
|
fileGet: (uri, saveFile) => dispatch(doFileGet(uri, saveFile)),
|
||||||
notify: data => dispatch(doToast(data)),
|
notify: data => dispatch(doToast(data)),
|
||||||
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
popDrawerStack: () => dispatch(doPopDrawerStack()),
|
||||||
purchaseUri: (uri, costInfo, saveFile) => dispatch(doPurchaseUri(uri, costInfo, saveFile)),
|
purchaseUri: (uri, costInfo, saveFile) => dispatch(doPurchaseUri(uri, costInfo, saveFile)),
|
||||||
|
|
|
@ -63,6 +63,7 @@ class FilePage extends React.PureComponent {
|
||||||
downloadPressed: false,
|
downloadPressed: false,
|
||||||
fileViewLogged: false,
|
fileViewLogged: false,
|
||||||
fullscreenMode: false,
|
fullscreenMode: false,
|
||||||
|
fileGetStarted: false,
|
||||||
imageUrls: null,
|
imageUrls: null,
|
||||||
isLandscape: false,
|
isLandscape: false,
|
||||||
mediaLoaded: false,
|
mediaLoaded: false,
|
||||||
|
@ -150,7 +151,7 @@ class FilePage extends React.PureComponent {
|
||||||
|
|
||||||
const mediaType = Lbry.getMediaType(contentType);
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
if (prevPurchasedUris.length != purchasedUris.length && NativeModules.UtilityModule) {
|
if ((this.state.fileGetStarted || prevPurchasedUris.length !== purchasedUris.length) && NativeModules.UtilityModule) {
|
||||||
if (purchasedUris.includes(uri)) {
|
if (purchasedUris.includes(uri)) {
|
||||||
const { nout, txid } = claim;
|
const { nout, txid } = claim;
|
||||||
const outpoint = `${txid}:${nout}`;
|
const outpoint = `${txid}:${nout}`;
|
||||||
|
@ -159,6 +160,7 @@ class FilePage extends React.PureComponent {
|
||||||
if (!isPlayable && !this.state.fileViewLogged) {
|
if (!isPlayable && !this.state.fileViewLogged) {
|
||||||
this.logFileView(uri, claim);
|
this.logFileView(uri, claim);
|
||||||
}
|
}
|
||||||
|
this.setState({ fileGetStarted: false });
|
||||||
}
|
}
|
||||||
NativeModules.UtilityModule.checkDownloads();
|
NativeModules.UtilityModule.checkDownloads();
|
||||||
}
|
}
|
||||||
|
@ -499,6 +501,22 @@ class FilePage extends React.PureComponent {
|
||||||
navigateBack(navigation, drawerStack, popDrawerStack);
|
navigateBack(navigation, drawerStack, popDrawerStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSaveFilePressed = () => {
|
||||||
|
const { costInfo, fileGet, fileInfo, navigation, purchasedUris, purchaseUri } = this.props;
|
||||||
|
const { uri } = navigation.state.params;
|
||||||
|
|
||||||
|
if (fileInfo || purchasedUris.includes(uri)) {
|
||||||
|
// file already in library or URI already purchased, use fileGet directly
|
||||||
|
this.setState({ fileGetStarted: true }, () => fileGet(uri, true));
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
downloadPressed: true,
|
||||||
|
autoPlayMedia: false,
|
||||||
|
stopDownloadConfirmed: false
|
||||||
|
}, () => purchaseUri(uri, costInfo, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
balance,
|
balance,
|
||||||
|
@ -579,7 +597,10 @@ class FilePage extends React.PureComponent {
|
||||||
const mediaType = Lbry.getMediaType(contentType);
|
const mediaType = Lbry.getMediaType(contentType);
|
||||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||||
const { height, channel_name: channelName, value } = claim;
|
const { height, channel_name: channelName, value } = claim;
|
||||||
const showActions = !this.state.streamingMode && !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView;
|
const showActions = (fileInfo && fileInfo.download_path) &&
|
||||||
|
!this.state.fullscreenMode &&
|
||||||
|
!this.state.showImageViewer &&
|
||||||
|
!this.state.showWebView;
|
||||||
const showFileActions = (fileInfo && fileInfo.download_path) &&
|
const showFileActions = (fileInfo && fileInfo.download_path) &&
|
||||||
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
||||||
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
|
||||||
|
@ -754,6 +775,11 @@ class FilePage extends React.PureComponent {
|
||||||
show={DateTime.SHOW_DATE} />
|
show={DateTime.SHOW_DATE} />
|
||||||
</View>
|
</View>
|
||||||
<View style={filePageStyle.subscriptionRow}>
|
<View style={filePageStyle.subscriptionRow}>
|
||||||
|
{((isPlayable && !fileInfo) || (isPlayable && fileInfo && !fileInfo.download_path)) &&
|
||||||
|
<Button style={[filePageStyle.actionButton, filePageStyle.saveFileButton]}
|
||||||
|
theme={"light"}
|
||||||
|
icon={"download"}
|
||||||
|
onPress={this.onSaveFilePressed} />}
|
||||||
<Button style={[filePageStyle.actionButton, filePageStyle.tipButton]}
|
<Button style={[filePageStyle.actionButton, filePageStyle.tipButton]}
|
||||||
theme={"light"}
|
theme={"light"}
|
||||||
icon={"gift"}
|
icon={"gift"}
|
||||||
|
@ -761,7 +787,8 @@ class FilePage extends React.PureComponent {
|
||||||
<SubscribeButton
|
<SubscribeButton
|
||||||
style={filePageStyle.actionButton}
|
style={filePageStyle.actionButton}
|
||||||
uri={fullChannelUri}
|
uri={fullChannelUri}
|
||||||
name={channelName} />
|
name={channelName}
|
||||||
|
hideText={false} />
|
||||||
<SubscribeNotificationButton
|
<SubscribeNotificationButton
|
||||||
style={[filePageStyle.actionButton, filePageStyle.bellButton]}
|
style={[filePageStyle.actionButton, filePageStyle.bellButton]}
|
||||||
uri={fullChannelUri}
|
uri={fullChannelUri}
|
||||||
|
|
|
@ -79,13 +79,13 @@ const filePageStyle = StyleSheet.create({
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
subscriptionRow: {
|
subscriptionRow: {
|
||||||
flex: 0.5,
|
flex: 0.6,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
marginTop: 8
|
marginTop: 8
|
||||||
},
|
},
|
||||||
publishInfo: {
|
publishInfo: {
|
||||||
flex: 0.5,
|
flex: 0.4,
|
||||||
marginTop: 6,
|
marginTop: 6,
|
||||||
},
|
},
|
||||||
channelName: {
|
channelName: {
|
||||||
|
@ -197,8 +197,8 @@ const filePageStyle = StyleSheet.create({
|
||||||
actionButton: {
|
actionButton: {
|
||||||
alignSelf: 'flex-start',
|
alignSelf: 'flex-start',
|
||||||
backgroundColor: Colors.White,
|
backgroundColor: Colors.White,
|
||||||
paddingLeft: 16,
|
paddingLeft: 10,
|
||||||
paddingRight: 16
|
paddingRight: 10
|
||||||
},
|
},
|
||||||
bellButton: {
|
bellButton: {
|
||||||
marginLeft: 8
|
marginLeft: 8
|
||||||
|
@ -309,6 +309,9 @@ const filePageStyle = StyleSheet.create({
|
||||||
tipButton: {
|
tipButton: {
|
||||||
marginRight: 8
|
marginRight: 8
|
||||||
},
|
},
|
||||||
|
saveFileButton: {
|
||||||
|
marginRight: 8
|
||||||
|
},
|
||||||
tagContainer: {
|
tagContainer: {
|
||||||
marginLeft: 12,
|
marginLeft: 12,
|
||||||
marginRight: 12,
|
marginRight: 12,
|
||||||
|
|
Loading…
Add table
Reference in a new issue