diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a94afa13..1fa1b399b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ Web UI version numbers should always match the corresponding version of LBRY App ### Fixed * Some CSS changes to prevent the card row from clipping the scroll arrows after the window width is reduced below a certain point - * + * Clearly notify user when they try to send credits to an invalid address ### Deprecated * diff --git a/ui/js/component/formField/view.jsx b/ui/js/component/formField/view.jsx index 2473eaf8d..224b607ec 100644 --- a/ui/js/component/formField/view.jsx +++ b/ui/js/component/formField/view.jsx @@ -12,6 +12,15 @@ class FormField extends React.PureComponent { prefix: React.PropTypes.string, postfix: React.PropTypes.string, hasError: React.PropTypes.bool, + trim: React.PropTypes.bool, + regexp: React.PropTypes.oneOfType([ + React.PropTypes.instanceOf(RegExp), + React.PropTypes.string, + ]), + }; + + static defaultProps = { + trim: false, }; constructor(props) { @@ -77,6 +86,13 @@ class FormField extends React.PureComponent { }); } + clearError() { + this.setState({ + isError: false, + errorMessage: "", + }); + } + focus() { this.refs.field.focus(); } @@ -87,7 +103,9 @@ class FormField extends React.PureComponent { } else if (this.props.type == "SimpleMDE") { return this.refs.field.simplemde.value(); } else { - return this.refs.field.value; + return this.props.trim + ? this.refs.field.value.trim() + : this.refs.field.value; } } @@ -99,6 +117,16 @@ class FormField extends React.PureComponent { return this.refs.field.options; } + validate() { + if ("regexp" in this.props) { + if (!this.getValue().match(this.props.regexp)) { + this.showError(__("Invalid format.")); + } else { + this.clearError(); + } + } + } + render() { // Pass all unhandled props to the field element const otherProps = Object.assign({}, this.props), @@ -116,6 +144,8 @@ class FormField extends React.PureComponent { delete otherProps.postfix; delete otherProps.prefix; delete otherProps.dispatch; + delete otherProps.regexp; + delete otherProps.trim; const element = ( this.validate()} className={ "form-field__input form-field__input-" + this.props.type + diff --git a/ui/js/component/walletSend/index.js b/ui/js/component/walletSend/index.js index ab13440db..57e761c30 100644 --- a/ui/js/component/walletSend/index.js +++ b/ui/js/component/walletSend/index.js @@ -10,6 +10,7 @@ import { selectCurrentModal } from "selectors/app"; import { selectDraftTransactionAmount, selectDraftTransactionAddress, + selectDraftTransactionError, } from "selectors/wallet"; import WalletSend from "./view"; @@ -18,6 +19,7 @@ const select = state => ({ modal: selectCurrentModal(state), address: selectDraftTransactionAddress(state), amount: selectDraftTransactionAmount(state), + error: selectDraftTransactionError(state), }); const perform = dispatch => ({ diff --git a/ui/js/component/walletSend/view.jsx b/ui/js/component/walletSend/view.jsx index 680106584..2751c42ab 100644 --- a/ui/js/component/walletSend/view.jsx +++ b/ui/js/component/walletSend/view.jsx @@ -2,6 +2,7 @@ import React from "react"; import Link from "component/link"; import Modal from "modal/modal"; import { FormRow } from "component/form"; +import lbryuri from "lbryuri"; const WalletSend = props => { const { @@ -12,6 +13,7 @@ const WalletSend = props => { setAddress, amount, address, + error, } = props; return ( @@ -41,6 +43,8 @@ const WalletSend = props => { size="60" onChange={setAddress} value={address} + regexp={lbryuri.REGEXP_ADDRESS} + trim={true} />
{ contentLabel={__("Transaction failed")} onConfirmed={closeModal} > - {__("Something went wrong")}: + {error} } ); diff --git a/ui/js/lbryuri.js b/ui/js/lbryuri.js index a7f43890a..922cbfd33 100644 --- a/ui/js/lbryuri.js +++ b/ui/js/lbryuri.js @@ -4,6 +4,7 @@ const CLAIM_ID_MAX_LEN = 40; const lbryuri = {}; lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g; +lbryuri.REGEXP_ADDRESS = /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/; /** * Parses a LBRY name into its component parts. Throws errors with user-friendly diff --git a/ui/js/selectors/wallet.js b/ui/js/selectors/wallet.js index bf8fcb61b..de7fd337b 100644 --- a/ui/js/selectors/wallet.js +++ b/ui/js/selectors/wallet.js @@ -82,6 +82,11 @@ export const selectDraftTransactionAddress = createSelector( draft => draft.address ); +export const selectDraftTransactionError = createSelector( + selectDraftTransaction, + draft => draft.error +); + export const selectBlocks = createSelector(_selectState, state => state.blocks); export const makeSelectBlockDate = block => {