Allow external address input (#34)

* Allow external address input

* Remove hold-over debug log
This commit is contained in:
Jaco Greeff 2018-05-09 17:54:17 +02:00 committed by GitHub
parent 9206cbf7fc
commit e02b971998
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 108 additions and 38 deletions

View File

@ -99,7 +99,7 @@ class Editor extends React.PureComponent<Props, State> {
}
createOptions (): KeyringOptions {
return createOptions(this.props.keyring);
return createOptions(false, this.props.keyring, true);
}
createState (currentPair: KeyringPair): $Shape<State> {

View File

@ -15,6 +15,7 @@ import translate from './translate';
type Props = I18nProps & {
defaultValue?: Uint8Array,
isError?: boolean,
isInput?: boolean,
label: string,
onChange: (publicKey: Uint8Array) => void
};
@ -35,7 +36,7 @@ class Account extends React.PureComponent<Props, State> {
}
render (): React$Node {
const { className, defaultValue, label, style, t } = this.props;
const { className, defaultValue, isError, isInput, label, style, t } = this.props;
const { publicKey } = this.state;
return (
@ -46,6 +47,8 @@ class Account extends React.PureComponent<Props, State> {
<div className='large'>
<InputAddress
defaultValue={defaultValue}
isError={isError}
isInput={isInput}
label={label}
onChange={this.onChange}
placeholder='0x...'

View File

@ -25,6 +25,7 @@ export default function Account ({ className, defaultValue, index, isError, onCh
className={className}
defaultValue={defaultValue}
isError={isError}
isInput
label={label}
onChange={_onChange}
style={style}

View File

@ -7,3 +7,7 @@
.ui--InputAddress > .text {
width: 100%;
}
.ui--InputAddress input.search {
margin-left: 3rem;
}

View File

@ -3,25 +3,21 @@
// of the ISC license. See the LICENSE file for details.
// @flow
import type { KeyringPair } from '@polkadot/util-keyring/types';
import './PairDisplay.css';
import React from 'react';
import IdentityIcon from '@polkadot/ui-react/IdentityIcon';
type Props = {
address: string,
className?: string,
pair: KeyringPair,
name: string,
style?: {
[string]: string
}
};
export default function PairDisplay ({ className, pair, style }: Props): React$Node {
const address = pair.address();
const { name } = pair.getMeta();
export default function PairDisplay ({ address, className, name, style }: Props): React$Node {
return (
<div
className={['ui--InputyAddress-PairDisplay', className].join(' ')}

View File

@ -3,7 +3,6 @@
// of the ISC license. See the LICENSE file for details.
// @flow
import type { KeyringInstance } from '@polkadot/util-keyring/types';
import type { BareProps } from '../types';
import type { KeyringOptions } from './types';
@ -14,36 +13,64 @@ import addressDecode from '@polkadot/util-keyring/address/decode';
import addressEncode from '@polkadot/util-keyring/address/encode';
import RxDropdown from '../RxDropdown';
import createItem from './optionItem';
import createOptions from './options';
type Props = BareProps & {
defaultValue?: Uint8Array,
isError?: boolean,
keyring?: KeyringInstance,
isInput?: boolean,
label?: string,
onChange: (value: Uint8Array) => void,
options?: KeyringOptions
options?: KeyringOptions,
withInput?: boolean
};
const transform = (value: string): Uint8Array =>
addressDecode(value);
export default function InputAddress ({ className, defaultValue, isError, keyring, label, onChange, options, style }: Props): React$Node {
const _options = options || createOptions(keyring);
let _defaultValue;
if (defaultValue) {
_defaultValue = addressEncode(defaultValue);
const transform = (value: string): Uint8Array => {
try {
return addressDecode(value);
} catch (error) {
return new Uint8Array([]);
}
};
export default function InputAddress ({ className, defaultValue, isError, isInput = false, label, onChange, options, style }: Props): React$Node {
const _options = options || createOptions(isInput);
const onSearch = (filteredOptions: KeyringOptions, query: string): KeyringOptions => {
const queryLower = query.toLowerCase();
const matches = filteredOptions.filter((item) => {
const { name, value } = item;
const isManual = item['data-manual'] || false;
const hasMatch = name.toLowerCase().indexOf(queryLower) !== -1 ||
value.toLowerCase().indexOf(queryLower) !== -1;
return hasMatch && (isInput || !isManual);
});
// see if we should add a new item, i.e. valid address found
if (isInput && matches.length === 0) {
const publicKey = transform(query);
if (publicKey.length === 32) {
const newOption = createItem(query, `${query.slice(0, 16)}…`, true);
matches.push(newOption);
_options.push(newOption);
}
}
return matches;
};
return (
<RxDropdown
className={['ui--InputAddress', className].join(' ')}
defaultValue={_defaultValue}
defaultValue={defaultValue && addressEncode(defaultValue)}
isError={isError}
label={label}
onChange={onChange}
options={_options}
search={onSearch}
transform={transform}
/>
);

View File

@ -0,0 +1,27 @@
// Copyright 2017-2018 Jaco Greeff
// This software may be modified and distributed under the terms
// of the ISC license. See the LICENSE file for details.
// @flow
import type { KeyringOption } from './types';
import React from 'react';
import PairDisplay from './PairDisplay';
export default function createItem (address: string, name?: string, isManual: boolean = false): KeyringOption {
// flowlint-next-line sketchy-null-string:off
name = name || address;
return {
'data-manual': isManual,
name,
text: (
<PairDisplay
address={address}
name={name}
/>
),
value: address
};
}

View File

@ -6,18 +6,28 @@
import type { KeyringInstance } from '@polkadot/util-keyring/types';
import type { KeyringOptions } from './types';
import React from 'react';
import testKeyring from '../keyring';
import PairDisplay from './PairDisplay';
import createItem from './optionItem';
export default function createOptions (keyring?: KeyringInstance = testKeyring): KeyringOptions {
return keyring
.getPairs()
.map((pair) => ({
text: (
<PairDisplay pair={pair} />
),
value: pair.address()
}));
const cached: { [string]: ?KeyringOptions } = {
addresses: null,
accounts: null
};
export default function createOptions (isAddress?: boolean = false, keyring?: KeyringInstance = testKeyring, forceReload: boolean = false): KeyringOptions {
const map = isAddress ? 'addresses' : 'accounts';
if (forceReload || !cached[map]) {
cached[map] = keyring
.getPairs()
.map((pair) => {
const address = pair.address();
const { name } = pair.getMeta();
return createItem(address, name);
});
}
// $FlowFixMe we have checked and set just above
return cached[map];
}

View File

@ -4,7 +4,9 @@
// @flow
export type KeyringOption = {
text: React$Node,
'data-manual'?: boolean,
name: string,
text: React$Node | string,
value: string
};

View File

@ -26,8 +26,10 @@ export default function Account ({ index, isError, label, onChange, t, value: {
>
<InputAddress
defaultValue={defaultValue}
isError={isError}
isInput
onChange={_onChange}
placeholder='0x...'
placeholder='5...'
/>
</Base>
);

View File

@ -67,8 +67,6 @@ class Params extends React.PureComponent<Props, State> {
return null;
}
console.log('Params', paramNames, params);
return (
<div
className={['ui--Params', 'ui--form', className].join(' ')}