Chore desktop cleanup #6896

Merged
jessopb merged 8 commits from chore-desktopCleanup into master 2021-08-18 00:34:17 +02:00
15 changed files with 464 additions and 448 deletions

View file

@ -19,7 +19,7 @@ THUMBNAIL_CDN_URL=https://image-processor.vanwanet.com/optimize/
WELCOME_VERSION=1.0 WELCOME_VERSION=1.0
# STRIPE # STRIPE
STRIPE_PUBLIC_KEY='pk_test_NoL1JWL7i1ipfhVId5KfDZgo' # STRIPE_PUBLIC_KEY='pk_test_NoL1JWL7i1ipfhVId5KfDZgo'
# Analytics # Analytics
MATOMO_URL=https://analytics.lbry.com/ MATOMO_URL=https://analytics.lbry.com/

View file

@ -2090,5 +2090,8 @@
"Expand Comments": "Expand Comments", "Expand Comments": "Expand Comments",
"Expand": "Expand", "Expand": "Expand",
"Load More": "Load More", "Load More": "Load More",
"Collection": "Collection",
"%channelName% isn't live right now, but the chat is! Check back later to watch the stream.": "%channelName% isn't live right now, but the chat is! Check back later to watch the stream.",
"Review": "Review",
"--end--": "--end--" "--end--": "--end--"
} }

View file

