Merge branch 'check-address-valid'

This commit is contained in:
Jeremy Kauffman 2017-09-06 14:54:15 -04:00
commit 0aaf4741da
6 changed files with 46 additions and 3 deletions
CHANGELOG.md
ui/js
component
formField
walletSend
lbryuri.js
selectors

View file

@ -19,7 +19,7 @@ Web UI version numbers should always match the corresponding version of LBRY App
### Fixed ### Fixed
* Some CSS changes to prevent the card row from clipping the scroll arrows after the window width is reduced below a certain point * 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 ### Deprecated
* *

View file

@ -12,6 +12,15 @@ class FormField extends React.PureComponent {
prefix: React.PropTypes.string, prefix: React.PropTypes.string,
postfix: React.PropTypes.string, postfix: React.PropTypes.string,
hasError: React.PropTypes.bool, 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) { constructor(props) {
@ -77,6 +86,13 @@ class FormField extends React.PureComponent {
}); });
} }
clearError() {
this.setState({
isError: false,
errorMessage: "",
});
}
focus() { focus() {
this.refs.field.focus(); this.refs.field.focus();
} }
@ -87,7 +103,9 @@ class FormField extends React.PureComponent {
} else if (this.props.type == "SimpleMDE") { } else if (this.props.type == "SimpleMDE") {
return this.refs.field.simplemde.value(); return this.refs.field.simplemde.value();
} else { } 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; 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() { render() {
// Pass all unhandled props to the field element // Pass all unhandled props to the field element
const otherProps = Object.assign({}, this.props), const otherProps = Object.assign({}, this.props),
@ -116,6 +144,8 @@ class FormField extends React.PureComponent {
delete otherProps.postfix; delete otherProps.postfix;
delete otherProps.prefix; delete otherProps.prefix;
delete otherProps.dispatch; delete otherProps.dispatch;
delete otherProps.regexp;
delete otherProps.trim;
const element = ( const element = (
<this._element <this._element
@ -124,6 +154,7 @@ class FormField extends React.PureComponent {
name={this.props.name} name={this.props.name}
ref="field" ref="field"
placeholder={this.props.placeholder} placeholder={this.props.placeholder}
onBlur={() => this.validate()}
className={ className={
"form-field__input form-field__input-" + "form-field__input form-field__input-" +
this.props.type + this.props.type +

View file

@ -10,6 +10,7 @@ import { selectCurrentModal } from "selectors/app";
import { import {
selectDraftTransactionAmount, selectDraftTransactionAmount,
selectDraftTransactionAddress, selectDraftTransactionAddress,
selectDraftTransactionError,
} from "selectors/wallet"; } from "selectors/wallet";
import WalletSend from "./view"; import WalletSend from "./view";
@ -18,6 +19,7 @@ const select = state => ({
modal: selectCurrentModal(state), modal: selectCurrentModal(state),
address: selectDraftTransactionAddress(state), address: selectDraftTransactionAddress(state),
amount: selectDraftTransactionAmount(state), amount: selectDraftTransactionAmount(state),
error: selectDraftTransactionError(state),
}); });
const perform = dispatch => ({ const perform = dispatch => ({

View file

@ -2,6 +2,7 @@ import React from "react";
import Link from "component/link"; import Link from "component/link";
import Modal from "modal/modal"; import Modal from "modal/modal";
import { FormRow } from "component/form"; import { FormRow } from "component/form";
import lbryuri from "lbryuri";
const WalletSend = props => { const WalletSend = props => {
const { const {
@ -12,6 +13,7 @@ const WalletSend = props => {
setAddress, setAddress,
amount, amount,
address, address,
error,
} = props; } = props;
return ( return (
@ -41,6 +43,8 @@ const WalletSend = props => {
size="60" size="60"
onChange={setAddress} onChange={setAddress}
value={address} value={address}
regexp={lbryuri.REGEXP_ADDRESS}
trim={true}
/> />
<div className="form-row-submit"> <div className="form-row-submit">
<Link <Link
@ -77,7 +81,7 @@ const WalletSend = props => {
contentLabel={__("Transaction failed")} contentLabel={__("Transaction failed")}
onConfirmed={closeModal} onConfirmed={closeModal}
> >
{__("Something went wrong")}: {error}
</Modal>} </Modal>}
</section> </section>
); );

View file

@ -4,6 +4,7 @@ const CLAIM_ID_MAX_LEN = 40;
const lbryuri = {}; const lbryuri = {};
lbryuri.REGEXP_INVALID_URI = /[^A-Za-z0-9-]/g; 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 * Parses a LBRY name into its component parts. Throws errors with user-friendly

View file

@ -82,6 +82,11 @@ export const selectDraftTransactionAddress = createSelector(
draft => draft.address draft => draft.address
); );
export const selectDraftTransactionError = createSelector(
selectDraftTransaction,
draft => draft.error
);
export const selectBlocks = createSelector(_selectState, state => state.blocks); export const selectBlocks = createSelector(_selectState, state => state.blocks);
export const makeSelectBlockDate = block => { export const makeSelectBlockDate = block => {