implement send tip functionality #366

Merged
akinwale merged 2 commits from tips into master 2018-11-28 15:44:08 +01:00
4 changed files with 124 additions and 24 deletions

View file

@ -8,15 +8,15 @@ import {
} from 'lbry-redux'; } from 'lbry-redux';
import WalletSend from './view'; import WalletSend from './view';
const perform = dispatch => ({
sendToAddress: (address, amount) => dispatch(doSendDraftTransaction(address, amount)),
notify: (data) => dispatch(doToast(data))
});
const select = state => ({ const select = state => ({
balance: selectBalance(state), balance: selectBalance(state),
draftTransaction: selectDraftTransaction(state), draftTransaction: selectDraftTransaction(state),
transactionError: selectDraftTransactionError(state), transactionError: selectDraftTransactionError(state),
}); });
const perform = dispatch => ({
sendToAddress: (address, amount) => dispatch(doSendDraftTransaction(address, amount)),
notify: (data) => dispatch(doToast(data))
});
export default connect(select, perform)(WalletSend); export default connect(select, perform)(WalletSend);

View file

@ -3,6 +3,7 @@ import {
doFetchFileInfo, doFetchFileInfo,
doFetchCostInfoForUri, doFetchCostInfoForUri,
doResolveUri, doResolveUri,
doSendTip,
doToast, doToast,
makeSelectIsUriResolving, makeSelectIsUriResolving,
makeSelectCostInfoForUri, makeSelectCostInfoForUri,
@ -10,6 +11,7 @@ import {
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectContentTypeForUri, makeSelectContentTypeForUri,
makeSelectMetadataForUri, makeSelectMetadataForUri,
selectBalance,
selectBlackListedOutpoints, selectBlackListedOutpoints,
} from 'lbry-redux'; } from 'lbry-redux';
import { selectRewardContentClaimIds } from 'lbryinc'; import { selectRewardContentClaimIds } from 'lbryinc';
@ -19,6 +21,7 @@ import FilePage from './view';
const select = (state, props) => { const select = (state, props) => {
const selectProps = { uri: props.navigation.state.params.uri }; const selectProps = { uri: props.navigation.state.params.uri };
return { return {
balance: selectBalance(state),
blackListedOutpoints: selectBlackListedOutpoints(state), blackListedOutpoints: selectBlackListedOutpoints(state),
claim: makeSelectClaimForUri(selectProps.uri)(state), claim: makeSelectClaimForUri(selectProps.uri)(state),
isResolvingUri: makeSelectIsUriResolving(selectProps.uri)(state), isResolvingUri: makeSelectIsUriResolving(selectProps.uri)(state),
@ -40,6 +43,7 @@ const perform = dispatch => ({
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)), fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
notify: data => dispatch(doToast(data)), notify: data => dispatch(doToast(data)),
resolveUri: uri => dispatch(doResolveUri(uri)), resolveUri: uri => dispatch(doResolveUri(uri)),
sendTip: (amount, claimId, uri, successCallback, errorCallback) => dispatch(doSendTip(amount, claimId, uri, successCallback, errorCallback)),
stopDownload: (uri, fileInfo) => dispatch(doStopDownloadingFile(uri, fileInfo)), stopDownload: (uri, fileInfo) => dispatch(doStopDownloadingFile(uri, fileInfo)),
}); });

View file

