Display IdentityIcon with chain prefix (#218)
* Display IdentitIcon with chain prefix * Cleanups, make it actually work
This commit is contained in:
@@ -23,28 +23,24 @@ type Props = {};
|
||||
export default function Accounts (): React.ReactElement<Props> {
|
||||
const accounts = useContext(AccountContext);
|
||||
const mediaAllowed = useContext(MediaContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
(accounts.length === 0)
|
||||
? <AddAccount />
|
||||
: (
|
||||
<>
|
||||
<Header showSettings text={'Accounts'} />
|
||||
<AccountsArea>
|
||||
<>
|
||||
{
|
||||
accounts.map((json, index): React.ReactNode => (
|
||||
<Account
|
||||
{...json}
|
||||
key={`${index}:${json.address}`}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</>
|
||||
</AccountsArea>
|
||||
</>
|
||||
)
|
||||
{(accounts.length === 0)
|
||||
? <AddAccount />
|
||||
: (
|
||||
<>
|
||||
<Header showSettings text={'Accounts'} />
|
||||
<AccountsArea>
|
||||
{accounts.map((json, index): React.ReactNode => (
|
||||
<Account
|
||||
{...json}
|
||||
key={`${index}:${json.address}`}
|
||||
/>
|
||||
))}
|
||||
</AccountsArea>
|
||||
</>
|
||||
)
|
||||
}
|
||||
<ButtonArea>
|
||||
<ButtonWithSubtitle
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
// Copyright 2019-2020 @polkadot/extension-ui authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import settings from '@polkadot/ui-settings';
|
||||
import { setSS58Format } from '@polkadot/util-crypto';
|
||||
|
||||
import { Button, Dropdown } from '../../components';
|
||||
import { windowOpen } from '../../messaging';
|
||||
import { Back } from '../../partials';
|
||||
|
||||
interface Option {
|
||||
text: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
// There are probably better ways, but since we set the popup size, use that
|
||||
const isPopup = window.innerWidth <= 480;
|
||||
const cameraOptions = settings.availableCamera.map(({ text, value }): Option => ({ text, value: `${value}` }));
|
||||
const prefixOptions = settings.availablePrefixes.map(({ text, value }): Option => ({
|
||||
text: value === -1
|
||||
? 'Default (Substrate or as specified)'
|
||||
: text,
|
||||
value: `${value}`
|
||||
}));
|
||||
|
||||
export default function Settings (): React.ReactElement<{}> {
|
||||
const [camera, setCamera] = useState(settings.camera);
|
||||
const [prefix, setPrefix] = useState(`${settings.prefix}`);
|
||||
|
||||
const _onChangeCamera = (camera: string): void => {
|
||||
setCamera(camera);
|
||||
|
||||
settings.set({ camera });
|
||||
};
|
||||
|
||||
// FIXME check against index, we need a better solution
|
||||
const _onChangePrefix = (value: string): void => {
|
||||
const prefix = parseInt(value, 10);
|
||||
|
||||
setSS58Format(prefix === -1 ? 42 : prefix);
|
||||
setPrefix(value);
|
||||
|
||||
settings.set({ prefix });
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Back />
|
||||
<Dropdown
|
||||
label='display addresses formatted for'
|
||||
onChange={_onChangePrefix}
|
||||
options={prefixOptions}
|
||||
value={`${prefix}`}
|
||||
/>
|
||||
<Dropdown
|
||||
label='external QR accounts and access'
|
||||
onChange={_onChangeCamera}
|
||||
options={cameraOptions}
|
||||
value={camera}
|
||||
/>
|
||||
{isPopup && (
|
||||
<Button onClick={windowOpen}>Open extension in new window</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import Export from './Export';
|
||||
import Forget from './Forget';
|
||||
import ImportQr from './ImportQr';
|
||||
import ImportSeed from './ImportSeed';
|
||||
import Settings from './Settings';
|
||||
import Signing from './Signing';
|
||||
import Welcome from './Welcome';
|
||||
|
||||
@@ -100,7 +99,6 @@ export default function Popup (): React.ReactElement<{}> {
|
||||
<Route path='/account/export/:address' component={Export} />
|
||||
<Route path='/account/import-qr' component={ImportQr} />
|
||||
<Route path='/account/import-seed' component={ImportSeed} />
|
||||
<Route path='/settings' component={Settings} />
|
||||
<Route exact path='/' component={Root} />
|
||||
</Switch>
|
||||
</SigningContext.Provider>
|
||||
|
||||
@@ -27,6 +27,13 @@ interface Props {
|
||||
actions?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface Recoded {
|
||||
account: AccountJson | null;
|
||||
chain: Chain | null;
|
||||
formatted: string | null;
|
||||
prefix: number;
|
||||
}
|
||||
|
||||
// find an account in our list
|
||||
function findAccount (accounts: AccountJson[], publicKey: Uint8Array): AccountJson | null {
|
||||
const pkStr = publicKey.toString();
|
||||
@@ -37,29 +44,29 @@ function findAccount (accounts: AccountJson[], publicKey: Uint8Array): AccountJs
|
||||
}
|
||||
|
||||
// recodes an supplied address using the prefix/genesisHash, include the actual saved account & chain
|
||||
function recodeAddress (address: string, accounts: AccountJson[], genesisHash?: string | null): [string, AccountJson | null, Chain] {
|
||||
function recodeAddress (address: string, accounts: AccountJson[], genesisHash?: string | null): Recoded {
|
||||
// decode and create a shortcut for the encoded address
|
||||
const publicKey = decodeAddress(address);
|
||||
|
||||
// find our account using the actual publicKey, and then find the associated chain
|
||||
const account = findAccount(accounts, publicKey);
|
||||
const chain = findChain((account && account.genesisHash) || genesisHash);
|
||||
const chain = findChain(account?.genesisHash || genesisHash);
|
||||
const prefix = settings.prefix === -1 ? chain.ss58Format : settings.prefix;
|
||||
|
||||
return [
|
||||
// always allow the actual settings to override the display
|
||||
encodeAddress(publicKey, settings.prefix === -1 ? chain.ss58Format : settings.prefix),
|
||||
// always allow the actual settings to override the display
|
||||
return {
|
||||
account,
|
||||
chain
|
||||
];
|
||||
chain,
|
||||
formatted: encodeAddress(publicKey, prefix),
|
||||
prefix
|
||||
};
|
||||
}
|
||||
|
||||
const ACCOUNTS_SCREEN_HEIGHT = 500;
|
||||
|
||||
function Address ({ address, className, children, genesisHash, name, actions }: Props): React.ReactElement<Props> {
|
||||
const accounts = useContext(AccountContext);
|
||||
const [account, setAccount] = useState<AccountJson | null>(null);
|
||||
const [chain, setChain] = useState<Chain | null>(null);
|
||||
const [formatted, setFormatted] = useState<string | null>(null);
|
||||
const [{ account, chain, formatted, prefix }, setRecoded] = useState<Recoded>({ account: null, chain: null, formatted: null, prefix: 42 });
|
||||
const [showActionsMenu, setShowActionsMenu] = useState(false);
|
||||
const [moveMenuUp, setIsMovedMenu] = useState(false);
|
||||
const actionsRef = useRef<HTMLDivElement>(null);
|
||||
@@ -68,13 +75,9 @@ function Address ({ address, className, children, genesisHash, name, actions }:
|
||||
|
||||
useEffect((): void => {
|
||||
if (address) {
|
||||
const [formatted, account, chain] = recodeAddress(address, accounts, genesisHash);
|
||||
|
||||
setFormatted(formatted);
|
||||
setChain(chain);
|
||||
setAccount(account);
|
||||
setRecoded(recodeAddress(address, accounts, genesisHash));
|
||||
}
|
||||
}, [address]);
|
||||
}, [accounts, address, genesisHash]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showActionsMenu) {
|
||||
@@ -97,17 +100,23 @@ function Address ({ address, className, children, genesisHash, name, actions }:
|
||||
<AccountInfoRow>
|
||||
<Identicon
|
||||
iconTheme={theme}
|
||||
value={address}
|
||||
prefix={prefix}
|
||||
value={formatted || address}
|
||||
/>
|
||||
<Info>
|
||||
<Name>{name || (account && account.name) || '<unknown>'}</Name>
|
||||
<FullAddress>{formatted || '<unknown>'}</FullAddress>
|
||||
{chain?.genesisHash && <Banner>{chain.name}</Banner>}
|
||||
{chain?.genesisHash && (
|
||||
<Banner>{chain.name}</Banner>
|
||||
)}
|
||||
</Info>
|
||||
{actions && (
|
||||
<>
|
||||
<Settings onClick={_onClick}>
|
||||
{showActionsMenu ? <ActiveActionsIcon /> : <ActionsIcon />}
|
||||
{showActionsMenu
|
||||
? <ActiveActionsIcon />
|
||||
: <ActionsIcon />
|
||||
}
|
||||
</Settings>
|
||||
{showActionsMenu && (
|
||||
<MovableMenu
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import ArrowLeftImage from '../assets/arrowLeft.svg';
|
||||
import logo from '../assets/pjs.svg';
|
||||
import gear from '../assets/gear.svg';
|
||||
import { useOutsideClick } from '../hooks';
|
||||
|
||||
import Svg from '@polkadot/extension-ui/components/Svg';
|
||||
import Settings from './Settings';
|
||||
import ArrowLeftImage from '../assets/arrowLeft.svg';
|
||||
import Link from './Link';
|
||||
import Settings from './Settings';
|
||||
import Svg from './Svg';
|
||||
|
||||
interface Props {
|
||||
children?: React.ReactNode;
|
||||
|
||||
@@ -9,16 +9,18 @@ import Icon from '@polkadot/react-identicon';
|
||||
interface Props {
|
||||
iconTheme?: 'beachball' | 'empty' | 'jdenticon' | 'polkadot' | 'substrate';
|
||||
className?: string;
|
||||
prefix?: number;
|
||||
value?: string | null;
|
||||
}
|
||||
|
||||
function Identicon ({ iconTheme, className, value }: Props): React.ReactElement<Props> {
|
||||
function Identicon ({ iconTheme, className, prefix, value }: Props): React.ReactElement<Props> {
|
||||
return (
|
||||
<div className={className}>
|
||||
<Icon
|
||||
className='icon'
|
||||
size={64}
|
||||
theme={iconTheme}
|
||||
prefix={prefix}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -31,6 +31,7 @@ const prefixOptions = settings.availablePrefixes.map(({ text, value }): Option =
|
||||
value: `${value}`
|
||||
}));
|
||||
|
||||
// FIXME This does not belong in components, this is actual functionality
|
||||
export default function Settings ({ reference }: { reference: React.MutableRefObject<null> }): React.ReactElement {
|
||||
const [camera, setCamera] = useState(settings.camera === 'on');
|
||||
const [prefix, setPrefix] = useState(`${settings.prefix}`);
|
||||
@@ -49,6 +50,8 @@ export default function Settings ({ reference }: { reference: React.MutableRefOb
|
||||
setPrefix(value);
|
||||
|
||||
settings.set({ prefix });
|
||||
|
||||
// FIXME We don't want to reload here
|
||||
location.reload();
|
||||
};
|
||||
const _onChangeTheme = (checked: boolean): void => setTheme(checked ? 'dark' : 'light');
|
||||
|
||||
@@ -68,10 +68,13 @@ const lightTheme: Theme = {
|
||||
|
||||
export function chooseTheme (): AvailableThemes {
|
||||
const preferredTheme = localStorage.getItem('theme');
|
||||
|
||||
if (preferredTheme) {
|
||||
return preferredTheme === 'dark' ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
const isLightColorSchemePreferred = window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches;
|
||||
|
||||
return isLightColorSchemePreferred ? 'light' : 'dark';
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@ function Back ({ className, to = '/' }: Props): React.ReactElement<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
const ArrowLeft = styled(Svg).attrs(() => ({
|
||||
src: ArrowLeftImage
|
||||
}))`
|
||||
const ArrowLeft = styled(Svg).attrs(() => ({ src: ArrowLeftImage }))`
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 13px;
|
||||
|
||||
@@ -5460,7 +5460,7 @@ debug@3.1.0, debug@~3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
|
||||
debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||
@@ -5673,7 +5673,7 @@ detect-indent@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
|
||||
integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
|
||||
|
||||
detect-libc@^1.0.2, detect-libc@^1.0.3:
|
||||
detect-libc@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
@@ -7998,7 +7998,7 @@ humanize-url@^1.0.0:
|
||||
normalize-url "^1.0.0"
|
||||
strip-url-auth "^1.0.0"
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
@@ -10469,15 +10469,6 @@ nearley@^2.7.10:
|
||||
randexp "0.4.6"
|
||||
semver "^5.4.1"
|
||||
|
||||
needle@^2.2.1:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c"
|
||||
integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==
|
||||
dependencies:
|
||||
debug "^3.2.6"
|
||||
iconv-lite "^0.4.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
negotiator@0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
@@ -10626,22 +10617,6 @@ node-notifier@^6.0.0:
|
||||
shellwords "^0.1.1"
|
||||
which "^1.3.1"
|
||||
|
||||
node-pre-gyp@*:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
|
||||
integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.2"
|
||||
mkdirp "^0.5.1"
|
||||
needle "^2.2.1"
|
||||
nopt "^4.0.1"
|
||||
npm-packlist "^1.1.6"
|
||||
npmlog "^4.0.2"
|
||||
rc "^1.2.7"
|
||||
rimraf "^2.6.1"
|
||||
semver "^5.3.0"
|
||||
tar "^4.4.2"
|
||||
|
||||
node-releases@^1.1.46:
|
||||
version "1.1.47"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.47.tgz#c59ef739a1fd7ecbd9f0b7cf5b7871e8a8b591e4"
|
||||
@@ -10763,7 +10738,7 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1:
|
||||
semver "^5.6.0"
|
||||
validate-npm-package-name "^3.0.0"
|
||||
|
||||
npm-packlist@^1.1.6, npm-packlist@^1.4.4:
|
||||
npm-packlist@^1.4.4:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
|
||||
integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
|
||||
@@ -10795,7 +10770,7 @@ npm-run-path@^4.0.0:
|
||||
dependencies:
|
||||
path-key "^3.0.0"
|
||||
|
||||
npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2:
|
||||
npmlog@^4.0.1, npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
@@ -12972,7 +12947,7 @@ rimraf@2.6.3:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3:
|
||||
rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
||||
@@ -13084,7 +13059,7 @@ sass-lookup@^3.0.0:
|
||||
dependencies:
|
||||
commander "^2.16.0"
|
||||
|
||||
sax@^1.2.4, sax@~1.2.4:
|
||||
sax@~1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
@@ -14092,7 +14067,7 @@ tar-stream@^2.0.0:
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar@^4.4.10, tar@^4.4.12, tar@^4.4.2, tar@^4.4.8:
|
||||
tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
|
||||
version "4.4.13"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
||||
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
|
||||
|
||||
Reference in New Issue
Block a user