Cache pernt/child display parts (#2117)

This commit is contained in:
Jaco Greeff 2020-01-14 13:53:22 +01:00 committed by GitHub
parent ff6d5fb91c
commit 42993c9bdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 91 additions and 26 deletions

View File

@ -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<DerivedBalances>(api.derive.balances.all as any, [stashId]);
const stakingAccount = useCall<DerivedStakingAccount>(api.derive.staking.account as any, [stashId]);
const [{ controllerId, destination, hexSessionIdQueue, hexSessionIdNext, isLoading, isOwnController, isStashNominating, isStashValidating, nominees, sessionIds, validatorPrefs }, setStakeState] = useState<StakeState>({ 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
: (
<td>
{isStashNominating && nominees && (
<details>
<summary>{t('Nominating ({{count}})', { replace: { count: nominees.length } })}</summary>
{nominees.map((nomineeId, index): React.ReactNode => (
<AddressMini
key={index}
value={nomineeId}
withBalance={false}
withBonded
/>
))}
</details>
<>
<details>
<summary>{t('Nominating ({{count}})', { replace: { count: nominees.length } })}</summary>
{nominees.map((nomineeId, index): React.ReactNode => (
<AddressMini
key={index}
value={nomineeId}
withBalance={false}
withBonded
/>
))}
</details>
{inactives.length !== 0 && (
<details>
<summary>{t('Inactive ({{count}})', { replace: { count: inactives.length } })}</summary>
{inactives.map((nomineeId, index): React.ReactNode => (
<AddressMini
key={index}
value={nomineeId}
withBalance={false}
withBonded
/>
))}
</details>
)}
</>
)}
</td>
)

View File

@ -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<string[]>([]);
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;
}

View File

@ -34,25 +34,25 @@ interface Props extends BareProps {
withShort?: boolean;
}
const nameCache: Map<string, [boolean, React.ReactNode]> = new Map();
const nameCache: Map<string, [boolean, [React.ReactNode, React.ReactNode | null]]> = 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<Props> {
@ -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 (
<div className='via-identity'>
<span className={`name ${isLocal ? 'isLocal' : (isAddress ? 'isAddress' : '')}`}>{name}</span>
<span className={`name ${isLocal ? 'isLocal' : (isAddress ? 'isAddress' : '')}`}>{
displaySecond
? <><span className='top'>{displayFirst}</span><span className='sub'>/{displaySecond}</span></>
: displayFirst
}</span>
</div>
);
};
@ -138,10 +142,12 @@ function AccountName ({ children, className, defaultName, label, onClick, overri
<td><AddressMini value={identity.parent} /></td>
</tr>
)}
<tr>
<td>{t('display')}</td>
<td>{identity.display}</td>
</tr>
{identity.display && (
<tr>
<td>{t('display')}</td>
<td>{identity.display}</td>
</tr>
)}
{identity.legal && (
<tr>
<td>{t('legal')}</td>
@ -213,13 +219,13 @@ function AccountName ({ children, className, defaultName, label, onClick, overri
</div>
);
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));