From 42993c9bdf27dba23a49fd8ee5c95e76079e375e Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Tue, 14 Jan 2020 13:53:22 +0100 Subject: [PATCH] Cache pernt/child display parts (#2117) --- .../app-staking/src/Actions/Account/index.tsx | 39 ++++++++++++----- .../src/Actions/Account/useInactives.ts | 42 +++++++++++++++++++ packages/react-components/src/AccountName.tsx | 36 +++++++++------- 3 files changed, 91 insertions(+), 26 deletions(-) create mode 100644 packages/app-staking/src/Actions/Account/useInactives.ts diff --git a/packages/app-staking/src/Actions/Account/index.tsx b/packages/app-staking/src/Actions/Account/index.tsx index c281568c15..478c0deae1 100644 --- a/packages/app-staking/src/Actions/Account/index.tsx +++ b/packages/app-staking/src/Actions/Account/index.tsx @@ -22,6 +22,7 @@ import SetRewardDestination from './SetRewardDestination'; import SetSessionKey from './SetSessionKey'; import Unbond from './Unbond'; import Validate from './Validate'; +import useInactives from './useInactives'; type ValidatorInfo = ITuple<[ValidatorPrefs, Codec]>; @@ -93,6 +94,7 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, staki const balancesAll = useCall(api.derive.balances.all as any, [stashId]); const stakingAccount = useCall(api.derive.staking.account as any, [stashId]); const [{ controllerId, destination, hexSessionIdQueue, hexSessionIdNext, isLoading, isOwnController, isStashNominating, isStashValidating, nominees, sessionIds, validatorPrefs }, setStakeState] = useState({ controllerId: null, destination: 0, hexSessionIdNext: null, hexSessionIdQueue: null, isLoading: true, isOwnController: false, isStashNominating: false, isStashValidating: false, sessionIds: [] }); + const inactives = useInactives(stashId, nominees); const [isBondExtraOpen, toggleBondExtra] = useToggle(); const [isInjectOpen, toggleInject] = useToggle(); const [isNominateOpen, toggleNominate] = useToggle(); @@ -214,17 +216,32 @@ function Account ({ allStashes, className, isOwnStash, next, onUpdateType, staki : ( {isStashNominating && nominees && ( -
- {t('Nominating ({{count}})', { replace: { count: nominees.length } })} - {nominees.map((nomineeId, index): React.ReactNode => ( - - ))} -
+ <> +
+ {t('Nominating ({{count}})', { replace: { count: nominees.length } })} + {nominees.map((nomineeId, index): React.ReactNode => ( + + ))} +
+ {inactives.length !== 0 && ( +
+ {t('Inactive ({{count}})', { replace: { count: inactives.length } })} + {inactives.map((nomineeId, index): React.ReactNode => ( + + ))} +
+ )} + )} ) diff --git a/packages/app-staking/src/Actions/Account/useInactives.ts b/packages/app-staking/src/Actions/Account/useInactives.ts new file mode 100644 index 0000000000..9740c09e3a --- /dev/null +++ b/packages/app-staking/src/Actions/Account/useInactives.ts @@ -0,0 +1,42 @@ +// Copyright 2017-2020 @polkadot/ui-staking 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 { Exposure } from '@polkadot/types/interfaces'; + +import { useEffect, useState } from 'react'; +import { useApi, useIsMountedRef } from '@polkadot/react-hooks'; + +export default function useInactives (stashId: string, nominees?: string[]): string[] { + const { api } = useApi(); + const mountedRef = useIsMountedRef(); + const [inactives, setInactives] = useState([]); + + useEffect((): () => void => { + let unsub: (() => void) | undefined; + + if (mountedRef.current && nominees?.length) { + api.query.staking.stakers + .multi(nominees, (exposures: Exposure[]): void => { + const inactives: string[] = []; + + exposures.forEach((exposure, index): void => { + if (!exposure.others.some((indv): boolean => indv.who.eq(stashId))) { + inactives.push(nominees[index].toString()); + } + }); + + setInactives(inactives); + }) + .then((_unsub): void => { + unsub = _unsub; + }); + } + + return (): void => { + unsub && unsub(); + }; + }, [nominees, stashId]); + + return inactives; +} diff --git a/packages/react-components/src/AccountName.tsx b/packages/react-components/src/AccountName.tsx index 55dcedbd9a..56192c6d07 100644 --- a/packages/react-components/src/AccountName.tsx +++ b/packages/react-components/src/AccountName.tsx @@ -34,25 +34,25 @@ interface Props extends BareProps { withShort?: boolean; } -const nameCache: Map = new Map(); +const nameCache: Map = new Map(); -function defaultOrAddr (defaultName = '', _address: AccountId | AccountIndex | Address | string | Uint8Array, _accountIndex?: AccountIndex | null): [React.ReactNode, boolean, boolean] { +function defaultOrAddr (defaultName = '', _address: AccountId | AccountIndex | Address | string | Uint8Array, _accountIndex?: AccountIndex | null): [[React.ReactNode, React.ReactNode | null], boolean, boolean] { const accountId = _address.toString(); const accountIndex = (_accountIndex || '').toString(); const [isAddressExtracted,, extracted] = getAddressName(accountId, null, defaultName); - const [isAddressCached, nameCached] = nameCache.get(accountId) || [false, null]; + const [isAddressCached, nameCached] = nameCache.get(accountId) || [false, [null, null]]; if (extracted && isAddressCached && !isAddressExtracted) { // skip, default return - } else if (nameCached) { + } else if (nameCached[0]) { return [nameCached, false, isAddressCached]; } else if (isAddressExtracted && accountIndex) { - nameCache.set(accountId, [true, accountIndex]); + nameCache.set(accountId, [true, [accountIndex, null]]); - return [accountIndex, false, true]; + return [[accountIndex, null], false, true]; } - return [extracted, !isAddressExtracted, isAddressExtracted]; + return [[extracted, null], !isAddressExtracted, isAddressExtracted]; } function AccountName ({ children, className, defaultName, label, onClick, override, style, toggle, value, withShort }: Props): React.ReactElement { @@ -70,11 +70,15 @@ function AccountName ({ children, className, defaultName, label, onClick, overri const address = useMemo((): string => (value || '').toString(), [value]); const _extractName = (accountId?: AccountId, accountIndex?: AccountIndex): React.ReactNode => { - const [name, isLocal, isAddress] = defaultOrAddr(defaultName, accountId || address, withShort ? null : accountIndex); + const [[displayFirst, displaySecond], isLocal, isAddress] = defaultOrAddr(defaultName, accountId || address, withShort ? null : accountIndex); return (
- {name} + { + displaySecond + ? <>{displayFirst}/{displaySecond} + : displayFirst + }
); }; @@ -138,10 +142,12 @@ function AccountName ({ children, className, defaultName, label, onClick, overri )} - - {t('display')} - {identity.display} - + {identity.display && ( + + {t('display')} + {identity.display} + + )} {identity.legal && ( {t('legal')} @@ -213,13 +219,13 @@ function AccountName ({ children, className, defaultName, label, onClick, overri ); - nameCache.set(address, [false, displayName]); + nameCache.set(address, [false, displayParent ? [displayParent, displayName] : [displayName, null]]); setName((): React.ReactNode => name); } else { setName((): React.ReactNode => _extractName(accountId, accountIndex)); } } else if (nickname) { - nameCache.set(address, [false, nickname]); + nameCache.set(address, [false, [nickname, null]]); setName(nickname); } else { setName(defaultOrAddr(defaultName, accountId || address, withShort ? null : accountIndex));