@ -1,6 +1,6 @@
// @flow // @flow
import type { ElementRef } from 'react'; import type { ElementRef } from 'react';
import { SIMPLE_SITE, STRIPE_PUBLIC_KEY } from 'config'; import { SIMPLE_SITE } from 'config';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import React from 'react'; import React from 'react';
@ -21,12 +21,8 @@ import Empty from 'component/common/empty';
import { getChannelIdFromClaim } from 'util/claim'; import { getChannelIdFromClaim } from 'util/claim';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
let stripeEnvironment = 'test'; import { getStripeEnvironment } from 'util/stripe';
// if the key contains pk_live it's a live key let stripeEnvironment = getStripeEnvironment();
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
const TAB_FIAT = 'TabFiat'; const TAB_FIAT = 'TabFiat';
const TAB_LBC = 'TabLBC'; const TAB_LBC = 'TabLBC';
@ -245,10 +241,13 @@ export function CommentCreate(props: Props) {
}, 1500); }, 1500);
doToast({ doToast({
message: __("You sent %tipAmount% LBRY Credits as a tip to %tipChannelName%, I'm sure they appreciate it!", { message: __(
tipAmount: tipAmount, // force show decimal places "You sent %tipAmount% LBRY Credits as a tip to %tipChannelName%, I'm sure they appreciate it!",
tipChannelName, {
}), tipAmount: tipAmount, // force show decimal places
tipChannelName,
}
),
}); });
setSuccessTip({ txid, tipAmount }); setSuccessTip({ txid, tipAmount });
@ -265,7 +264,8 @@ export function CommentCreate(props: Props) {
Lbryio.call( Lbryio.call(
'customer', 'customer',
'tip', 'tip',
{ // round to deal with floating point precision {
// round to deal with floating point precision
amount: Math.round(100 * roundedAmount), // convert from dollars to cents amount: Math.round(100 * roundedAmount), // convert from dollars to cents
creator_channel_name: tipChannelName, // creator_channel_name creator_channel_name: tipChannelName, // creator_channel_name
creator_channel_claim_id: channelClaimId, creator_channel_claim_id: channelClaimId,
@ -387,12 +387,7 @@ export function CommentCreate(props: Props) {
} }
}} }}
> >
<FormField <FormField type="textarea" name={'comment_signup_prompt'} placeholder={__('Say something about this...')} />
type="textarea"
name={'comment_signup_prompt'}
placeholder={__('Say something about this...')}
label={isFetchingChannels ? __('Comment') : undefined}
/>
<div className="section__actions--no-margin"> <div className="section__actions--no-margin">
<Button disabled button="primary" label={__('Post --[button to submit something]--')} requiresAuth={IS_WEB} /> <Button disabled button="primary" label={__('Post --[button to submit something]--')} requiresAuth={IS_WEB} />
</div> </div>
@ -534,7 +529,8 @@ export function CommentCreate(props: Props) {
}} }}
/> />
)} )}
{!claimIsMine && ( {/* @if TARGET='web' */}
{!claimIsMine && stripeEnvironment && (
<Button <Button
disabled={disabled} disabled={disabled}
button="alt" button="alt"
@ -546,6 +542,7 @@ export function CommentCreate(props: Props) {
}} }}
/> />
)} )}
{/* @endif */}
{isReply && !minTip && ( {isReply && !minTip && (
<Button <Button
button="link" button="link"

View file

@ -4,14 +4,8 @@ import Button from 'component/button';
import Card from 'component/common/card'; import Card from 'component/common/card';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import moment from 'moment'; import moment from 'moment';
import { STRIPE_PUBLIC_KEY } from 'config'; import { getStripeEnvironment } from 'util/stripe';
let stripeEnvironment = getStripeEnvironment();
let stripeEnvironment = 'test';
// if the key contains pk_live it's a live key
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
type Props = { type Props = {
accountDetails: any, accountDetails: any,
@ -41,12 +35,15 @@ const WalletBalance = (props: Props) => {
// TODO: this is actually incorrect, last4 should be populated based on the transaction not the current customer details // TODO: this is actually incorrect, last4 should be populated based on the transaction not the current customer details
React.useEffect(() => { React.useEffect(() => {
(async function() { (async function () {
const customerStatusResponse = await getCustomerStatus(); const customerStatusResponse = await getCustomerStatus();
const lastFour = customerStatusResponse.PaymentMethods && customerStatusResponse.PaymentMethods.length && customerStatusResponse.PaymentMethods[0].card.last4; const lastFour =
customerStatusResponse.PaymentMethods &&
customerStatusResponse.PaymentMethods.length &&
customerStatusResponse.PaymentMethods[0].card.last4;
setLastFour(lastFour); setLastFour(lastFour);
})(); })();
}, []); }, []);
@ -59,53 +56,57 @@ const WalletBalance = (props: Props) => {
<div className="table__wrapper"> <div className="table__wrapper">
<table className="table table--transactions"> <table className="table table--transactions">
<thead> <thead>
<tr> <tr>
<th className="date-header">{__('Date')}</th> <th className="date-header">{__('Date')}</th>
<th>{<>{__('Receiving Channel Name')}</>}</th> <th>{<>{__('Receiving Channel Name')}</>}</th>
<th>{__('Tip Location')}</th> <th>{__('Tip Location')}</th>
<th>{__('Amount (USD)')} </th> <th>{__('Amount (USD)')} </th>
<th>{__('Card Last 4')}</th> <th>{__('Card Last 4')}</th>
<th>{__('Anonymous')}</th> <th>{__('Anonymous')}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{accountTransactions && {accountTransactions &&
accountTransactions.map((transaction) => ( accountTransactions.map((transaction) => (
<tr key={transaction.name + transaction.created_at}> <tr key={transaction.name + transaction.created_at}>
<td>{moment(transaction.created_at).format('LLL')}</td> <td>{moment(transaction.created_at).format('LLL')}</td>
<td> <td>
<Button <Button
className="" className=""
navigate={'/' + transaction.channel_name + ':' + transaction.channel_claim_id} navigate={'/' + transaction.channel_name + ':' + transaction.channel_claim_id}
label={transaction.channel_name} label={transaction.channel_name}
button="link" button="link"
/> />
</td> </td>
<td> <td>
<Button <Button
className="" className=""
navigate={'/' + transaction.channel_name + ':' + transaction.source_claim_id} navigate={'/' + transaction.channel_name + ':' + transaction.source_claim_id}
label={ label={
transaction.channel_claim_id === transaction.source_claim_id transaction.channel_claim_id === transaction.source_claim_id
? 'Channel Page' ? 'Channel Page'
: 'Content Page' : 'Content Page'
} }
button="link" button="link"
/> />
</td> </td>
<td>${transaction.tipped_amount / 100}</td> <td>${transaction.tipped_amount / 100}</td>
<td>{lastFour}</td> <td>{lastFour}</td>
<td>{transaction.private_tip ? 'Yes' : 'No'}</td> <td>{transaction.private_tip ? 'Yes' : 'No'}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
{(!accountTransactions || accountTransactions.length === 0) && <p style={{textAlign: 'center', marginTop: '20px', fontSize: '13px', color: 'rgb(171, 171, 171)'}}>No Transactions</p>} {(!accountTransactions || accountTransactions.length === 0) && (
<p style={{ textAlign: 'center', marginTop: '20px', fontSize: '13px', color: 'rgb(171, 171, 171)' }}>
No Transactions
</p>
)}
</div> </div>
</> </>
} }
/> />
</> </>
); );
}; };

View file

@ -15,14 +15,8 @@ import LbcSymbol from 'component/common/lbc-symbol';
import { parseURI } from 'lbry-redux'; import { parseURI } from 'lbry-redux';
import usePersistedState from 'effects/use-persisted-state'; import usePersistedState from 'effects/use-persisted-state';
import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp'; import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp';
import { STRIPE_PUBLIC_KEY } from 'config'; import { getStripeEnvironment } from 'util/stripe';
let stripeEnvironment = getStripeEnvironment();
let stripeEnvironment = 'test';
// if the key contains pk_live it's a live key
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
const DEFAULT_TIP_AMOUNTS = [1, 5, 25, 100]; const DEFAULT_TIP_AMOUNTS = [1, 5, 25, 100];
const MINIMUM_FIAT_TIP = 1; const MINIMUM_FIAT_TIP = 1;
@ -100,7 +94,7 @@ function WalletSendTip(props: Props) {
// check if creator has a payment method saved // check if creator has a payment method saved
React.useEffect(() => { React.useEffect(() => {
if (channelClaimId && isAuthenticated) { if (channelClaimId && isAuthenticated && stripeEnvironment) {
Lbryio.call( Lbryio.call(
'customer', 'customer',
'status', 'status',
@ -118,16 +112,18 @@ function WalletSendTip(props: Props) {
setHasSavedCard(Boolean(defaultPaymentMethodId)); setHasSavedCard(Boolean(defaultPaymentMethodId));
}); });
} }
}, [channelClaimId, isAuthenticated]); }, [channelClaimId, isAuthenticated, stripeEnvironment]);
// check if creator has an account saved // check if creator has an account saved
React.useEffect(() => { React.useEffect(() => {
const tipInputElement = document.getElementById('tip-input'); const tipInputElement = document.getElementById('tip-input');
if (tipInputElement) { tipInputElement.focus() } if (tipInputElement) {
tipInputElement.focus();
}
}, []); }, []);
React.useEffect(() => { React.useEffect(() => {
if (channelClaimId) { if (channelClaimId && stripeEnvironment) {
Lbryio.call( Lbryio.call(
'account', 'account',
'check', 'check',
@ -149,14 +145,14 @@ function WalletSendTip(props: Props) {
// console.log(error); // console.log(error);
}); });
} }
}, [channelClaimId]); }, [channelClaimId, stripeEnvironment]);
const noBalance = balance === 0; const noBalance = balance === 0;
const tipAmount = useCustomTip ? customTipAmount : presetTipAmount; const tipAmount = useCustomTip ? customTipAmount : presetTipAmount;
const [activeTab, setActiveTab] = React.useState(claimIsMine ? TAB_BOOST : TAB_LBC); const [activeTab, setActiveTab] = React.useState(claimIsMine ? TAB_BOOST : TAB_LBC);
function setClaimTypeText() { function getClaimTypeText() {
if (claim.value_type === 'stream') { if (claim.value_type === 'stream') {
return __('Content'); return __('Content');
} else if (claim.value_type === 'channel') { } else if (claim.value_type === 'channel') {
@ -169,22 +165,24 @@ function WalletSendTip(props: Props) {
return __('Claim'); return __('Claim');
} }
} }
const claimTypeText = setClaimTypeText(); const claimTypeText = getClaimTypeText();
let iconToUse; let iconToUse;
let explainerText = ''; let explainerText = '';
if (activeTab === TAB_BOOST) { if (activeTab === TAB_BOOST) {
iconToUse = ICONS.LBC; iconToUse = ICONS.LBC;
explainerText = __('This refundable boost will improve the discoverability of this %claimTypeText% while active.', {claimTypeText}); explainerText = __('This refundable boost will improve the discoverability of this %claimTypeText% while active.', {
claimTypeText,
});
} else if (activeTab === TAB_FIAT) { } else if (activeTab === TAB_FIAT) {
iconToUse = ICONS.FINANCE; iconToUse = ICONS.FINANCE;
explainerText = __('Show this channel your appreciation by sending a donation in USD. '); explainerText = __('Show this channel your appreciation by sending a donation in USD.');
// if (!hasCardSaved) { // if (!hasCardSaved) {
// explainerText += __('You must add a card to use this functionality.'); // explainerText += __('You must add a card to use this functionality.');
// } // }
} else if (activeTab === TAB_LBC) { } else if (activeTab === TAB_LBC) {
iconToUse = ICONS.LBC; iconToUse = ICONS.LBC;
explainerText = __('Show this channel your appreciation by sending a donation of Credits. '); explainerText = __('Show this channel your appreciation by sending a donation of Credits.');
} }
const isSupport = claimIsMine || activeTab === TAB_BOOST; const isSupport = claimIsMine || activeTab === TAB_BOOST;
@ -216,7 +214,7 @@ function WalletSendTip(props: Props) {
} else if (tipAmount < MINIMUM_PUBLISH_BID) { } else if (tipAmount < MINIMUM_PUBLISH_BID) {
tipError = __('Amount must be higher'); tipError = __('Amount must be higher');
} }
// if tip fiat tab // if tip fiat tab
} else { } else {
regexp = RegExp(/^(\d*([.]\d{0,2})?)$/); regexp = RegExp(/^(\d*([.]\d{0,2})?)$/);
const validTipInput = regexp.test(String(tipAmount)); const validTipInput = regexp.test(String(tipAmount));
@ -276,7 +274,8 @@ function WalletSendTip(props: Props) {
Lbryio.call( Lbryio.call(
'customer', 'customer',
'tip', 'tip',
{ // round to fix issues with floating point numbers {
// round to fix issues with floating point numbers
amount: Math.round(100 * tipAmount), // convert from dollars to cents amount: Math.round(100 * tipAmount), // convert from dollars to cents
creator_channel_name: tipChannelName, // creator_channel_name creator_channel_name: tipChannelName, // creator_channel_name
creator_channel_claim_id: channelClaimId, creator_channel_claim_id: channelClaimId,
@ -297,7 +296,7 @@ function WalletSendTip(props: Props) {
}), }),
}); });
}) })
.catch(function(error) { .catch(function (error) {
let displayError = 'Sorry, there was an error in processing your payment!'; let displayError = 'Sorry, there was an error in processing your payment!';
if (error.message !== 'payment intent failed to confirm') { if (error.message !== 'payment intent failed to confirm') {
@ -316,10 +315,10 @@ function WalletSendTip(props: Props) {
} }
} }
const countDecimals = function(value) { const countDecimals = function (value) {
const text = value.toString(); const text = value.toString();
const index = text.indexOf('.'); const index = text.indexOf('.');
return (text.length - index - 1); return text.length - index - 1;
}; };
function handleCustomPriceChange(event: SyntheticInputEvent<*>) { function handleCustomPriceChange(event: SyntheticInputEvent<*>) {
@ -387,7 +386,9 @@ function WalletSendTip(props: Props) {
const displayAmount = !isNan(tipAmount) ? amountToShow : ''; const displayAmount = !isNan(tipAmount) ? amountToShow : '';
if (activeTab === TAB_BOOST) { if (activeTab === TAB_BOOST) {
return (claimIsMine ? __('Boost Your %claimTypeText%', {claimTypeText}) : __('Boost This %claimTypeText%', {claimTypeText})); return claimIsMine
? __('Boost Your %claimTypeText%', { claimTypeText })
: __('Boost This %claimTypeText%', { claimTypeText });
} else if (activeTab === TAB_FIAT) { } else if (activeTab === TAB_FIAT) {
return __('Send a $%displayAmount% Tip', { displayAmount }); return __('Send a $%displayAmount% Tip', { displayAmount });
} else if (activeTab === TAB_LBC) { } else if (activeTab === TAB_LBC) {
@ -416,7 +417,16 @@ function WalletSendTip(props: Props) {
{/* if there is no LBC balance, show user frontend to get credits */} {/* if there is no LBC balance, show user frontend to get credits */}
{/* if there is lbc, the main tip/boost gui with the 3 tabs at the top */} {/* if there is lbc, the main tip/boost gui with the 3 tabs at the top */}
<Card <Card
title={<LbcSymbol postfix={claimIsMine ? __('Boost Your %claimTypeText%', {claimTypeText}) : __('Support This %claimTypeText%', {claimTypeText})} size={22} />} title={
<LbcSymbol
postfix={
claimIsMine
? __('Boost Your %claimTypeText%', { claimTypeText })
: __('Support This %claimTypeText%', { claimTypeText })
}
size={22}
/>
}
subtitle={ subtitle={
<React.Fragment> <React.Fragment>
{!claimIsMine && ( {!claimIsMine && (
@ -429,7 +439,9 @@ function WalletSendTip(props: Props) {
button="alt" button="alt"
onClick={() => { onClick={() => {
const tipInputElement = document.getElementById('tip-input'); const tipInputElement = document.getElementById('tip-input');
if (tipInputElement) { tipInputElement.focus() } if (tipInputElement) {
tipInputElement.focus();
}
if (!isConfirming) { if (!isConfirming) {
setActiveTab(TAB_LBC); setActiveTab(TAB_LBC);
} }
@ -438,20 +450,24 @@ function WalletSendTip(props: Props) {
/> />
{/* tip fiat tab button */} {/* tip fiat tab button */}
{/* @if TARGET='web' */} {/* @if TARGET='web' */}
<Button {stripeEnvironment && (
key="tip-fiat" <Button
icon={ICONS.FINANCE} key="tip-fiat"
label={__('Tip')} icon={ICONS.FINANCE}
button="alt" label={__('Tip')}
onClick={() => { button="alt"
const tipInputElement = document.getElementById('tip-input'); onClick={() => {
if (tipInputElement) { tipInputElement.focus() } const tipInputElement = document.getElementById('tip-input');
if (!isConfirming) { if (tipInputElement) {
setActiveTab(TAB_FIAT); tipInputElement.focus();
} }
}} if (!isConfirming) {
className={classnames('button-toggle', { 'button-toggle--active': activeTab === TAB_FIAT })} setActiveTab(TAB_FIAT);
/> }
}}
className={classnames('button-toggle', { 'button-toggle--active': activeTab === TAB_FIAT })}
/>
)}
{/* @endif */} {/* @endif */}
{/* tip LBC tab button */} {/* tip LBC tab button */}
<Button <Button
@ -461,7 +477,9 @@ function WalletSendTip(props: Props) {
button="alt" button="alt"
onClick={() => { onClick={() => {
const tipInputElement = document.getElementById('tip-input'); const tipInputElement = document.getElementById('tip-input');
if (tipInputElement) { tipInputElement.focus() } if (tipInputElement) {
tipInputElement.focus();
}
if (!isConfirming) { if (!isConfirming) {
setActiveTab(TAB_BOOST); setActiveTab(TAB_BOOST);
} }
@ -493,33 +511,29 @@ function WalletSendTip(props: Props) {
</div> </div>
<div className="confirm__label">{setConfirmLabel()}</div> <div className="confirm__label">{setConfirmLabel()}</div>
<div className="confirm__value"> <div className="confirm__value">
{activeTab === TAB_FIAT ? <p>$ {(Math.round(tipAmount * 100) / 100).toFixed(2)}</p> : <LbcSymbol postfix={tipAmount} size={22} />} {activeTab === TAB_FIAT ? (
<p>$ {(Math.round(tipAmount * 100) / 100).toFixed(2)}</p>
) : (
<LbcSymbol postfix={tipAmount} size={22} />
)}
</div> </div>
</div> </div>
</div> </div>
<div className="section__actions"> <div className="section__actions">
<Button <Button autoFocus onClick={handleSubmit} button="primary" disabled={isPending} label={__('Confirm')} />
autoFocus
onClick={handleSubmit}
button="primary"
disabled={isPending}
label={__('Confirm')}
/>
<Button button="link" label={__('Cancel')} onClick={() => setIsConfirming(false)} /> <Button button="link" label={__('Cancel')} onClick={() => setIsConfirming(false)} />
</div> </div>
</> </>
// only show the prompt to earn more if its lbc or boost tab and no balance ) : !((activeTab === TAB_LBC || activeTab === TAB_BOOST) && noBalance) ? (
// otherwise you can show the full prompt <>
) : (!((activeTab === TAB_LBC || activeTab === TAB_BOOST) && noBalance)
? <>
<div className="section"> <div className="section">
<ChannelSelector /> <ChannelSelector />
</div> </div>
{activeTab === TAB_FIAT && !hasCardSaved && ( {activeTab === TAB_FIAT && !hasCardSaved && (
<h3 className="add-card-prompt"> <h3 className="add-card-prompt">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card')} button="link" /> <Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card')} button="link" />{' '}
{' '}{__('To Tip Creators')} {__('To Tip Creators')}
</h3> </h3>
)} )}
@ -625,28 +639,36 @@ function WalletSendTip(props: Props) {
<div className="help">{__('The payment will be made from your saved card')}</div> <div className="help">{__('The payment will be made from your saved card')}</div>
)} )}
</> </>
// if it's LBC and there is no balance, you can prompt to purchase LBC ) : (
: <Card // if it's LBC and there is no balance, you can prompt to purchase LBC
title={<I18nMessage tokens={{ lbc: <LbcSymbol size={22} /> }}>Supporting content requires %lbc%</I18nMessage>} <Card
subtitle={ title={
<I18nMessage tokens={{ lbc: <LbcSymbol /> }}> <I18nMessage tokens={{ lbc: <LbcSymbol size={22} /> }}>Supporting content requires %lbc%</I18nMessage>
With %lbc%, you can send tips to your favorite creators, or help boost their content for more people to }
see. subtitle={
</I18nMessage> <I18nMessage tokens={{ lbc: <LbcSymbol /> }}>
} With %lbc%, you can send tips to your favorite creators, or help boost their content for more people
actions={ to see.
<div className="section__actions"> </I18nMessage>
<Button }
icon={ICONS.REWARDS} actions={
button="primary" <div className="section__actions">
label={__('Earn Rewards')} <Button
navigate={`/$/${PAGES.REWARDS}`} icon={ICONS.REWARDS}
/> button="primary"
<Button icon={ICONS.BUY} button="secondary" label={__('Buy/Swap Credits')} navigate={`/$/${PAGES.BUY}`} /> label={__('Earn Rewards')}
<Button button="link" label={__('Nevermind')} onClick={closeModal} /> navigate={`/$/${PAGES.REWARDS}`}
</div> />
} <Button
/> icon={ICONS.BUY}
button="secondary"
label={__('Buy/Swap Credits')}
navigate={`/$/${PAGES.BUY}`}
/>
<Button button="link" label={__('Nevermind')} onClick={closeModal} />
</div>
}
/>
) )
} }
/> />

View file

@ -11,14 +11,8 @@ import classnames from 'classnames';
import usePersistedState from 'effects/use-persisted-state'; import usePersistedState from 'effects/use-persisted-state';
import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp'; import WalletSpendableBalanceHelp from 'component/walletSpendableBalanceHelp';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { STRIPE_PUBLIC_KEY } from 'config'; import { getStripeEnvironment } from 'util/stripe';
let stripeEnvironment = getStripeEnvironment();
let stripeEnvironment = 'test';
// if the key contains pk_live it's a live key
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
const DEFAULT_TIP_AMOUNTS = [1, 5, 25, 100]; const DEFAULT_TIP_AMOUNTS = [1, 5, 25, 100];
@ -76,45 +70,49 @@ function WalletTipAmountSelector(props: Props) {
// check if creator has a payment method saved // check if creator has a payment method saved
React.useEffect(() => { React.useEffect(() => {
Lbryio.call( if (stripeEnvironment) {
'customer', Lbryio.call(
'status', 'customer',
{ 'status',
environment: stripeEnvironment, {
}, environment: stripeEnvironment,
'post' },
).then((customerStatusResponse) => { 'post'
const defaultPaymentMethodId = ).then((customerStatusResponse) => {
customerStatusResponse.Customer && const defaultPaymentMethodId =
customerStatusResponse.Customer.invoice_settings && customerStatusResponse.Customer &&
customerStatusResponse.Customer.invoice_settings.default_payment_method && customerStatusResponse.Customer.invoice_settings &&
customerStatusResponse.Customer.invoice_settings.default_payment_method.id; customerStatusResponse.Customer.invoice_settings.default_payment_method &&
customerStatusResponse.Customer.invoice_settings.default_payment_method.id;
setHasSavedCard(Boolean(defaultPaymentMethodId)); setHasSavedCard(Boolean(defaultPaymentMethodId));
}); });
}, []); }
}, [stripeEnvironment]);
// //
React.useEffect(() => { React.useEffect(() => {
Lbryio.call( if (stripeEnvironment) {
'account', Lbryio.call(
'check', 'account',
{ 'check',
channel_claim_id: channelClaimId, {
channel_name: tipChannelName, channel_claim_id: channelClaimId,
environment: stripeEnvironment, channel_name: tipChannelName,
}, environment: stripeEnvironment,
'post' },
) 'post'
.then((accountCheckResponse) => { )
if (accountCheckResponse === true && canReceiveFiatTip !== true) { .then((accountCheckResponse) => {
setCanReceiveFiatTip(true); if (accountCheckResponse === true && canReceiveFiatTip !== true) {
} setCanReceiveFiatTip(true);
}) }
.catch(function (error) { })
// console.log(error); .catch(function (error) {
}); // console.log(error);
}, []); });
}
}, [stripeEnvironment]);
React.useEffect(() => { React.useEffect(() => {
// setHasSavedCard(false); // setHasSavedCard(false);
@ -214,7 +212,7 @@ function WalletTipAmountSelector(props: Props) {
<div className="help"> <div className="help">
<span className="help--spendable"> <span className="help--spendable">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To{' '} <Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To{' '}
{__(' Tip Creators')} {__('Tip Creators')}
</span> </span>
</div> </div>
</> </>
@ -282,7 +280,7 @@ function WalletTipAmountSelector(props: Props) {
<div className="help"> <div className="help">
<span className="help--spendable"> <span className="help--spendable">
<Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To{' '} <Button navigate={`/$/${PAGES.SETTINGS_STRIPE_CARD}`} label={__('Add a Card ')} button="link" /> To{' '}
{__(' Tip Creators')} {__('Tip Creators')}
</span> </span>
</div> </div>
</> </>

2
ui/constants/stripe.js Normal file
View file

@ -0,0 +1,2 @@
export const TEST = 'test';
export const LIVE = 'live';

View file

@ -5,43 +5,19 @@ import Card from 'component/common/card';
import Button from 'component/button'; import Button from 'component/button';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { STRIPE_PUBLIC_KEY } from 'config'; import { getStripeEnvironment } from 'util/stripe';
let stripeEnvironment = getStripeEnvironment();
let stripeEnvironment = 'test';
// if the key contains pk_live it's a live key
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
type Props = { type Props = {
closeModal: () => void, closeModal: () => void,
abandonTxo: (Txo, () => void) => void,
abandonClaim: (string, number, ?() => void) => void,
tx: Txo,
claim: GenericClaim,
cb: () => void,
doResolveUri: (string) => void,
uri: string,
paymentMethodId: string, paymentMethodId: string,
setAsConfirmingCard: () => void, setAsConfirmingCard: () => void, // ?
}; };
export default function ModalRevokeClaim(props: Props) { export default function ModalRemoveCard(props: Props) {
var that = this; const { closeModal, paymentMethodId } = props;
console.log(that);
console.log(props);
const { closeModal, uri, paymentMethodId, setAsConfirmingCard } = props;
console.log(uri);
console.log(setAsConfirmingCard);
function removeCard() { function removeCard() {
console.log(paymentMethodId);
Lbryio.call( Lbryio.call(
'customer', 'customer',
'detach', 'detach',
@ -51,11 +27,9 @@ export default function ModalRevokeClaim(props: Props) {
}, },
'post' 'post'
).then((removeCardResponse) => { ).then((removeCardResponse) => {
console.log(removeCardResponse);
// TODO: add toast here // TODO: add toast here
// closeModal(); // closeModal();
// Is there a better way to handle this? Why reload?
window.location.reload(); window.location.reload();
}); });
} }
@ -63,15 +37,14 @@ export default function ModalRevokeClaim(props: Props) {
return ( return (
<Modal ariaHideApp={false} isOpen contentLabel={'hello'} type="card" onAborted={closeModal}> <Modal ariaHideApp={false} isOpen contentLabel={'hello'} type="card" onAborted={closeModal}>
<Card <Card
title={'Confirm Remove Card'} title={__('Confirm Remove Card')}
// body={getMsgBody(type, isSupport, name)}
actions={ actions={
<div className="section__actions"> <div className="section__actions">
<Button <Button
className="stripe__confirm-remove-card" className="stripe__confirm-remove-card"
button="secondary" button="secondary"
icon={ICONS.DELETE} icon={ICONS.DELETE}
label={'Remove Card'} label={__('Remove Card')}
onClick={removeCard} onClick={removeCard}
/> />
<Button button="link" label={__('Cancel')} onClick={closeModal} /> <Button button="link" label={__('Cancel')} onClick={closeModal} />

View file

@ -12,7 +12,6 @@ import FileRenderDownload from 'component/fileRenderDownload';
import RecommendedContent from 'component/recommendedContent'; import RecommendedContent from 'component/recommendedContent';
import CollectionContent from 'component/collectionContentSidebar'; import CollectionContent from 'component/collectionContentSidebar';
import CommentsList from 'component/commentsList'; import CommentsList from 'component/commentsList';
import { Redirect } from 'react-router';
import Button from 'component/button'; import Button from 'component/button';
import I18nMessage from 'component/i18nMessage'; import I18nMessage from 'component/i18nMessage';
import Empty from 'component/common/empty'; import Empty from 'component/common/empty';
@ -145,10 +144,6 @@ function FilePage(props: Props) {
); );
} }
if (!claimIsMine && isLivestream) {
return <Redirect to={`/$/${PAGES.LIVESTREAM}`} />;
}
if (obscureNsfw && isMature) { if (obscureNsfw && isMature) {
return ( return (
<Page className="file-page" filePage isMarkdown={isMarkdown}> <Page className="file-page" filePage isMarkdown={isMarkdown}>

View file

@ -20,6 +20,7 @@ import { SIMPLE_SITE } from 'config';
import homepages from 'homepages'; import homepages from 'homepages';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import Yrbl from 'component/yrbl'; import Yrbl from 'component/yrbl';
import { getStripeEnvironment } from 'util/stripe';
type Price = { type Price = {
currency: string, currency: string,
@ -451,7 +452,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
{/* @endif */} {/* @endif */}
{/* @if TARGET='web' */} {/* @if TARGET='web' */}
{user && ( {user && getStripeEnvironment() && (
<Card <Card
title={__('Bank Accounts')} title={__('Bank Accounts')}
subtitle={__('Connect a bank account to receive tips and compensation in your local currency')} subtitle={__('Connect a bank account to receive tips and compensation in your local currency')}
@ -470,7 +471,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
{/* @endif */} {/* @endif */}
{/* @if TARGET='web' */} {/* @if TARGET='web' */}
{isAuthenticated && ( {isAuthenticated && getStripeEnvironment() && (
<Card <Card
title={__('Payment Methods')} title={__('Payment Methods')}
subtitle={__('Add a credit card to tip creators in their local currency')} subtitle={__('Add a credit card to tip creators in their local currency')}

View file

@ -7,17 +7,12 @@ import Card from 'component/common/card';
import Page from 'component/page'; import Page from 'component/page';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { URL, WEBPACK_WEB_PORT, STRIPE_PUBLIC_KEY } from 'config'; import { URL, WEBPACK_WEB_PORT } from 'config';
import { getStripeEnvironment } from 'util/stripe';
const isDev = process.env.NODE_ENV !== 'production'; const isDev = process.env.NODE_ENV !== 'production';
let stripeEnvironment = 'test'; let stripeEnvironment = getStripeEnvironment();
// if the key contains pk_live it's a live key
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
let successStripeRedirectUrl, failureStripeRedirectUrl; let successStripeRedirectUrl, failureStripeRedirectUrl;
let successEndpoint = '/$/settings/tip_account'; let successEndpoint = '/$/settings/tip_account';
let failureEndpoint = '/$/settings/tip_account'; let failureEndpoint = '/$/settings/tip_account';
@ -46,7 +41,7 @@ type State = {
unpaidBalance: number, unpaidBalance: number,
pageTitle: string, pageTitle: string,
stillRequiringVerification: boolean, stillRequiringVerification: boolean,
accountTransactions: any accountTransactions: any,
}; };
class StripeAccountConnection extends React.Component<Props, State> { class StripeAccountConnection extends React.Component<Props, State> {
@ -144,7 +139,10 @@ class StripeAccountConnection extends React.Component<Props, State> {
stillRequiringVerification: false, stillRequiringVerification: false,
}; };
if ((eventuallyDueInformation && eventuallyDueInformation.length) || (currentlyDueInformation && currentlyDueInformation.length)) { if (
(eventuallyDueInformation && eventuallyDueInformation.length) ||
(currentlyDueInformation && currentlyDueInformation.length)
) {
objectToUpdateState.stillRequiringVerification = true; objectToUpdateState.stillRequiringVerification = true;
getAndSetAccountLink(false); getAndSetAccountLink(false);
} }
@ -233,8 +231,17 @@ class StripeAccountConnection extends React.Component<Props, State> {
<div> <div>
<div> <div>
<h3>{__('Congratulations! Your account has been connected with Odysee.')}</h3> <h3>{__('Congratulations! Your account has been connected with Odysee.')}</h3>
{stillRequiringVerification && <><h3 style={{marginTop: '10px'}}>Although your account is connected it still requires verification to begin receiving tips.</h3> {stillRequiringVerification && (
<h3 style={{marginTop: '10px'}}>Please use the button below to complete your verification process and enable tipping for your account.</h3></> } <>
<h3 style={{ marginTop: '10px' }}>
Although your account is connected it still requires verification to begin receiving tips.
</h3>
<h3 style={{ marginTop: '10px' }}>
Please use the button below to complete your verification process and enable tipping for
your account.
</h3>
</>
)}
</div> </div>
</div> </div>
</div> </div>
@ -254,9 +261,7 @@ class StripeAccountConnection extends React.Component<Props, State> {
<br /> <br />
<div> <div>
<h3> <h3>
{__( {__('Connect your bank account to be able to cash your pending balance out to your account.')}
'Connect your bank account to be able to cash your pending balance out to your account.'
)}
</h3> </h3>
</div> </div>
<div className="section__actions"> <div className="section__actions">
@ -271,19 +276,23 @@ class StripeAccountConnection extends React.Component<Props, State> {
</div> </div>
} }
actions={ actions={
<>{ stillRequiringVerification && <Button <>
button="primary" {stillRequiringVerification && (
label={__('Complete Verification')} <Button
icon={ICONS.SETTINGS} button="primary"
navigate={stripeConnectionUrl} label={__('Complete Verification')}
className="stripe__complete-verification-button" icon={ICONS.SETTINGS}
/> } navigate={stripeConnectionUrl}
<Button className="stripe__complete-verification-button"
button="secondary" />
label={__('View Transactions')} )}
icon={ICONS.SETTINGS} <Button
navigate={`/$/${PAGES.WALLET}?tab=fiat-payment-history`} button="secondary"
/></> label={__('View Transactions')}
icon={ICONS.SETTINGS}
navigate={`/$/${PAGES.WALLET}?tab=fiat-payment-history`}
/>
</>
} }
/> />
<br /> <br />

View file

@ -5,19 +5,14 @@ import React from 'react';
import Page from 'component/page'; import Page from 'component/page';
import Card from 'component/common/card'; import Card from 'component/common/card';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { STRIPE_PUBLIC_KEY } from 'config';
import Plastic from 'react-plastic'; import Plastic from 'react-plastic';
import Button from 'component/button'; import Button from 'component/button';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import * as MODALS from 'constants/modal_types'; import * as MODALS from 'constants/modal_types';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import { STRIPE_PUBLIC_KEY } from 'config';
let stripeEnvironment = 'test'; import { getStripeEnvironment } from 'util/stripe';
// if the key contains pk_live it's a live key let stripeEnvironment = getStripeEnvironment();
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
const APIS_DOWN_ERROR_RESPONSE = __('There was an error from the server, please try again later'); const APIS_DOWN_ERROR_RESPONSE = __('There was an error from the server, please try again later');
const CARD_SETUP_ERROR_RESPONSE = __('There was an error getting your card setup, please try again later'); const CARD_SETUP_ERROR_RESPONSE = __('There was an error getting your card setup, please try again later');
@ -79,114 +74,116 @@ class SettingsStripeCard extends React.Component<Props, State> {
// TODO: fix this, should be a cleaner way // TODO: fix this, should be a cleaner way
setTimeout(function () { setTimeout(function () {
// check if customer has card setup already // check if customer has card setup already
Lbryio.call( if (stripeEnvironment) {
'customer', Lbryio.call(
'status', 'customer',
{ 'status',
environment: stripeEnvironment, {
}, environment: stripeEnvironment,
'post' },
) 'post'
.then((customerStatusResponse) => { )
// user has a card saved if their defaultPaymentMethod has an id .then((customerStatusResponse) => {
const defaultPaymentMethod = customerStatusResponse.Customer.invoice_settings.default_payment_method; // user has a card saved if their defaultPaymentMethod has an id
let userHasAlreadySetupPayment = Boolean(defaultPaymentMethod && defaultPaymentMethod.id); const defaultPaymentMethod = customerStatusResponse.Customer.invoice_settings.default_payment_method;
let userHasAlreadySetupPayment = Boolean(defaultPaymentMethod && defaultPaymentMethod.id);
// show different frontend if user already has card // show different frontend if user already has card
if (userHasAlreadySetupPayment) { if (userHasAlreadySetupPayment) {
let card = customerStatusResponse.PaymentMethods[0].card; let card = customerStatusResponse.PaymentMethods[0].card;
let customer = customerStatusResponse.Customer; let customer = customerStatusResponse.Customer;
let topOfDisplay = customer.email.split('@')[0]; let topOfDisplay = customer.email.split('@')[0];
let bottomOfDisplay = '@' + customer.email.split('@')[1]; let bottomOfDisplay = '@' + customer.email.split('@')[1];
let cardDetails = { let cardDetails = {
brand: card.brand, brand: card.brand,
expiryYear: card.exp_year, expiryYear: card.exp_year,
expiryMonth: card.exp_month, expiryMonth: card.exp_month,
lastFour: card.last4, lastFour: card.last4,
topOfDisplay: topOfDisplay, topOfDisplay: topOfDisplay,
bottomOfDisplay: bottomOfDisplay, bottomOfDisplay: bottomOfDisplay,
}; };
that.setState({ that.setState({
currentFlowStage: 'cardConfirmed', currentFlowStage: 'cardConfirmed',
pageTitle: 'Tip History', pageTitle: 'Tip History',
userCardDetails: cardDetails, userCardDetails: cardDetails,
paymentMethodId: customerStatusResponse.PaymentMethods[0].id, paymentMethodId: customerStatusResponse.PaymentMethods[0].id,
}); });
// otherwise, prompt them to save a card // otherwise, prompt them to save a card
} else { } else {
that.setState({ that.setState({
currentFlowStage: 'confirmingCard', currentFlowStage: 'confirmingCard',
}); });
// get a payment method secret for frontend // get a payment method secret for frontend
Lbryio.call(
'customer',
'setup',
{
environment: stripeEnvironment,
},
'post'
).then((customerSetupResponse) => {
clientSecret = customerSetupResponse.client_secret;
// instantiate stripe elements
setupStripe();
});
}
// get customer transactions
Lbryio.call( Lbryio.call(
'customer', 'customer',
'setup', 'list',
{ {
environment: stripeEnvironment, environment: stripeEnvironment,
}, },
'post' 'post'
).then((customerSetupResponse) => { ).then((customerTransactionsResponse) => {
clientSecret = customerSetupResponse.client_secret; that.setState({
customerTransactions: customerTransactionsResponse,
// instantiate stripe elements });
setupStripe();
}); });
} // if the status call fails, either an actual error or need to run setup first
})
.catch(function (error) {
// errorString passed from the API (with a 403 error)
const errorString = 'user as customer is not setup yet';
// get customer transactions // if it's beamer's error indicating the account is not linked yet
Lbryio.call( if (error.message && error.message.indexOf(errorString) > -1) {
'customer', // send them to save a card
'list', that.setState({
{ currentFlowStage: 'confirmingCard',
environment: stripeEnvironment, });
},
'post' // get a payment method secret for frontend
).then((customerTransactionsResponse) => { Lbryio.call(
that.setState({ 'customer',
customerTransactions: customerTransactionsResponse, 'setup',
}); {
environment: stripeEnvironment,
},
'post'
).then((customerSetupResponse) => {
clientSecret = customerSetupResponse.client_secret;
// instantiate stripe elements
setupStripe();
});
// 500 error from the backend being down
} else if (error === 'internal_apis_down') {
doToast({ message: APIS_DOWN_ERROR_RESPONSE, isError: true });
} else {
// probably an error from stripe
doToast({ message: CARD_SETUP_ERROR_RESPONSE, isError: true });
}
}); });
// if the status call fails, either an actual error or need to run setup first }
})
.catch(function (error) {
// errorString passed from the API (with a 403 error)
const errorString = 'user as customer is not setup yet';
// if it's beamer's error indicating the account is not linked yet
if (error.message && error.message.indexOf(errorString) > -1) {
// send them to save a card
that.setState({
currentFlowStage: 'confirmingCard',
});
// get a payment method secret for frontend
Lbryio.call(
'customer',
'setup',
{
environment: stripeEnvironment,
},
'post'
).then((customerSetupResponse) => {
clientSecret = customerSetupResponse.client_secret;
// instantiate stripe elements
setupStripe();
});
// 500 error from the backend being down
} else if (error === 'internal_apis_down') {
doToast({ message: APIS_DOWN_ERROR_RESPONSE, isError: true });
} else {
// probably an error from stripe
doToast({ message: CARD_SETUP_ERROR_RESPONSE, isError: true });
}
});
}, 250); }, 250);
function setupStripe() { function setupStripe() {

View file

@ -1,5 +1,5 @@
// @flow // @flow
import { DOMAIN } from 'config'; import { DOMAIN, ENABLE_NO_SOURCE_CLAIMS } from 'config';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { lazyImport } from 'util/lazyImport'; import { lazyImport } from 'util/lazyImport';
@ -199,7 +199,7 @@ function ShowPage(props: Props) {
/> />
</Page> </Page>
); );
} else if (isLivestream) { } else if (isLivestream && ENABLE_NO_SOURCE_CLAIMS) {
innerContent = <LivestreamPage uri={uri} />; innerContent = <LivestreamPage uri={uri} />;
} else { } else {
innerContent = <FilePage uri={uri} location={location} />; innerContent = <FilePage uri={uri} location={location} />;

View file

@ -12,8 +12,8 @@ import * as PAGES from 'constants/pages';
import Spinner from 'component/spinner'; import Spinner from 'component/spinner';
import YrblWalletEmpty from 'component/yrblWalletEmpty'; import YrblWalletEmpty from 'component/yrblWalletEmpty';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import { STRIPE_PUBLIC_KEY } from 'config';
import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs'; import { Tabs, TabList, Tab, TabPanels, TabPanel } from 'component/common/tabs';
import { getStripeEnvironment } from 'util/stripe';
const TAB_QUERY = 'tab'; const TAB_QUERY = 'tab';
@ -23,12 +23,7 @@ const TABS = {
PAYMENT_HISTORY: 'fiat-payment-history', PAYMENT_HISTORY: 'fiat-payment-history',
}; };
let stripeEnvironment = 'test'; let stripeEnvironment = getStripeEnvironment();
// if the key contains pk_live it's a live key
// update the environment for the calls to the backend to indicate which environment to hit
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
stripeEnvironment = 'live';
}
type Props = { type Props = {
history: { action: string, push: (string) => void, replace: (string) => void }, history: { action: string, push: (string) => void, replace: (string) => void },
@ -117,8 +112,11 @@ const WalletPage = (props: Props) => {
// calculate account transactions section // calculate account transactions section
React.useEffect(() => { React.useEffect(() => {
(async function() { (async function () {
try { try {
if (!stripeEnvironment) {
return;
}
const response = await getAccountStatus(); const response = await getAccountStatus();
setAccountStatusResponse(response); setAccountStatusResponse(response);
@ -131,23 +129,27 @@ const WalletPage = (props: Props) => {
console.log(err); console.log(err);
} }
})(); })();
}, []); }, [stripeEnvironment]);
// populate customer payment data // populate customer payment data
React.useEffect(() => { React.useEffect(() => {
(async function() { (async function () {
try { try {
// get card payments customer has made // get card payments customer has made
if (!stripeEnvironment) {
return;
}
let customerTransactionResponse = await getPaymentHistory(); let customerTransactionResponse = await getPaymentHistory();
if (customerTransactionResponse && customerTransactionResponse.length) {
customerTransactionResponse.reverse(); customerTransactionResponse.reverse();
}
setCustomerTransactions(customerTransactionResponse); setCustomerTransactions(customerTransactionResponse);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
})(); })();
}, []); }, [stripeEnvironment]);
// @endif // @endif
@ -157,77 +159,80 @@ const WalletPage = (props: Props) => {
return ( return (
<> <>
{/* @if TARGET='web' */} {stripeEnvironment && (
<Page> <Page>
<Tabs onChange={onTabChange} index={tabIndex}> <Tabs onChange={onTabChange} index={tabIndex}>
<TabList className="tabs__list--collection-edit-page"> <TabList className="tabs__list--collection-edit-page">
<Tab>{__('LBRY Credits')}</Tab> <Tab>{__('LBRY Credits')}</Tab>
<Tab>{__('Account History')}</Tab> <Tab>{__('Account History')}</Tab>
<Tab>{__('Payment History')}</Tab> <Tab>{__('Payment History')}</Tab>
</TabList> </TabList>
<TabPanels> <TabPanels>
<TabPanel> <TabPanel>
<div className="section card-stack"> <div className="section card-stack">
<div className="lbc-transactions"> <div className="lbc-transactions">
{/* if the transactions are loading */} {/* if the transactions are loading */}
{loading && ( {loading && (
<div className="main--empty"> <div className="main--empty">
<Spinner delayed /> <Spinner delayed />
</div> </div>
)} )}
{/* when the transactions are finished loading */} {/* when the transactions are finished loading */}
{!loading && ( {!loading && (
<> <>
{showIntro ? ( {showIntro ? (
<YrblWalletEmpty includeWalletLink /> <YrblWalletEmpty includeWalletLink />
) : ( ) : (
<div className="card-stack"> <div className="card-stack">
<WalletBalance /> <WalletBalance />
<TxoList search={search} /> <TxoList search={search} />
</div> </div>
)} )}
</> </>
)} )}
</div>
</div> </div>
</div> </TabPanel>
</TabPanel> <TabPanel>
<TabPanel> <div className="section card-stack">
<div className="section card-stack"> <WalletFiatBalance accountDetails={accountStatusResponse} />
<WalletFiatBalance accountDetails={accountStatusResponse} /> <WalletFiatAccountHistory transactions={accountTransactionResponse} />
<WalletFiatAccountHistory transactions={accountTransactionResponse} /> </div>
</div> </TabPanel>
</TabPanel> <TabPanel>
<TabPanel> <div className="section card-stack">
<div className="section card-stack"> <WalletFiatPaymentBalance
<WalletFiatPaymentBalance transactions={customerTransactions} accountDetails={accountStatusResponse} /> transactions={customerTransactions}
<WalletFiatPaymentHistory transactions={customerTransactions} /> accountDetails={accountStatusResponse}
</div> />
</TabPanel> <WalletFiatPaymentHistory transactions={customerTransactions} />
</TabPanels> </div>
</Tabs> </TabPanel>
</Page> </TabPanels>
{/* @endif */} </Tabs>
{/* @if TARGET='app' */} </Page>
<Page> )}
{loading && ( {!stripeEnvironment && (
<div className="main--empty"> <Page>
<Spinner delayed /> {loading && (
</div> <div className="main--empty">
)} <Spinner delayed />
{!loading && ( </div>
<> )}
{showIntro ? ( {!loading && (
<YrblWalletEmpty includeWalletLink /> <>
) : ( {showIntro ? (
<div className="card-stack"> <YrblWalletEmpty includeWalletLink />
<WalletBalance /> ) : (
<TxoList search={search} /> <div className="card-stack">
</div> <WalletBalance />
)} <TxoList search={search} />
</> </div>
)} )}
</Page> </>
{/* @endif */} )}
</Page>
)}
</> </>
); );
}; };

13
ui/util/stripe.js Normal file
View file

@ -0,0 +1,13 @@
// @flow
import { STRIPE_PUBLIC_KEY } from 'config';
import * as STRIPE_CONSTS from 'constants/stripe';
export function getStripeEnvironment() {
if (STRIPE_PUBLIC_KEY) {
if (STRIPE_PUBLIC_KEY.indexOf('pk_live') > -1) {
return STRIPE_CONSTS.LIVE;
} else {
return STRIPE_CONSTS.TEST;
}
}
return null;
}