diff --git a/packages/app-accounts/src/Editor.js b/packages/app-accounts/src/Editor.js index 956758c4c2..1b3023f740 100644 --- a/packages/app-accounts/src/Editor.js +++ b/packages/app-accounts/src/Editor.js @@ -99,7 +99,7 @@ class Editor extends React.PureComponent { } createOptions (): KeyringOptions { - return createOptions(this.props.keyring); + return createOptions(false, this.props.keyring, true); } createState (currentPair: KeyringPair): $Shape { diff --git a/packages/app-extrinsics/src/Account.js b/packages/app-extrinsics/src/Account.js index 2a7e6831df..9d8fbf84bc 100644 --- a/packages/app-extrinsics/src/Account.js +++ b/packages/app-extrinsics/src/Account.js @@ -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 { } 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 {
.text { width: 100%; } + +.ui--InputAddress input.search { + margin-left: 3rem; +} diff --git a/packages/ui-react-app/src/InputAddress/PairDisplay.js b/packages/ui-react-app/src/InputAddress/PairDisplay.js index 4b700dbf92..4327f1f7c0 100644 --- a/packages/ui-react-app/src/InputAddress/PairDisplay.js +++ b/packages/ui-react-app/src/InputAddress/PairDisplay.js @@ -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 (
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 ( ); diff --git a/packages/ui-react-app/src/InputAddress/optionItem.js b/packages/ui-react-app/src/InputAddress/optionItem.js new file mode 100644 index 0000000000..121cbb0fce --- /dev/null +++ b/packages/ui-react-app/src/InputAddress/optionItem.js @@ -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: ( + + ), + value: address + }; +} diff --git a/packages/ui-react-app/src/InputAddress/options.js b/packages/ui-react-app/src/InputAddress/options.js index 3470733d11..177683d4c2 100644 --- a/packages/ui-react-app/src/InputAddress/options.js +++ b/packages/ui-react-app/src/InputAddress/options.js @@ -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: ( - - ), - 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]; } diff --git a/packages/ui-react-app/src/InputAddress/types.js b/packages/ui-react-app/src/InputAddress/types.js index 9418c227dd..82e3281605 100644 --- a/packages/ui-react-app/src/InputAddress/types.js +++ b/packages/ui-react-app/src/InputAddress/types.js @@ -4,7 +4,9 @@ // @flow export type KeyringOption = { - text: React$Node, + 'data-manual'?: boolean, + name: string, + text: React$Node | string, value: string }; diff --git a/packages/ui-react-app/src/Params/Param/Account.js b/packages/ui-react-app/src/Params/Param/Account.js index 678a63ad11..afc5ebad8b 100644 --- a/packages/ui-react-app/src/Params/Param/Account.js +++ b/packages/ui-react-app/src/Params/Param/Account.js @@ -26,8 +26,10 @@ export default function Account ({ index, isError, label, onChange, t, value: { > ); diff --git a/packages/ui-react-app/src/Params/index.js b/packages/ui-react-app/src/Params/index.js index d4003eff63..0d859222db 100644 --- a/packages/ui-react-app/src/Params/index.js +++ b/packages/ui-react-app/src/Params/index.js @@ -67,8 +67,6 @@ class Params extends React.PureComponent { return null; } - console.log('Params', paramNames, params); - return (