@ -37,6 +37,8 @@ class FilePage extends React.PureComponent {
title: '' title: ''
}; };
tipAmountInput = null;
playerBackground = null; playerBackground = null;
startTime = null; startTime = null;
@ -55,8 +57,10 @@ class FilePage extends React.PureComponent {
pageSuspended: false, pageSuspended: false,
showImageViewer: false, showImageViewer: false,
showWebView: false, showWebView: false,
showTipView: false,
playerBgHeight: 0, playerBgHeight: 0,
playerHeight: 0, playerHeight: 0,
tipAmount: null,
uri: null, uri: null,
stopDownloadConfirmed: false stopDownloadConfirmed: false
}; };
@ -310,6 +314,21 @@ class FilePage extends React.PureComponent {
this.setState({ fileViewLogged: true }); this.setState({ fileViewLogged: true });
} }
handleSendTip = () => {
const { claim, balance, navigation, notify, sendTip } = this.props;
const { uri } = navigation.state.params;
const { tipAmount } = this.state;
if (tipAmount > balance) {
notify({
message: 'Insufficient credits',
});
return;
}
sendTip(tipAmount, claim.claim_id, uri, () => { this.setState({ tipAmount: 0, showTipView: false }) });
}
render() { render() {
const { const {
claim, claim,
@ -378,12 +397,12 @@ 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.fullscreenMode && const showActions = !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView;
!this.state.showImageViewer && const showFileActions = (completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
!this.state.showWebView &&
(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 canSendTip = this.state.tipAmount > 0;
const playerStyle = [filePageStyle.player, const playerStyle = [filePageStyle.player,
this.state.isLandscape ? filePageStyle.containedPlayerLandscape : this.state.isLandscape ? filePageStyle.containedPlayerLandscape :
@ -473,8 +492,15 @@ class FilePage extends React.PureComponent {
onPlaybackStarted={this.onPlaybackStarted} onPlaybackStarted={this.onPlaybackStarted}
/>} />}
{fileInfo && showActions && {showActions &&
<View style={filePageStyle.actions}> <View style={filePageStyle.actions}>
{<Button style={filePageStyle.actionButton}
theme={"light"}
icon={"gift"}
text={"Send a tip"}
onPress={() => this.setState({ showTipView: true })} />}
{showFileActions &&
<View style={filePageStyle.fileActions}>
{completed && <Button style={filePageStyle.actionButton} {completed && <Button style={filePageStyle.actionButton}
theme={"light"} theme={"light"}
icon={"trash"} icon={"trash"}
@ -489,6 +515,7 @@ class FilePage extends React.PureComponent {
onPress={this.onStopDownloadPressed} /> onPress={this.onStopDownloadPressed} />
} }
</View>} </View>}
</View>}
<ScrollView <ScrollView
style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer} style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer}
contentContainerstyle={showActions ? null : filePageStyle.scrollContent}> contentContainerstyle={showActions ? null : filePageStyle.scrollContent}>
@ -507,6 +534,23 @@ class FilePage extends React.PureComponent {
<RelatedContent navigation={navigation} uri={uri} /> <RelatedContent navigation={navigation} uri={uri} />
</ScrollView> </ScrollView>
{this.state.showTipView && <View style={filePageStyle.tipCard}>
<View style={filePageStyle.row}>
<View style={filePageStyle.amountRow}>
<TextInput ref={ref => this.tipAmountInput = ref}
onChangeText={value => this.setState({tipAmount: value})}
keyboardType={'numeric'}
value={this.state.tipAmount}
style={[filePageStyle.input, filePageStyle.tipAmountInput]} />
<Text style={[filePageStyle.text, filePageStyle.currency]}>LBC</Text>
</View>
<Link style={[filePageStyle.link, filePageStyle.cancelTipLink]} text={'Cancel'} onPress={() => this.setState({ showTipView: false })} />
<Button text={'Send tip'}
style={[filePageStyle.button, filePageStyle.sendButton]}
disabled={!canSendTip}
onPress={this.handleSendTip} />
</View>
</View>}
</View> </View>
)} )}
{!this.state.fullscreenMode && <FloatingWalletBalance navigation={navigation} />} {!this.state.fullscreenMode && <FloatingWalletBalance navigation={navigation} />}

View file

@ -142,6 +142,8 @@ const filePageStyle = StyleSheet.create({
color: '#0c604b' color: '#0c604b'
}, },
actions: { actions: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingLeft: 16, paddingLeft: 16,
paddingRight: 16, paddingRight: 16,
paddingTop: 16, paddingTop: 16,
@ -149,6 +151,9 @@ const filePageStyle = StyleSheet.create({
marginTop: -14, marginTop: -14,
width: '100%', width: '100%',
}, },
fileActions: {
alignSelf: 'flex-end'
},
actionButton: { actionButton: {
alignSelf: 'flex-start', alignSelf: 'flex-start',
backgroundColor: Colors.White, backgroundColor: Colors.White,
@ -200,10 +205,57 @@ const filePageStyle = StyleSheet.create({
zIndex: 100 zIndex: 100
}, },
link: { link: {
color: Colors.LbryGreen color: Colors.Grey
}, },
linkTapped: { linkTapped: {
color: "rgba(64, 184, 154, .2)" color: "rgba(64, 184, 154, .2)"
},
tipCard: {
backgroundColor: Colors.White,
position: 'absolute',
top: containedMediaHeightWithControls - 16,
width: '100%',
paddingTop: 8,
paddingBottom: 8,
paddingLeft: 16,
paddingRight: 16
},
row: {
flexDirection: 'row',
flex: 1,
justifyContent: 'space-between'
},
amountRow: {
flexDirection: 'row',
flex: 0.75
},
button: {
backgroundColor: Colors.LbryGreen,
alignSelf: 'flex-end',
marginBottom: 6
},
cancelTipLink: {
alignSelf: 'flex-end',
marginBottom: 14
},
input: {
fontFamily: 'Metropolis-Regular',
fontSize: 14
},
tipAmountInput: {
alignSelf: 'flex-start',
width: 80,
fontSize: 16,
letterSpacing: 1
},
currency: {
alignSelf: 'flex-start',
marginTop: 17
},
text: {
fontFamily: 'Metropolis-Regular',
fontSize: 16,
lineHeight: 24
} }
}); });