diff --git a/src/component/modalTipView/index.js b/src/component/modalTipView/index.js
new file mode 100644
index 0000000..7eaf6e6
--- /dev/null
+++ b/src/component/modalTipView/index.js
@@ -0,0 +1,18 @@
+import { connect } from 'react-redux';
+import { doSendTip, doToast, selectBalance } from 'lbry-redux';
+import ModalTipView from './view';
+
+const select = state => ({
+ balance: selectBalance(state),
+});
+
+const perform = dispatch => ({
+ notify: data => dispatch(doToast(data)),
+ sendTip: (amount, claimId, isSupport, successCallback, errorCallback) =>
+ dispatch(doSendTip(amount, claimId, isSupport, successCallback, errorCallback)),
+});
+
+export default connect(
+ select,
+ perform
+)(ModalTipView);
diff --git a/src/component/modalTipView/view.js b/src/component/modalTipView/view.js
new file mode 100644
index 0000000..301a225
--- /dev/null
+++ b/src/component/modalTipView/view.js
@@ -0,0 +1,139 @@
+import React from 'react';
+import { ActivityIndicator, Alert, Text, TextInput, TouchableOpacity, View } from 'react-native';
+import { formatCredits } from 'lbry-redux';
+import modalStyle from 'styles/modal';
+import modalTipStyle from 'styles/modalTip';
+import Button from 'component/button';
+import Colors from 'styles/colors';
+import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
+import Icon from 'react-native-vector-icons/FontAwesome5';
+import Link from 'component/link';
+
+export default class ModalTipView extends React.PureComponent {
+ state = {
+ creditsInputFocused: false,
+ sendTipStarted: false,
+ tipAmount: null,
+ };
+
+ handleSendTip = () => {
+ const { claim, balance, notify, onSendTipFailed, onSendTipSuccessful, sendTip } = this.props;
+ const { tipAmount } = this.state;
+
+ if (tipAmount > balance) {
+ notify({
+ message: 'Insufficient credits',
+ });
+ return;
+ }
+
+ const amount = parseInt(tipAmount, 10);
+ const message =
+ amount === 1
+ ? __('Are you sure you want to tip %amount% credit', { amount })
+ : __('Are you sure you want to tip %amount% credits', { amount });
+
+ Alert.alert(
+ __('Send tip'),
+ message,
+ [
+ { text: __('No') },
+ {
+ text: __('Yes'),
+ onPress: () => {
+ this.setState({ sendTipStarted: true }, () =>
+ sendTip(
+ tipAmount,
+ claim.claim_id,
+ false,
+ () => {
+ // success
+ this.setState({ tipAmount: null, sendTipStarted: false });
+ if (onSendTipSuccessful) onSendTipSuccessful();
+ },
+ () => {
+ // error
+ if (onSendTipFailed) onSendTipFailed();
+ }
+ )
+ );
+ },
+ },
+ ],
+ { cancelable: true }
+ );
+ };
+
+ render() {
+ const { balance, channelName, contentName, onCancelPress, onOverlayPress } = this.props;
+ const canSendTip = this.state.tipAmount > 0;
+
+ return (
+
+
+
+
+ {channelName ? __('Send a tip to %channel%', { channel: channelName }) : __('Send a tip')}
+
+
+
+
+ (this.tipAmountInput = ref)}
+ onChangeText={value => this.setState({ tipAmount: value })}
+ underlineColorAndroid={Colors.NextLbryGreen}
+ keyboardType={'numeric'}
+ onFocus={() => this.setState({ creditsInputFocused: true })}
+ onBlur={() => this.setState({ creditsInputFocused: false })}
+ placeholder={'0'}
+ value={this.state.tipAmount}
+ selectTextOnFocus
+ style={modalTipStyle.tipAmountInput}
+ />
+ LBC
+
+ {this.state.creditsInputFocused && }
+ {this.state.creditsInputFocused && (
+ {formatCredits(parseFloat(balance), 1, true)}
+ )}
+
+
+ {this.state.sendTipStarted && }
+
+
+
+
+ {__(
+ 'This will appear as a tip for %content%, which will boost its ability to be discovered while active.',
+ { content: contentName }
+ )}
+
+
+
+
+
+ {
+ if (onCancelPress) onCancelPress();
+ }}
+ />
+
+
+
+
+
+ );
+ }
+}
diff --git a/src/index.js b/src/index.js
index 74b01f0..a82ebf5 100644
--- a/src/index.js
+++ b/src/index.js
@@ -57,7 +57,6 @@ window.__ = __;
const globalExceptionHandler = (error, isFatal) => {
if (error && NativeModules.Firebase) {
- console.log(error);
NativeModules.Firebase.logException(isFatal, error.message ? error.message : 'No message', JSON.stringify(error));
}
};
diff --git a/src/page/channel/view.js b/src/page/channel/view.js
index 40c13ec..0f25128 100644
--- a/src/page/channel/view.js
+++ b/src/page/channel/view.js
@@ -23,6 +23,7 @@ import EmptyStateView from 'component/emptyStateView';
import Icon from 'react-native-vector-icons/FontAwesome5';
import Link from 'component/link';
import ModalPicker from 'component/modalPicker';
+import ModalTipView from 'component/modalTipView';
import PageHeader from 'component/pageHeader';
import SubscribeButton from 'component/subscribeButton';
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
@@ -36,6 +37,7 @@ class ChannelPage extends React.PureComponent {
autoStyle: null,
showSortPicker: false,
showTimePicker: false,
+ showTipView: false,
orderBy: ['release_time'], // sort by new by default
activeTab: Constants.CONTENT_TAB,
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting channel pages by new
@@ -176,6 +178,10 @@ class ChannelPage extends React.PureComponent {
}
};
+ onTipPressed = () => {
+ this.setState({ showTipView: true });
+ };
+
onSharePressed = () => {
const { claim } = this.props;
if (claim) {
@@ -212,7 +218,7 @@ class ChannelPage extends React.PureComponent {
render() {
const { channels, claim, navigation, uri, drawerStack, popDrawerStack, subCount, timeItem } = this.props;
const { name, permanent_url: permanentUrl } = claim;
- const { autoStyle, currentSortByItem, showSortPicker, showTimePicker } = this.state;
+ const { autoStyle, currentSortByItem, showSortPicker, showTimePicker, showTipView } = this.state;
const ownedChannel = channels ? channels.map(channel => channel.permanent_url).includes(permanentUrl) : false;
let thumbnailUrl,
@@ -297,6 +303,12 @@ class ChannelPage extends React.PureComponent {
icon={'share-alt'}
onPress={this.onSharePressed}
/>
+
{!ownedChannel && }
{false && !ownedChannel && (
)}
+ {showTipView && (
+ this.setState({ showTipView: false })}
+ onOverlayPress={() => this.setState({ showTipView: false })}
+ onSendTipSuccessful={() => this.setState({ showTipView: false })}
+ />
+ )}
);
}
diff --git a/src/page/file/view.js b/src/page/file/view.js
index a151fbd..403df20 100644
--- a/src/page/file/view.js
+++ b/src/page/file/view.js
@@ -36,6 +36,7 @@ import FilePrice from 'component/filePrice';
import FloatingWalletBalance from 'component/floatingWalletBalance';
import Link from 'component/link';
import MediaPlayer from 'component/mediaPlayer';
+import ModalTipView from 'component/modalTipView';
import RelatedContent from 'component/relatedContent';
import SubscribeButton from 'component/subscribeButton';
import SubscribeNotificationButton from 'component/subscribeNotificationButton';
@@ -51,8 +52,6 @@ class FilePage extends React.PureComponent {
title: '',
};
- tipAmountInput = null;
-
playerBackground = null;
scrollView = null;
@@ -85,7 +84,6 @@ class FilePage extends React.PureComponent {
showTipView: false,
playerBgHeight: 0,
playerHeight: 0,
- tipAmount: null,
uri: null,
uriVars: null,
stopDownloadConfirmed: false,
@@ -584,39 +582,6 @@ class FilePage extends React.PureComponent {
}
};
- 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;
- }
-
- const suffix = 'credit' + (parseInt(tipAmount, 10) === 1 ? '' : 's');
- Alert.alert(
- 'Send tip',
- `Are you sure you want to tip ${tipAmount} ${suffix}?`,
- [
- { text: 'No' },
- {
- text: 'Yes',
- onPress: () => {
- this.setState({ sendTipStarted: true }, () =>
- sendTip(tipAmount, claim.claim_id, false, () => {
- this.setState({ tipAmount: null, showTipView: false, sendTipStarted: false });
- })
- );
- },
- },
- ],
- { cancelable: true }
- );
- };
-
renderTags = tags => {
const { navigation } = this.props;
return tags.map((tag, i) => (
@@ -830,7 +795,6 @@ class FilePage extends React.PureComponent {
const { height, signing_channel: signingChannel, value } = claim;
const channelName = signingChannel && signingChannel.name;
const channelClaimId = claim && claim.signing_channel && claim.signing_channel.claim_id;
- const canSendTip = this.state.tipAmount > 0;
const fullUri = `${claim.name}#${claim.claim_id}`;
const canEdit = myClaimUris.includes(normalizeURI(fullUri));
const showActions =
@@ -1169,48 +1133,6 @@ class FilePage extends React.PureComponent {
- {this.state.showTipView && }
- {this.state.showTipView && (
-
-
-
- (this.tipAmountInput = ref)}
- onChangeText={value => this.setState({ tipAmount: value })}
- onFocus={() => this.setState({ creditsInputFocused: true })}
- onBlur={() => this.setState({ creditsInputFocused: false })}
- underlineColorAndroid={Colors.NextLbryGreen}
- keyboardType={'numeric'}
- placeholder={'0'}
- value={this.state.tipAmount}
- selectTextOnFocus
- style={[filePageStyle.input, filePageStyle.tipAmountInput]}
- />
- LBC
-
- {this.state.creditsInputFocused && }
- {this.state.creditsInputFocused && (
- {formatCredits(parseFloat(balance), 1, true)}
- )}
-
-
- {this.state.sendTipStarted && }
- this.setState({ showTipView: false })}
- />
-
-
-
- )}
-
{this.state.showDescription && description && description.length > 0 && (
)}
@@ -1243,8 +1165,18 @@ class FilePage extends React.PureComponent {
)}
- {!this.state.creditsInputFocused &&
- !this.state.fullscreenMode &&
+ {this.state.showTipView && (
+ this.setState({ showTipView: false })}
+ onOverlayPress={() => this.setState({ showTipView: false })}
+ onSendTipSuccessful={() => this.setState({ showTipView: false })}
+ />
+ )}
+ {!this.state.fullscreenMode &&
+ !this.state.showTipView &&
!this.state.showImageViewer &&
!this.state.showWebView && }
diff --git a/src/styles/channelPage.js b/src/styles/channelPage.js
index 9de0bda..be7f0ca 100644
--- a/src/styles/channelPage.js
+++ b/src/styles/channelPage.js
@@ -176,6 +176,9 @@ const channelPageStyle = StyleSheet.create({
marginLeft: 8,
marginRight: 8,
},
+ tipButton: {
+ marginRight: 8,
+ },
followerCount: {
fontFamily: 'Inter-UI-Regular',
fontSize: 12,
diff --git a/src/styles/modalTip.js b/src/styles/modalTip.js
new file mode 100644
index 0000000..e86f95c
--- /dev/null
+++ b/src/styles/modalTip.js
@@ -0,0 +1,71 @@
+import { StyleSheet } from 'react-native';
+import Colors from './colors';
+
+const modalTipStyle = StyleSheet.create({
+ container: {
+ padding: 16,
+ },
+ title: {
+ fontFamily: 'Inter-UI-Regular',
+ fontSize: 24,
+ },
+ row: {
+ flexDirection: 'row',
+ flex: 1,
+ },
+ amountRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginRight: 24,
+ },
+ tipAmountInput: {
+ fontFamily: 'Inter-UI-Regular',
+ fontSize: 14,
+ alignSelf: 'flex-start',
+ textAlign: 'right',
+ width: 80,
+ letterSpacing: 1,
+ },
+ currency: {
+ fontFamily: 'Inter-UI-Regular',
+ fontSize: 12,
+ marginLeft: 4,
+ },
+ buttonRow: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ marginTop: 16,
+ },
+ button: {
+ backgroundColor: Colors.LbryGreen,
+ },
+ cancelTipLink: {
+ color: Colors.Grey,
+ },
+ balance: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ marginLeft: 24,
+ },
+ balanceText: {
+ fontFamily: 'Inter-UI-SemiBold',
+ fontSize: 14,
+ marginLeft: 4,
+ },
+ info: {
+ marginTop: 4,
+ },
+ infoText: {
+ fontFamily: 'Inter-UI-Regular',
+ fontSize: 14,
+ color: Colors.DescriptionGrey,
+ },
+ learnMoreLink: {
+ fontFamily: 'Inter-UI-Regular',
+ fontSize: 14,
+ color: Colors.LbryGreen,
+ },
+});
+
+export default modalTipStyle;