Display USD #135
18 changed files with 270 additions and 62 deletions
|
@ -1,12 +1,14 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doToast, selectMyChannelClaims } from 'lbry-redux';
|
import { doToast, selectBalance, selectMyChannelClaims } from 'lbry-redux';
|
||||||
import { selectUser } from 'lbryinc';
|
import { selectUnclaimedRewardValue, selectUser } from 'lbryinc';
|
||||||
import { selectSdkReady } from 'redux/selectors/settings';
|
import { selectSdkReady } from 'redux/selectors/settings';
|
||||||
import DrawerContent from './view';
|
import DrawerContent from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
balance: selectBalance(state),
|
||||||
channels: selectMyChannelClaims(state),
|
channels: selectMyChannelClaims(state),
|
||||||
sdkReady: selectSdkReady(state),
|
sdkReady: selectSdkReady(state),
|
||||||
|
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import channelIconStyle from 'styles/channelIcon';
|
import channelIconStyle from 'styles/channelIcon';
|
||||||
import discoverStyle from 'styles/discover';
|
import discoverStyle from 'styles/discover';
|
||||||
|
import { Lbryio } from 'lbryinc';
|
||||||
|
import { formatUsd } from 'utils/helper';
|
||||||
|
|
||||||
const groupedMenuItems = {
|
const groupedMenuItems = {
|
||||||
'Find content': [
|
'Find content': [
|
||||||
|
@ -42,6 +44,18 @@ const routesRequiringSdkReady = [
|
||||||
];
|
];
|
||||||
|
|
||||||
class DrawerContent extends React.PureComponent {
|
class DrawerContent extends React.PureComponent {
|
||||||
|
state = {
|
||||||
|
usdExchangeRate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getAvatarImageUrl = () => {
|
getAvatarImageUrl = () => {
|
||||||
const { channels = [] } = this.props;
|
const { channels = [] } = this.props;
|
||||||
if (channels) {
|
if (channels) {
|
||||||
|
@ -82,7 +96,7 @@ class DrawerContent extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { activeTintColor, navigation, user, onItemPress } = this.props;
|
const { activeTintColor, balance, navigation, unclaimedRewardAmount, user, onItemPress } = this.props;
|
||||||
const { state } = navigation;
|
const { state } = navigation;
|
||||||
|
|
||||||
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
const activeItemKey = state.routes[state.index] ? state.routes[state.index].key : null;
|
||||||
|
@ -189,6 +203,15 @@ class DrawerContent extends React.PureComponent {
|
||||||
</View>
|
</View>
|
||||||
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
<Text style={[discoverStyle.menuItem, focused ? discoverStyle.menuItemFocused : null]}>
|
||||||
{__(item.label)}
|
{__(item.label)}
|
||||||
|
{item.label === 'Wallet' && this.state.usdExchangeRate > 0 && (
|
||||||
|
<Text> ({formatUsd(parseFloat(balance) * parseFloat(this.state.usdExchangeRate))})</Text>
|
||||||
|
)}
|
||||||
|
{item.label === 'Rewards' && this.state.usdExchangeRate > 0 && (
|
||||||
|
<Text>
|
||||||
|
{' '}
|
||||||
|
({formatUsd(parseFloat(unclaimedRewardAmount) * parseFloat(this.state.usdExchangeRate))})
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { connect } from 'react-redux';
|
||||||
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
||||||
import { selectBalance } from 'lbry-redux';
|
import { selectBalance } from 'lbry-redux';
|
||||||
import { selectUnclaimedRewardValue } from 'lbryinc';
|
import { selectUnclaimedRewardValue } from 'lbryinc';
|
||||||
import Constants from 'constants';
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
import FloatingWalletBalance from './view';
|
import FloatingWalletBalance from './view';
|
||||||
|
|
||||||
const select = state => ({
|
const select = state => ({
|
||||||
|
@ -11,7 +11,4 @@ const select = state => ({
|
||||||
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, null)(FloatingWalletBalance);
|
||||||
select,
|
|
||||||
null
|
|
||||||
)(FloatingWalletBalance);
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
|
import { ActivityIndicator, Text, TouchableOpacity, View } from 'react-native';
|
||||||
import Colors from '../../styles/colors';
|
import { formatUsd } from 'utils/helper';
|
||||||
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from '../link';
|
import Link from 'component/link';
|
||||||
import rewardStyle from '../../styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
canClaim: boolean,
|
canClaim: boolean,
|
||||||
|
@ -61,7 +62,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
if (reward) {
|
if (reward) {
|
||||||
const claimed = !!reward.transaction_id;
|
const claimed = !!reward.transaction_id;
|
||||||
if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
|
if (!claimed && reward.reward_range && reward.reward_range.includes('-')) {
|
||||||
return reward.reward_range.split('-')[0] + '+'; // ex: 5+
|
return reward.reward_range.split('-')[1];
|
||||||
} else if (reward.reward_amount > 0) {
|
} else if (reward.reward_amount > 0) {
|
||||||
return reward.reward_amount;
|
return reward.reward_amount;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +73,7 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { canClaim, isPending, onClaimPress, reward } = this.props;
|
const { canClaim, isPending, onClaimPress, reward, usdExchangeRate } = this.props;
|
||||||
const claimed = !!reward.transaction_id;
|
const claimed = !!reward.transaction_id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -117,8 +118,16 @@ class RewardCard extends React.PureComponent<Props> {
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View style={rewardStyle.rightCol}>
|
<View style={rewardStyle.rightCol}>
|
||||||
|
{reward.reward_range && reward.reward_range.indexOf('-') > -1 && (
|
||||||
|
<Text style={rewardStyle.rightColHeader}>{__('up to')}</Text>
|
||||||
|
)}
|
||||||
<Text style={rewardStyle.rewardAmount}>{this.getDisplayAmount()}</Text>
|
<Text style={rewardStyle.rewardAmount}>{this.getDisplayAmount()}</Text>
|
||||||
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
<Text style={rewardStyle.rewardCurrency}>LBC</Text>
|
||||||
|
{usdExchangeRate > 0 && (
|
||||||
|
<Text style={rewardStyle.rewardUsd}>
|
||||||
|
≈{formatUsd(parseFloat(this.getDisplayAmount()) * parseFloat(usdExchangeRate))}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Link from 'component/link';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import rewardStyle from 'styles/reward';
|
import rewardStyle from 'styles/reward';
|
||||||
|
import { formatUsd } from '../../utils/helper';
|
||||||
|
|
||||||
class RewardEnrolment extends React.Component {
|
class RewardEnrolment extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -29,7 +30,7 @@ class RewardEnrolment extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { fetching, navigation, unclaimedRewardAmount, user } = this.props;
|
const { unclaimedRewardAmount, usdExchangeRate } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.enrollContainer}>
|
<View style={rewardStyle.enrollContainer}>
|
||||||
|
@ -43,9 +44,11 @@ class RewardEnrolment extends React.Component {
|
||||||
|
|
||||||
<View style={rewardStyle.onboarding}>
|
<View style={rewardStyle.onboarding}>
|
||||||
<Text style={rewardStyle.enrollDescText}>
|
<Text style={rewardStyle.enrollDescText}>
|
||||||
{__('LBRY credits allow you to purchase content, publish content, and influence the network.')}
|
{__('LBRY credits allow you to publish or purchase content.')}
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
{__('You get credits for free for providing an email address and taking other basic actions.')}
|
{__('You can obtain free credits worth %amount% after you provide an email address.', {
|
||||||
|
amount: formatUsd(parseFloat(unclaimedRewardAmount) * parseFloat(usdExchangeRate)),
|
||||||
|
})}
|
||||||
{'\n\n'}
|
{'\n\n'}
|
||||||
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
<Link style={rewardStyle.learnMoreLink} text={__('Learn more')} onPress={this.onLearnMorePressed} />.
|
||||||
</Text>
|
</Text>
|
||||||
|
|
|
@ -58,7 +58,7 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||||
const uris = claimSearchByQuery[claimSearchKey];
|
const uris = claimSearchByQuery[claimSearchKey];
|
||||||
if (
|
if (
|
||||||
lastPageReached[claimSearchKey] ||
|
lastPageReached[claimSearchKey] ||
|
||||||
((uris.length > 0 && uris.length < suggestedPageSize) || uris.length >= softLimit)
|
(uris.length > 0 && uris.length < suggestedPageSize) || uris.length >= softLimit
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claimSearchByQuery, suggested, inModal, navigation } = this.props;
|
const { claimSearchByQuery, inModal, navigation } = this.props;
|
||||||
const options = this.buildClaimSearchOptions();
|
const options = this.buildClaimSearchOptions();
|
||||||
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
const claimSearchKey = createNormalizedClaimSearchKey(options);
|
||||||
const claimSearchUris = claimSearchByQuery[claimSearchKey];
|
const claimSearchUris = claimSearchByQuery[claimSearchKey];
|
||||||
|
@ -92,7 +92,7 @@ class SuggestedSubscriptionsGrid extends React.PureComponent {
|
||||||
maxToRenderPerBatch={48}
|
maxToRenderPerBatch={48}
|
||||||
removeClippedSubviews
|
removeClippedSubviews
|
||||||
itemDimension={120}
|
itemDimension={120}
|
||||||
spacing={2}
|
spacing={1}
|
||||||
items={claimSearchUris}
|
items={claimSearchUris}
|
||||||
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
|
style={inModal ? subscriptionsStyle.modalScrollContainer : subscriptionsStyle.scrollContainer}
|
||||||
contentContainerStyle={
|
contentContainerStyle={
|
||||||
|
|
|
@ -6,7 +6,4 @@ const select = state => ({
|
||||||
balance: selectBalance(state),
|
balance: selectBalance(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, null)(WalletBalance);
|
||||||
select,
|
|
||||||
null
|
|
||||||
)(WalletBalance);
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Image, Text, View } from 'react-native';
|
import { Image, Text, View } from 'react-native';
|
||||||
import { Lbry, formatCredits } from 'lbry-redux';
|
import { formatCredits } from 'lbry-redux';
|
||||||
import Address from 'component/address';
|
import { Lbryio } from 'lbryinc';
|
||||||
import Button from 'component/button';
|
import { formatUsd } from 'utils/helper';
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -11,6 +11,18 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalletBalance extends React.PureComponent<Props> {
|
class WalletBalance extends React.PureComponent<Props> {
|
||||||
|
state = {
|
||||||
|
usdExchangeRate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { balance } = this.props;
|
const { balance } = this.props;
|
||||||
return (
|
return (
|
||||||
|
@ -21,6 +33,13 @@ class WalletBalance extends React.PureComponent<Props> {
|
||||||
<Text style={walletStyle.balance}>
|
<Text style={walletStyle.balance}>
|
||||||
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
{(balance || balance === 0) && formatCredits(parseFloat(balance), 2) + ' LBC'}
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text style={walletStyle.usdBalance}>
|
||||||
|
{this.state.usdExchangeRate > 0 && (
|
||||||
|
<Text>
|
||||||
|
≈{formatUsd(isNaN(balance) ? 0 : parseFloat(balance) * parseFloat(this.state.usdExchangeRate))}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Image, Text, View } from 'react-native';
|
import { Text, View } from 'react-native';
|
||||||
import { Lbry, formatCredits } from 'lbry-redux';
|
import { formatCredits } from 'lbry-redux';
|
||||||
import Address from 'component/address';
|
import { Lbryio } from 'lbryinc';
|
||||||
import Button from 'component/button';
|
import { formatUsd } from 'utils/helper';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Icon from 'react-native-vector-icons/FontAwesome5';
|
import Icon from 'react-native-vector-icons/FontAwesome5';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
import walletStyle from 'styles/wallet';
|
import walletStyle from 'styles/wallet';
|
||||||
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
claimsBalance: number,
|
claimsBalance: number,
|
||||||
|
@ -16,25 +17,37 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class WalletBalanceExtra extends React.PureComponent<Props> {
|
class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
|
state = {
|
||||||
|
usdExchangeRate: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { claimsBalance, deviceWalletSynced, supportsBalance, tipsBalance } = this.props;
|
const { claimsBalance, deviceWalletSynced, navigation, supportsBalance, tipsBalance } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={walletStyle.balanceExtra}>
|
<View style={walletStyle.balanceExtra}>
|
||||||
<View style={walletStyle.syncDriverCustody}>
|
<View style={walletStyle.usdInfoCard}>
|
||||||
<Text style={walletStyle.syncInfoText}>
|
<Text style={walletStyle.usdInfoText}>
|
||||||
{deviceWalletSynced
|
You can convert your credits to USD and withdraw the converted amount using an exchange.{' '}
|
||||||
? __('A backup of your wallet is synced with lbry.tv')
|
<Link
|
||||||
: __('Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.')}
|
style={walletStyle.usdConvertFaqLink}
|
||||||
|
href={'https://lbry.com/faq/exchanges'}
|
||||||
|
text={__('Learn more')}
|
||||||
|
/>
|
||||||
|
.
|
||||||
</Text>
|
</Text>
|
||||||
<Link
|
<Link
|
||||||
text={__('What does this mean?')}
|
style={walletStyle.usdConvertLink}
|
||||||
href={
|
href={'https://bittrex.com/Account/Register?referralCode=4M1-P30-BON'}
|
||||||
deviceWalletSynced
|
text={__('Convert credits to USD on Bittrex')}
|
||||||
? 'https://lbry.com/faq/account-sync'
|
|
||||||
: 'https://lbry.com/faq/how-to-backup-wallet#android'
|
|
||||||
}
|
|
||||||
style={walletStyle.syncInfoLink}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
@ -47,7 +60,18 @@ class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
<Text style={walletStyle.walletExtraBalance}>{formatCredits(parseFloat(tipsBalance), 2)}</Text>
|
||||||
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
<Text style={walletStyle.walletExtraCurrency}>LBC</Text>
|
||||||
</View>
|
</View>
|
||||||
|
<Text style={walletStyle.usdWalletExtraBalance}>
|
||||||
|
≈{formatUsd(parseFloat(tipsBalance) * parseFloat(this.state.usdExchangeRate))}
|
||||||
|
</Text>
|
||||||
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
<Text style={walletStyle.text}>{__('in tips')}</Text>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
style={walletStyle.earnTipsLink}
|
||||||
|
onPress={() => {
|
||||||
|
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_PUBLISH });
|
||||||
|
}}
|
||||||
|
text={__('Earn more tips by uploading cool videos')}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={walletStyle.walletExtraCol}>
|
<View style={walletStyle.walletExtraCol}>
|
||||||
|
@ -66,6 +90,23 @@ class WalletBalanceExtra extends React.PureComponent<Props> {
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<View style={walletStyle.syncDriverCustody}>
|
||||||
|
<Text style={walletStyle.syncInfoText}>
|
||||||
|
{deviceWalletSynced
|
||||||
|
? __('A backup of your wallet is synced with lbry.tv')
|
||||||
|
: __('Your wallet is not currently synced with lbry.tv. You are responsible for backing up your wallet.')}
|
||||||
|
</Text>
|
||||||
|
<Link
|
||||||
|
text={__('What does this mean?')}
|
||||||
|
href={
|
||||||
|
deviceWalletSynced
|
||||||
|
? 'https://lbry.com/faq/account-sync'
|
||||||
|
: 'https://lbry.com/faq/how-to-backup-wallet#android'
|
||||||
|
}
|
||||||
|
style={walletStyle.syncInfoLink}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Lbry } from 'lbry-redux';
|
import { Lbryio } from 'lbryinc';
|
||||||
import { ActivityIndicator, NativeModules, ScrollView, Text, View } from 'react-native';
|
import { ActivityIndicator, NativeModules, ScrollView, Text, View } from 'react-native';
|
||||||
import Colors from 'styles/colors';
|
import Colors from 'styles/colors';
|
||||||
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
import Constants from 'constants'; // eslint-disable-line node/no-deprecated-api
|
||||||
|
@ -17,13 +17,14 @@ const FILTER_CLAIMED = 'claimed';
|
||||||
|
|
||||||
class RewardsPage extends React.PureComponent {
|
class RewardsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
currentFilter: FILTER_AVAILABLE,
|
||||||
|
firstRewardClaimed: false,
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
isIdentityVerified: false,
|
isIdentityVerified: false,
|
||||||
isRewardApproved: false,
|
isRewardApproved: false,
|
||||||
verifyRequestStarted: false,
|
|
||||||
revealVerification: true,
|
revealVerification: true,
|
||||||
firstRewardClaimed: false,
|
usdExchangeRate: 0,
|
||||||
currentFilter: FILTER_AVAILABLE,
|
verifyRequestStarted: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
scrollView = null;
|
scrollView = null;
|
||||||
|
@ -48,6 +49,12 @@ class RewardsPage extends React.PureComponent {
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Rewards');
|
NativeModules.Firebase.setCurrentScreen('Rewards');
|
||||||
|
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fetchRewards();
|
fetchRewards();
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -158,6 +165,7 @@ class RewardsPage extends React.PureComponent {
|
||||||
canClaim={!isNotEligible}
|
canClaim={!isNotEligible}
|
||||||
reward={reward}
|
reward={reward}
|
||||||
reward_type={reward.reward_type}
|
reward_type={reward.reward_type}
|
||||||
|
usdExchangeRate={this.state.usdExchangeRate}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<CustomRewardCard canClaim={!isNotEligible} showVerification={this.showVerification} />
|
<CustomRewardCard canClaim={!isNotEligible} showVerification={this.showVerification} />
|
||||||
|
@ -211,7 +219,9 @@ class RewardsPage extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<View style={rewardStyle.container}>
|
<View style={rewardStyle.container}>
|
||||||
<UriBar navigation={navigation} />
|
<UriBar navigation={navigation} />
|
||||||
{(!this.state.isEmailVerified || !this.state.isRewardApproved) && <RewardEnrolment navigation={navigation} />}
|
{(!this.state.isEmailVerified || !this.state.isRewardApproved) && (
|
||||||
|
<RewardEnrolment usdExchangeRate={this.state.usdExchangeRate} navigation={navigation} />
|
||||||
|
)}
|
||||||
|
|
||||||
{this.state.isEmailVerified && this.state.isRewardApproved && (
|
{this.state.isEmailVerified && this.state.isRewardApproved && (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
selectViewMode,
|
selectViewMode,
|
||||||
selectFirstRunCompleted,
|
selectFirstRunCompleted,
|
||||||
selectShowSuggestedSubs,
|
selectShowSuggestedSubs,
|
||||||
|
selectUnclaimedRewardValue,
|
||||||
selectUser,
|
selectUser,
|
||||||
} from 'lbryinc';
|
} from 'lbryinc';
|
||||||
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
|
import { doToast, selectFetchingClaimSearch } from 'lbry-redux';
|
||||||
|
@ -33,9 +34,11 @@ const select = state => ({
|
||||||
unreadSubscriptions: selectUnreadSubscriptions(state),
|
unreadSubscriptions: selectUnreadSubscriptions(state),
|
||||||
viewMode: selectViewMode(state),
|
viewMode: selectViewMode(state),
|
||||||
firstRunCompleted: selectFirstRunCompleted(state),
|
firstRunCompleted: selectFirstRunCompleted(state),
|
||||||
|
rewardsNotInterested: makeSelectClientSetting(Constants.SETTING_REWARDS_NOT_INTERESTED)(state),
|
||||||
showSuggestedSubs: selectShowSuggestedSubs(state),
|
showSuggestedSubs: selectShowSuggestedSubs(state),
|
||||||
timeItem: selectTimeItem(state),
|
timeItem: selectTimeItem(state),
|
||||||
sdkReady: selectSdkReady(state),
|
sdkReady: selectSdkReady(state),
|
||||||
|
unclaimedRewardAmount: selectUnclaimedRewardValue(state),
|
||||||
user: selectUser(state),
|
user: selectUser(state),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
View,
|
View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { buildURI, parseURI } from 'lbry-redux';
|
import { buildURI, parseURI } from 'lbry-redux';
|
||||||
import { getOrderBy } from 'utils/helper';
|
import { formatUsd, getOrderBy } from 'utils/helper';
|
||||||
import AsyncStorage from '@react-native-community/async-storage';
|
import AsyncStorage from '@react-native-community/async-storage';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
@ -31,17 +31,21 @@ import SuggestedSubscriptions from 'component/suggestedSubscriptions';
|
||||||
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
import SuggestedSubscriptionsGrid from 'component/suggestedSubscriptionsGrid';
|
||||||
import UriBar from 'component/uriBar';
|
import UriBar from 'component/uriBar';
|
||||||
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
import SdkLoadingStatus from 'component/sdkLoadingStatus';
|
||||||
|
import Snackbar from 'react-native-snackbar';
|
||||||
|
import { Lbryio } from 'lbryinc';
|
||||||
|
|
||||||
class SubscriptionsPage extends React.PureComponent {
|
class SubscriptionsPage extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
|
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
||||||
|
filteredChannels: [],
|
||||||
|
orderBy: ['release_time'],
|
||||||
|
showRewardsNag: true,
|
||||||
showingSuggestedSubs: false,
|
showingSuggestedSubs: false,
|
||||||
showSortPicker: false,
|
showSortPicker: false,
|
||||||
showTimePicker: false,
|
showTimePicker: false,
|
||||||
showModalSuggestedSubs: false,
|
showModalSuggestedSubs: false,
|
||||||
|
usdExchangeRate: 0,
|
||||||
userEmailVerified: false,
|
userEmailVerified: false,
|
||||||
orderBy: ['release_time'],
|
|
||||||
filteredChannels: [],
|
|
||||||
currentSortByItem: Constants.CLAIM_SEARCH_SORT_BY_ITEMS[1], // should always default to sorting subscriptions by new
|
|
||||||
};
|
};
|
||||||
|
|
||||||
didFocusListener;
|
didFocusListener;
|
||||||
|
@ -58,15 +62,25 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onComponentFocused = () => {
|
onComponentFocused = () => {
|
||||||
const { currentRoute, doFetchMySubscriptions, pushDrawerStack, setPlayerVisible, user } = this.props;
|
const { currentRoute, doFetchMySubscriptions, pushDrawerStack, sdkReady, setPlayerVisible, user } = this.props;
|
||||||
|
|
||||||
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
|
if (currentRoute === Constants.DRAWER_ROUTE_SUBSCRIPTIONS) {
|
||||||
pushDrawerStack();
|
pushDrawerStack();
|
||||||
}
|
}
|
||||||
setPlayerVisible();
|
setPlayerVisible();
|
||||||
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
NativeModules.Firebase.setCurrentScreen('Subscriptions');
|
||||||
this.setState({ userEmailVerified: user && user.has_verified_email });
|
|
||||||
|
|
||||||
|
Lbryio.getExchangeRates().then(rates => {
|
||||||
|
if (!isNaN(rates.LBC_USD)) {
|
||||||
|
this.setState({ usdExchangeRate: rates.LBC_USD }, () => {
|
||||||
|
if (sdkReady && parseFloat(this.state.usdExchangeRate) > 0 && user && !user.is_reward_approved) {
|
||||||
|
this.showRewardsAvailable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({ userEmailVerified: user && user.has_verified_email });
|
||||||
doFetchMySubscriptions();
|
doFetchMySubscriptions();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,7 +89,7 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const { currentRoute, user } = nextProps;
|
const { currentRoute, user, sdkReady } = nextProps;
|
||||||
const { currentRoute: prevRoute, doFetchMySubscriptions } = this.props;
|
const { currentRoute: prevRoute, doFetchMySubscriptions } = this.props;
|
||||||
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
if (Constants.DRAWER_ROUTE_SUBSCRIPTIONS === currentRoute && currentRoute !== prevRoute) {
|
||||||
this.onComponentFocused();
|
this.onComponentFocused();
|
||||||
|
@ -88,9 +102,43 @@ class SubscriptionsPage extends React.PureComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
sdkReady &&
|
||||||
|
parseFloat(this.state.usdExchangeRate) > 0 &&
|
||||||
|
this.state.showRewardsNag &&
|
||||||
|
user &&
|
||||||
|
!user.is_reward_approved
|
||||||
|
) {
|
||||||
|
this.showRewardsAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
this.unsubscribeShortChannelUrls();
|
this.unsubscribeShortChannelUrls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showRewardsAvailable = () => {
|
||||||
|
const { navigation, unclaimedRewardAmount, rewardsNotInterested } = this.props;
|
||||||
|
if (rewardsNotInterested) {
|
||||||
|
this.setState({ showRewardsNag: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ showRewardsNag: false }, () => {
|
||||||
|
Snackbar.show({
|
||||||
|
title: __('Did you know that you can earn free credits worth up to %amount%?', {
|
||||||
|
amount: formatUsd(parseFloat(this.state.usdExchangeRate) * parseFloat(unclaimedRewardAmount)),
|
||||||
|
}),
|
||||||
|
duration: Snackbar.LENGTH_LONG,
|
||||||
|
action: {
|
||||||
|
title: __('SHOW ME'),
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
onPress: () => {
|
||||||
|
navigation.navigate({ routeName: Constants.DRAWER_ROUTE_REWARDS });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
handleSortByItemSelected = item => {
|
handleSortByItemSelected = item => {
|
||||||
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
this.setState({ currentSortByItem: item, orderBy: getOrderBy(item), showSortPicker: false });
|
||||||
};
|
};
|
||||||
|
|
|
@ -94,7 +94,7 @@ class WalletPage extends React.PureComponent {
|
||||||
>
|
>
|
||||||
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
{!rewardsNotInterested && (!balance || balance === 0) && <WalletRewardsDriver navigation={navigation} />}
|
||||||
<WalletBalance />
|
<WalletBalance />
|
||||||
<WalletBalanceExtra />
|
<WalletBalanceExtra navigation={navigation} />
|
||||||
<WalletAddress />
|
<WalletAddress />
|
||||||
<WalletSend />
|
<WalletSend />
|
||||||
<TransactionListRecent navigation={navigation} />
|
<TransactionListRecent navigation={navigation} />
|
||||||
|
|
|
@ -147,6 +147,10 @@ const rewardStyle = StyleSheet.create({
|
||||||
width: '18%',
|
width: '18%',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
|
rightColHeader: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
rewardAmount: {
|
rewardAmount: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
fontSize: 26,
|
fontSize: 26,
|
||||||
|
@ -154,6 +158,7 @@ const rewardStyle = StyleSheet.create({
|
||||||
},
|
},
|
||||||
rewardCurrency: {
|
rewardCurrency: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
},
|
},
|
||||||
rewardTitle: {
|
rewardTitle: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
|
@ -322,6 +327,12 @@ const rewardStyle = StyleSheet.create({
|
||||||
activeFilterLink: {
|
activeFilterLink: {
|
||||||
fontFamily: 'Inter-SemiBold',
|
fontFamily: 'Inter-SemiBold',
|
||||||
},
|
},
|
||||||
|
rewardUsd: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.DescriptionGrey,
|
||||||
|
marginTop: 6,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rewardStyle;
|
export default rewardStyle;
|
||||||
|
|
|
@ -192,8 +192,6 @@ const subscriptionsStyle = StyleSheet.create({
|
||||||
suggestedItem: {
|
suggestedItem: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
marginLeft: 16,
|
|
||||||
marginRight: 16,
|
|
||||||
height: 140,
|
height: 140,
|
||||||
},
|
},
|
||||||
suggestedItemThumbnailContainer: {
|
suggestedItemThumbnailContainer: {
|
||||||
|
@ -209,8 +207,8 @@ const subscriptionsStyle = StyleSheet.create({
|
||||||
height: '100%',
|
height: '100%',
|
||||||
},
|
},
|
||||||
suggestedItemDetails: {
|
suggestedItemDetails: {
|
||||||
marginLeft: 16,
|
marginLeft: 8,
|
||||||
marginRight: 16,
|
marginRight: 8,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
},
|
},
|
||||||
suggestedItemSubscribe: {
|
suggestedItemSubscribe: {
|
||||||
|
@ -229,7 +227,7 @@ const subscriptionsStyle = StyleSheet.create({
|
||||||
suggestedItemTitle: {
|
suggestedItemTitle: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
fontSize: 14,
|
fontSize: 13,
|
||||||
marginTop: 4,
|
marginTop: 4,
|
||||||
marginBottom: 2,
|
marginBottom: 2,
|
||||||
},
|
},
|
||||||
|
|
|
@ -23,7 +23,7 @@ const tagStyle = StyleSheet.create({
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
fontFamily: 'Inter-Regular',
|
fontFamily: 'Inter-Regular',
|
||||||
fontSize: 14,
|
fontSize: 12,
|
||||||
marginRight: 8,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
tagResultsList: {
|
tagResultsList: {
|
||||||
|
|
|
@ -137,6 +137,13 @@ const walletStyle = StyleSheet.create({
|
||||||
fontFamily: 'Inter-Bold',
|
fontFamily: 'Inter-Bold',
|
||||||
fontSize: 36,
|
fontSize: 36,
|
||||||
marginLeft: 16,
|
marginLeft: 16,
|
||||||
|
},
|
||||||
|
usdBalance: {
|
||||||
|
color: Colors.White,
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 20,
|
||||||
|
marginLeft: 16,
|
||||||
|
marginTop: 2,
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
balanceFocus: {
|
balanceFocus: {
|
||||||
|
@ -402,6 +409,11 @@ const walletStyle = StyleSheet.create({
|
||||||
fontFamily: 'Inter-SemiBold',
|
fontFamily: 'Inter-SemiBold',
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
},
|
},
|
||||||
|
usdWalletExtraBalance: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.DescriptionGrey,
|
||||||
|
},
|
||||||
balanceRow: {
|
balanceRow: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
@ -424,6 +436,34 @@ const walletStyle = StyleSheet.create({
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
},
|
},
|
||||||
|
usdInfoCard: {
|
||||||
|
backgroundColor: Colors.White,
|
||||||
|
padding: 16,
|
||||||
|
borderBottomColor: Colors.VeryLightGrey,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
usdInfoText: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
usdConvertLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
usdConvertFaqLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
},
|
||||||
|
earnTipsLink: {
|
||||||
|
fontFamily: 'Inter-Regular',
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.LbryGreen,
|
||||||
|
marginTop: 12,
|
||||||
|
marginRight: 16,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default walletStyle;
|
export default walletStyle;
|
||||||
|
|
|
@ -436,3 +436,10 @@ export function fetchReferralCode(successCallback, errorCallback) {
|
||||||
export function decode(value) {
|
export function decode(value) {
|
||||||
return decodeURIComponent(value).replace(/\+/g, ' ');
|
return decodeURIComponent(value).replace(/\+/g, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatUsd(value) {
|
||||||
|
if (isNaN(parseFloat(value))) {
|
||||||
|
value = 0;
|
||||||
|
}
|
||||||
|
return '$' + parseFloat(value).toFixed(2);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue