Custom DPaths, Improvements, and Fix SingularDTV (#1351)

* Add dpath to select option display

* Re-enable custom path

* Make it a submittable form to behave better with HW wallets

* Adjust styles

* Widen regex to allow for SingularDTV dpath
This commit is contained in:
William O'Beirne 2018-03-21 16:19:15 -04:00 committed by Daniel Ternyak
parent f42b81ac8a
commit 7521337bda
3 changed files with 80 additions and 30 deletions

View File

@ -7,19 +7,42 @@
&-label {
font-size: $font-size-medium;
margin-right: 16px;
margin-right: $space-md;
line-height: $input-height-base;
}
&-select {
flex: 1;
small {
padding-left: 5px;
opacity: 0.5;
font-size: 11px;
@include mono;
}
}
&-custom {
flex: 1;
margin-left: $space-md;
.input-group-input {
margin: 0;
}
}
&-submit {
margin-left: $space-md;
padding-left: $space;
padding-right: $space;
border: none;
}
.form-control {
display: inline-block;
width: auto;
margin: 0 0 0 10px;
}
.Select {
flex-grow: 1;
}
}
&-addresses {

View File

@ -1,3 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
import Select, { Option } from 'react-select';
import translate from 'translations';
import {
DeterministicWalletData,
getDeterministicWallets,
@ -9,14 +13,11 @@ import {
import Modal, { IButton } from 'components/ui/Modal';
import { AppState } from 'reducers';
import { isValidPath } from 'libs/validators';
import React from 'react';
import { connect } from 'react-redux';
import { getNetworkConfig } from 'selectors/config';
import { getTokens, MergedToken } from 'selectors/wallet';
import { UnitDisplay, Input } from 'components/ui';
import './DeterministicWalletsModal.scss';
import { StaticNetworkConfig } from 'types/network';
import Select from 'react-select';
import './DeterministicWalletsModal.scss';
const WALLETS_PER_PAGE = 5;
@ -125,23 +126,36 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
onSubmit={this.handleSubmitCustomPath}
>
<span className="DWModal-path-label">Addresses </span>
<Select
name="fieldDPath"
className=""
value={this.state.currentLabel || this.findDPath('value', dPath).value}
onChange={this.handleChangePath}
options={dPaths}
clearable={false}
searchable={false}
/>
{/* TODO/Hack - Custom Paths are temporarily disabled. `false` is used for smallest diff */}
{false && (
<Input
className={isValidPath(customPath) ? '' : 'invalid'}
value={customPath}
placeholder="m/44'/60'/0'/0"
onChange={this.handleChangeCustomPath}
<div className="DWModal-path-select">
<Select
name="fieldDPath"
className=""
value={this.state.currentLabel || this.findDPath('value', dPath).value}
onChange={this.handleChangePath}
options={dPaths.concat([customDPath])}
optionRenderer={this.renderDPathOption}
valueRenderer={this.renderDPathOption}
clearable={false}
searchable={false}
/>
</div>
{this.state.currentLabel === customDPath.label && (
<React.Fragment>
<div className="DWModal-path-custom">
<Input
className={customPath ? (isValidPath(customPath) ? 'valid' : 'invalid') : ''}
value={customPath}
placeholder="m/44'/60'/0'/0"
onChange={this.handleChangeCustomPath}
/>
</div>
<button
className="DWModal-path-submit btn btn-success"
disabled={!isValidPath(customPath)}
>
<i className="fa fa-check" />
</button>
</React.Fragment>
)}
</form>
@ -215,7 +229,7 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
const { value: dPathLabel } = newPath;
const { value } = this.findDPath('value', dPathLabel);
if (value === 'custom') {
if (value === customDPath.value) {
this.setState({ isCustomPath: true, currentLabel: dPathLabel });
} else {
this.setState({ isCustomPath: false, currentLabel: dPathLabel });
@ -228,11 +242,12 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
};
private handleSubmitCustomPath = (ev: React.FormEvent<HTMLFormElement>) => {
const { customPath, currentLabel } = this.state;
ev.preventDefault();
if (!isValidPath(this.state.customPath)) {
return;
if (currentLabel === customDPath.label && isValidPath(customPath)) {
this.props.onPathChange(customPath);
}
this.props.onPathChange(this.state.customPath);
};
private handleChangeToken = (ev: React.FormEvent<HTMLSelectElement>) => {
@ -257,6 +272,18 @@ class DeterministicWalletsModalClass extends React.PureComponent<Props, State> {
this.setState({ page: Math.max(this.state.page - 1, 0) }, this.getAddresses);
};
private renderDPathOption(option: Option) {
if (option.value === customDPath.value) {
return translate('ADD_Radio_5_PathCustom');
}
return (
<React.Fragment>
{option.label} {option.value && <small>({option.value.toString().replace(' ', '')})</small>}
</React.Fragment>
);
}
private renderWalletRow(wallet: DeterministicWalletData) {
const { desiredToken, network } = this.props;
const { selectedAddress } = this.state;

View File

@ -68,5 +68,5 @@ export const EXTRA_PATHS = [ETH_SINGULAR];
// whitespace strings are evaluated the same way as nospace strings, except they allow optional spaces between each portion of the string
// ie. "m / 44' / 0' / 0'" is valid, "m / 4 4' / 0' / 0'" is invalid
export const dPathRegex = /m\/44'\/[0-9]+\'\/[0-9]+(\'+$|\'+(\/[0-1]+$))/;
export const dPathRegex = /m\/(44|0)'\/[0-9]+\'\/[0-9]+(\'+$|\'+(\/[0-1]+$))/;
// export const whitespaceDPathRegex = /m\s*\/\s*44'\s*\/\s*[0-9]+\'\s*\/\s*[0-9]+(\'+$|\'+\s*(\/\s*[0-1]+$))/;