implement send tip functionality #366
5 changed files with 126 additions and 26 deletions
|
@ -8,15 +8,15 @@ import {
|
|||
} from 'lbry-redux';
|
||||
import WalletSend from './view';
|
||||
|
||||
const perform = dispatch => ({
|
||||
sendToAddress: (address, amount) => dispatch(doSendDraftTransaction(address, amount)),
|
||||
notify: (data) => dispatch(doToast(data))
|
||||
});
|
||||
|
||||
const select = state => ({
|
||||
balance: selectBalance(state),
|
||||
draftTransaction: selectDraftTransaction(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);
|
||||
|
|
|
@ -37,7 +37,7 @@ const globalExceptionHandler = (error, isFatal) => {
|
|||
NativeModules.Mixpanel.logException(isFatal, error.message ? error.message : "No message", error);
|
||||
}
|
||||
};
|
||||
setJSExceptionHandler(globalExceptionHandler, true);
|
||||
//setJSExceptionHandler(globalExceptionHandler, true);
|
||||
|
||||
|
||||
function isFunction(object) {
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
doFetchFileInfo,
|
||||
doFetchCostInfoForUri,
|
||||
doResolveUri,
|
||||
doSendTip,
|
||||
doToast,
|
||||
makeSelectIsUriResolving,
|
||||
makeSelectCostInfoForUri,
|
||||
|
@ -10,6 +11,7 @@ import {
|
|||
makeSelectClaimForUri,
|
||||
makeSelectContentTypeForUri,
|
||||
makeSelectMetadataForUri,
|
||||
selectBalance,
|
||||
selectBlackListedOutpoints,
|
||||
} from 'lbry-redux';
|
||||
import { selectRewardContentClaimIds } from 'lbryinc';
|
||||
|
@ -19,6 +21,7 @@ import FilePage from './view';
|
|||
const select = (state, props) => {
|
||||
const selectProps = { uri: props.navigation.state.params.uri };
|
||||
return {
|
||||
balance: selectBalance(state),
|
||||
blackListedOutpoints: selectBlackListedOutpoints(state),
|
||||
claim: makeSelectClaimForUri(selectProps.uri)(state),
|
||||
isResolvingUri: makeSelectIsUriResolving(selectProps.uri)(state),
|
||||
|
@ -40,6 +43,7 @@ const perform = dispatch => ({
|
|||
fetchCostInfo: uri => dispatch(doFetchCostInfoForUri(uri)),
|
||||
notify: data => dispatch(doToast(data)),
|
||||
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)),
|
||||
});
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ class FilePage extends React.PureComponent {
|
|||
title: ''
|
||||
};
|
||||
|
||||
tipAmountInput = null;
|
||||
|
||||
playerBackground = null;
|
||||
|
||||
startTime = null;
|
||||
|
@ -55,8 +57,10 @@ class FilePage extends React.PureComponent {
|
|||
pageSuspended: false,
|
||||
showImageViewer: false,
|
||||
showWebView: false,
|
||||
showTipView: false,
|
||||
playerBgHeight: 0,
|
||||
playerHeight: 0,
|
||||
tipAmount: null,
|
||||
uri: null,
|
||||
stopDownloadConfirmed: false
|
||||
};
|
||||
|
@ -177,7 +181,7 @@ class FilePage extends React.PureComponent {
|
|||
[
|
||||
{ text: 'No' },
|
||||
{ text: 'Yes', onPress: () => {
|
||||
stopDownload(navigation.state.params.uri, fileInfo);
|
||||
stopDownloadz4(navigation.state.params.uri, fileInfo);
|
||||
this.setState({
|
||||
downloadPressed: false,
|
||||
fileViewLogged: false,
|
||||
|
@ -310,6 +314,21 @@ class FilePage extends React.PureComponent {
|
|||
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() {
|
||||
const {
|
||||
claim,
|
||||
|
@ -378,12 +397,12 @@ class FilePage extends React.PureComponent {
|
|||
const mediaType = Lbry.getMediaType(contentType);
|
||||
const isPlayable = mediaType === 'video' || mediaType === 'audio';
|
||||
const { height, channel_name: channelName, value } = claim;
|
||||
const showActions = !this.state.fullscreenMode &&
|
||||
!this.state.showImageViewer &&
|
||||
!this.state.showWebView &&
|
||||
(completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
||||
const showActions = !this.state.fullscreenMode && !this.state.showImageViewer && !this.state.showWebView;
|
||||
const showFileActions = (completed || (fileInfo && !fileInfo.stopped && fileInfo.written_bytes < fileInfo.total_bytes));
|
||||
const channelClaimId =
|
||||
value && value.publisherSignature && value.publisherSignature.certificateId;
|
||||
const canSendTip = this.state.tipAmount > 0;
|
||||
|
||||
|
||||
const playerStyle = [filePageStyle.player,
|
||||
this.state.isLandscape ? filePageStyle.containedPlayerLandscape :
|
||||
|
@ -473,8 +492,15 @@ class FilePage extends React.PureComponent {
|
|||
onPlaybackStarted={this.onPlaybackStarted}
|
||||
/>}
|
||||
|
||||
{fileInfo && showActions &&
|
||||
{showActions &&
|
||||
<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}
|
||||
theme={"light"}
|
||||
icon={"trash"}
|
||||
|
@ -489,6 +515,7 @@ class FilePage extends React.PureComponent {
|
|||
onPress={this.onStopDownloadPressed} />
|
||||
}
|
||||
</View>}
|
||||
</View>}
|
||||
<ScrollView
|
||||
style={showActions ? filePageStyle.scrollContainerActions : filePageStyle.scrollContainer}
|
||||
contentContainerstyle={showActions ? null : filePageStyle.scrollContent}>
|
||||
|
@ -507,6 +534,23 @@ class FilePage extends React.PureComponent {
|
|||
|
||||
<RelatedContent navigation={navigation} uri={uri} />
|
||||
</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>
|
||||
)}
|
||||
{!this.state.fullscreenMode && <FloatingWalletBalance navigation={navigation} />}
|
||||
|
|
|
@ -142,6 +142,8 @@ const filePageStyle = StyleSheet.create({
|
|||
color: '#0c604b'
|
||||
},
|
||||
actions: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
paddingTop: 16,
|
||||
|
@ -149,6 +151,9 @@ const filePageStyle = StyleSheet.create({
|
|||
marginTop: -14,
|
||||
width: '100%',
|
||||
},
|
||||
fileActions: {
|
||||
alignSelf: 'flex-end'
|
||||
},
|
||||
actionButton: {
|
||||
alignSelf: 'flex-start',
|
||||
backgroundColor: Colors.White,
|
||||
|
@ -200,10 +205,57 @@ const filePageStyle = StyleSheet.create({
|
|||
zIndex: 100
|
||||
},
|
||||
link: {
|
||||
color: Colors.LbryGreen
|
||||
color: Colors.Grey
|
||||
},
|
||||
linkTapped: {
|
||||
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
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue