diff --git a/ui/js/actions/claims.js b/ui/js/actions/claims.js new file mode 100644 index 000000000..5d72a9f5f --- /dev/null +++ b/ui/js/actions/claims.js @@ -0,0 +1,76 @@ +import lbry from "lbry"; +import { selectBalance } from "selectors/wallet"; +import { + selectSupportTransaction, + selectSupportTransactionAmount, +} from "selectors/claims"; +import { doOpenModal, doShowSnackBar } from "actions/app"; +import * as types from "constants/action_types"; +import * as modals from "constants/modal_types"; + +export function doSendSupport() { + return function(dispatch, getState) { + const state = getState(); + const supportTx = selectSupportTransaction(state); + const balance = selectBalance(state); + const amount = selectSupportTransactionAmount(state); + + if (balance - amount < 1) { + return dispatch(doOpenModal(modals.INSUFFICIENT_BALANCE)); + } + + dispatch({ + type: types.SUPPORT_TRANSACTION_STARTED, + }); + + const successCallback = results => { + if (results.txid) { + dispatch({ + type: types.SUPPORT_TRANSACTION_COMPLETED, + }); + dispatch( + doShowSnackBar({ + message: __(`You sent ${amount} LBC as support, Mahalo!`), + linkText: __("History"), + linkTarget: __("/wallet"), + }) + ); + } else { + dispatch({ + type: types.SUPPORT_TRANSACTION_FAILED, + data: { error: results }, + }); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + } + }; + + const errorCallback = error => { + dispatch({ + type: types.SUPPORT_TRANSACTION_FAILED, + data: { error: error.message }, + }); + dispatch(doOpenModal(modals.TRANSACTION_FAILED)); + }; + + lbry + .claim_send_tip({ + claim_id: supportTx.claim_id, + amount: supportTx.amount, + }) + .then(successCallback, errorCallback); + }; +} + +export function doSetSupportAmount(amount) { + return { + type: types.SET_SUPPORT_AMOUNT, + data: { amount }, + }; +} + +export function doSetSupportClaimID(claim_id) { + return { + type: types.SET_SUPPORT_CLAIMID, + data: { claim_id }, + }; +} diff --git a/ui/js/component/fileActions/view.jsx b/ui/js/component/fileActions/view.jsx index 79bfbf506..1b0c2670a 100644 --- a/ui/js/component/fileActions/view.jsx +++ b/ui/js/component/fileActions/view.jsx @@ -187,7 +187,7 @@ class FileActions extends React.PureComponent { onTipShow={this.handleTipShow.bind(this)} onTipHide={this.handleTipHide.bind(this)} showTipBox={showTipBox} - address={claimInfo.address} + claim_id={claimInfo.claim_id} /> {showMenu && !showTipBox ? diff --git a/ui/js/component/priceForm/index.js b/ui/js/component/priceForm/index.js deleted file mode 100644 index 5370b8ed1..000000000 --- a/ui/js/component/priceForm/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; -import { connect } from "react-redux"; -import PriceForm from "./view"; - -export default connect(null, null)(PriceForm); diff --git a/ui/js/component/priceForm/view.jsx b/ui/js/component/priceForm/view.jsx deleted file mode 100644 index bba0173f5..000000000 --- a/ui/js/component/priceForm/view.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import { FormField } from "component/form"; - -const PriceForm = props => { - const { - onFeeChange, - onCurrencyChange, - defaultFeeValue, - defaultCurrencyValue, - placeholder, - min, - step, - isTip, - } = props; - - return ( - - - - - - - - ); -}; - -export default PriceForm; diff --git a/ui/js/component/tipLink/index.js b/ui/js/component/tipLink/index.js index 3e093833e..b969bfb57 100644 --- a/ui/js/component/tipLink/index.js +++ b/ui/js/component/tipLink/index.js @@ -1,18 +1,18 @@ import React from "react"; import { connect } from "react-redux"; import { - doSendDraftTransaction, - doSetDraftTransactionAmount, - doSetDraftTransactionAddress, -} from "actions/wallet"; + doSendSupport, + doSetSupportAmount, + doSetSupportClaimID, +} from "actions/claims"; import TipLink from "./view"; const select = state => ({}); const perform = dispatch => ({ - sendToAddress: () => dispatch(doSendDraftTransaction()), - setAmount: amount => dispatch(doSetDraftTransactionAmount(amount)), - setAddress: address => dispatch(doSetDraftTransactionAddress(address)), + sendSupport: () => dispatch(doSendSupport()), + setAmount: amount => dispatch(doSetSupportAmount(amount)), + setClaimID: claim_id => dispatch(doSetSupportClaimID(claim_id)), }); export default connect(select, perform)(TipLink); diff --git a/ui/js/component/tipLink/view.jsx b/ui/js/component/tipLink/view.jsx index 373f46257..295afc3db 100644 --- a/ui/js/component/tipLink/view.jsx +++ b/ui/js/component/tipLink/view.jsx @@ -1,7 +1,6 @@ import React from "react"; import Link from "component/link"; -import { FormField } from "component/form"; -import PriceForm from "component/priceForm"; +import FormFieldPrice from "component/formFieldPrice"; class TipLink extends React.PureComponent { constructor(props) { @@ -13,35 +12,30 @@ class TipLink extends React.PureComponent { }; } - handleTipPublisherButtonClicked() { + handleSupportButtonClicked() { this.resetDefaults(); this.props.onTipShow(); } - handleTipButtonClicked() { - let address = this.props.address; + handleSendButtonClicked() { + let claim_id = this.props.claim_id; let amount = this.state.feeAmount; - this.props.setAddress(address); + this.props.setClaimID(claim_id); this.props.setAmount(amount); - this.props.sendToAddress(); + this.props.sendSupport(); this.props.onTipHide(); } - handleTipCancelButtonClicked() { + handleSupportCancelButtonClicked() { this.props.onTipHide(); } - handleFeeAmountChange(event) { + handleSupportPriceChange(newValue) { this.setState({ - feeAmount: event.target.value, - }); - } - - handleCurrencyChange(event) { - this.setState({ - currency: event.target.value, + feeAmount: newValue.amount, + feeCurrency: newValue.currency, }); } @@ -54,37 +48,35 @@ class TipLink extends React.PureComponent { render() { const { showTipBox } = this.props; + const { feeAmount, currency } = this.state; let tipLink = ( ); let tipBox = ( - this.handleFeeAmountChange(event)} - defaultFeeValue={this.state.feeAmount} - onCurrencyChange={event => this.handleCurrencyChange(event)} - defaultCurrencyValue="LBC" + onChange={value => this.handleSupportPriceChange(value)} + defaultValue={{ amount: feeAmount, currency: currency }} />
{__("This sends the entered amount of LBCs to the publisher.")} diff --git a/ui/js/constants/action_types.js b/ui/js/constants/action_types.js index 71d6d8072..8d53d0806 100644 --- a/ui/js/constants/action_types.js +++ b/ui/js/constants/action_types.js @@ -112,5 +112,11 @@ export const CLAIM_REWARD_STARTED = "CLAIM_REWARD_STARTED"; export const CLAIM_REWARD_SUCCESS = "CLAIM_REWARD_SUCCESS"; export const CLAIM_REWARD_FAILURE = "CLAIM_REWARD_FAILURE"; export const CLAIM_REWARD_CLEAR_ERROR = "CLAIM_REWARD_CLEAR_ERROR"; -export const FETCH_REWARD_CONTENT_COMPLETED = - "FETCH_REWARD_CONTENT_COMPLETED"; +export const FETCH_REWARD_CONTENT_COMPLETED = "FETCH_REWARD_CONTENT_COMPLETED"; + +// Supports +export const SET_SUPPORT_CLAIMID = "SET_SUPPORT_CLAIMID"; +export const SET_SUPPORT_AMOUNT = "SET_SUPPORT_AMOUNT"; +export const SUPPORT_TRANSACTION_STARTED = "SUPPORT_TRANSACTION_STARTED"; +export const SUPPORT_TRANSACTION_COMPLETED = "SUPPORT_TRANSACTION_COMPLETED"; +export const SUPPORT_TRANSACTION_FAILED = "SUPPORT_TRANSACTION_FAILED"; diff --git a/ui/js/reducers/claims.js b/ui/js/reducers/claims.js index c70fd45e0..8d913438d 100644 --- a/ui/js/reducers/claims.js +++ b/ui/js/reducers/claims.js @@ -2,7 +2,14 @@ import * as types from "constants/action_types"; import lbryuri from "lbryuri"; const reducers = {}; -const defaultState = {}; +const buildSupportTransaction = () => ({ + claim_id: undefined, + amount: undefined, +}); + +const defaultState = { + supportTransaction: buildSupportTransaction(), +}; reducers[types.RESOLVE_URI_COMPLETED] = function(state, action) { const { uri, certificate, claim } = action.data; @@ -190,6 +197,55 @@ reducers[types.CREATE_CHANNEL_COMPLETED] = function(state, action) { }); }; +reducers[types.SET_SUPPORT_AMOUNT] = function(state, action) { + const oldDraft = state.supportTransaction; + const newDraft = Object.assign({}, oldDraft, { + amount: parseFloat(action.data.amount), + }); + + return Object.assign({}, state, { + supportTransaction: newDraft, + }); +}; + +reducers[types.SET_SUPPORT_CLAIMID] = function(state, action) { + const oldDraft = state.supportTransaction; + const newDraft = Object.assign({}, oldDraft, { + claim_id: action.data.claim_id, + }); + + return Object.assign({}, state, { + supportTransaction: newDraft, + }); +}; + +reducers[types.SUPPORT_TRANSACTION_STARTED] = function(state, action) { + const newSupportTransaction = Object.assign({}, state.supportTransaction, { + sendingSupport: true, + }); + + return Object.assign({}, state, { + supportTransaction: newSupportTransaction, + }); +}; + +reducers[types.SUPPORT_TRANSACTION_COMPLETED] = function(state, action) { + return Object.assign({}, state, { + supportTransaction: buildSupportTransaction(), + }); +}; + +reducers[types.SUPPORT_TRANSACTION_FAILED] = function(state, action) { + const newSupportTransaction = Object.assign({}, state.supportTransaction, { + sendingSupport: false, + error: action.data.error, + }); + + return Object.assign({}, state, { + supportTransaction: newSupportTransaction, + }); +}; + export default function reducer(state = defaultState, action) { const handler = reducers[action.type]; if (handler) return handler(state, action); diff --git a/ui/js/selectors/claims.js b/ui/js/selectors/claims.js index 2c4b4b511..4676eb77a 100644 --- a/ui/js/selectors/claims.js +++ b/ui/js/selectors/claims.js @@ -215,3 +215,13 @@ export const selectMyChannelClaims = createSelector( return claims; } ); + +export const selectSupportTransaction = createSelector( + _selectState, + state => state.supportTransaction || {} +); + +export const selectSupportTransactionAmount = createSelector( + selectSupportTransaction, + supportTxAmount => supportTxAmount.amount +);