Make active/waiting click "snappy" (#7361)

This commit is contained in:
Jaco 2022-04-12 10:09:53 +02:00 committed by GitHub
parent ec02457b8f
commit a983a07261
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 55 deletions

View File

@ -15,8 +15,8 @@ interface Props {
className?: string;
nameFilter: string;
setNameFilter: (value: string, isQuery: boolean) => void;
setWithIdentity: (value: boolean) => void;
withIdentity: boolean;
setWithIdentity?: (value: boolean) => void;
withIdentity?: boolean;
}
function Filtering ({ children, className, nameFilter, setNameFilter, setWithIdentity, withIdentity }: Props): React.ReactElement<Props> | null {
@ -47,17 +47,19 @@ function Filtering ({ children, className, nameFilter, setNameFilter, setWithIde
onChange={_setNameFilter}
value={nameFilter}
/>
<div className='staking--optionsBar'>
{children}
{api.query.identity && (
<Toggle
className='staking--buttonToggle'
label={t<string>('with an identity')}
onChange={setWithIdentity}
value={withIdentity}
/>
)}
</div>
{(children || setWithIdentity) && (
<div className='staking--optionsBar'>
{children}
{setWithIdentity && api.query.identity && (
<Toggle
className='staking--buttonToggle'
label={t<string>('with an identity')}
onChange={setWithIdentity}
value={withIdentity}
/>
)}
</div>
)}
</div>
);
}

View File

@ -38,7 +38,7 @@ interface Props {
recentlyOnline?: DeriveHeartbeatAuthor;
toggleFavorite: (accountId: string) => void;
validatorInfo?: ValidatorInfo;
withIdentity: boolean;
withIdentity?: boolean;
}
interface StakingState {

View File

@ -10,7 +10,7 @@ import type { NominatedByMap, SortedTargets, ValidatorInfo } from '../types';
import React, { useContext, useMemo, useRef, useState } from 'react';
import { Table } from '@polkadot/react-components';
import { useApi, useCall, useLoadingDelay, useSavedFlags } from '@polkadot/react-hooks';
import { useApi, useLoadingDelay } from '@polkadot/react-hooks';
import { BlockAuthorsContext } from '@polkadot/react-query';
import Filtering from '../Filtering';
@ -29,6 +29,7 @@ interface Props {
nominatedBy?: NominatedByMap;
ownStashIds?: string[];
paraValidators?: Record<string, boolean>;
recentlyOnline?: DeriveHeartbeats;
setNominators?: (nominators: string[]) => void;
stakingOverview?: DeriveStakingOverview;
targets: SortedTargets;
@ -73,7 +74,11 @@ function accountsToString (accounts: AccountId[]): string[] {
return accounts.map((a) => a.toString());
}
function getFiltered (isOwn: boolean, stakingOverview: DeriveStakingOverview, favorites: string[], next?: string[], ownStashIds?: string[]): Filtered {
function getFiltered (isOwn: boolean, stakingOverview: DeriveStakingOverview | undefined, favorites: string[], next?: string[], ownStashIds?: string[]): Filtered {
if (!stakingOverview) {
return {};
}
const allElected = accountsToString(stakingOverview.nextElected);
const validatorIds = accountsToString(stakingOverview.validators);
@ -87,24 +92,31 @@ function getFiltered (isOwn: boolean, stakingOverview: DeriveStakingOverview, fa
const DEFAULT_PARAS = {};
function CurrentList ({ className, favorites, hasQueries, isIntentions, isOwn, minCommission, nominatedBy, ownStashIds, paraValidators = DEFAULT_PARAS, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement<Props> | null {
function CurrentList ({ className, favorites, hasQueries, isIntentions, isOwn, minCommission, nominatedBy, ownStashIds, paraValidators = DEFAULT_PARAS, recentlyOnline, stakingOverview, targets, toggleFavorite }: Props): React.ReactElement<Props> | null {
const { t } = useTranslation();
const { api } = useApi();
const { byAuthor, eraPoints } = useContext(isIntentions ? EmptyAuthorsContext : BlockAuthorsContext);
const recentlyOnline = useCall<DeriveHeartbeats>(!isIntentions && api.derive.imOnline?.receivedHeartbeats);
const [nameFilter, setNameFilter] = useState<string>('');
const [toggles, setToggle] = useSavedFlags('staking:overview', { withIdentity: false });
// we have a very large list, so we use a loading delay
const isLoading = useLoadingDelay();
const { validators, waiting } = useMemo(
() => stakingOverview ? getFiltered(isOwn, stakingOverview, favorites, targets.waitingIds, ownStashIds) : {},
() => getFiltered(isOwn, stakingOverview, favorites, targets.waitingIds, ownStashIds),
[favorites, isOwn, ownStashIds, stakingOverview, targets]
);
const list = useMemo(
() => isLoading
? undefined
: isIntentions
? nominatedBy && waiting
: validators,
[isIntentions, isLoading, nominatedBy, validators, waiting]
);
const infoMap = useMemo(
() => targets.validators?.reduce<Record<string, ValidatorInfo>>((result, info) => {
() => targets.validators && targets.validators.reduce<Record<string, ValidatorInfo>>((result, info) => {
result[info.key] = info;
return result;
@ -137,11 +149,9 @@ function CurrentList ({ className, favorites, hasQueries, isIntentions, isOwn, m
<Table
className={className}
empty={
!isLoading && (
isIntentions
? waiting && nominatedBy && t<string>('No waiting validators found')
: recentlyOnline && validators && infoMap && t<string>('No active validators found')
)
isIntentions
? list && t<string>('No waiting validators found')
: list && recentlyOnline && infoMap && t<string>('No active validators found')
}
emptySpinner={
<>
@ -151,14 +161,13 @@ function CurrentList ({ className, favorites, hasQueries, isIntentions, isOwn, m
? !nominatedBy && <div>{t<string>('Retrieving nominators')}</div>
: !recentlyOnline && <div>{t<string>('Retrieving online status')}</div>
}
{!list && <div>{t<string>('Preparing validator list')}</div>}
</>
}
filter={
<Filtering
nameFilter={nameFilter}
setNameFilter={setNameFilter}
setWithIdentity={setToggle.withIdentity}
withIdentity={toggles.withIdentity}
/>
}
header={headerRef.current}
@ -169,12 +178,7 @@ function CurrentList ({ className, favorites, hasQueries, isIntentions, isOwn, m
/>
}
>
{!isLoading && (
(isIntentions
? nominatedBy && waiting
: validators
) || []
).map(([address, isElected, isFavorite]): React.ReactNode => (
{list && list.map(([address, isElected, isFavorite]): React.ReactNode => (
<Address
address={address}
filterName={nameFilter}
@ -191,7 +195,6 @@ function CurrentList ({ className, favorites, hasQueries, isIntentions, isOwn, m
recentlyOnline={recentlyOnline?.[address]}
toggleFavorite={toggleFavorite}
validatorInfo={infoMap?.[address]}
withIdentity={toggles.withIdentity}
/>
))}
</Table>

View File

@ -1,7 +1,7 @@
// Copyright 2017-2022 @polkadot/app-staking authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { DeriveStakingOverview } from '@polkadot/api-derive/types';
import type { DeriveHeartbeats, DeriveStakingOverview } from '@polkadot/api-derive/types';
import type { StakerState } from '@polkadot/react-hooks/types';
import type { BN } from '@polkadot/util';
import type { NominatedByMap, SortedTargets } from '../types';
@ -9,6 +9,7 @@ import type { NominatedByMap, SortedTargets } from '../types';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Button, ToggleGroup } from '@polkadot/react-components';
import { useApi, useCall } from '@polkadot/react-hooks';
import { useTranslation } from '../translate';
import CurrentList from './CurrentList';
@ -30,8 +31,10 @@ interface Props {
function Overview ({ className = '', favorites, hasQueries, minCommission, nominatedBy, ownStashes, paraValidators, stakingOverview, targets, toggleFavorite, toggleLedger, toggleNominatedBy }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const [intentIndex, _setIntentIndex] = useState(0);
const [typeIndex, setTypeIndex] = useState(1);
const recentlyOnline = useCall<DeriveHeartbeats>(api.derive.imOnline?.receivedHeartbeats);
const setIntentIndex = useCallback(
(index: number): void => {
@ -77,32 +80,20 @@ function Overview ({ className = '', favorites, hasQueries, minCommission, nomin
/>
</Button.Group>
<CurrentList
className={intentIndex === 0 ? '' : '--hidden'}
favorites={favorites}
hasQueries={hasQueries}
isIntentions={intentIndex === 1}
isOwn={isOwn}
minCommission={minCommission}
key={intentIndex}
minCommission={intentIndex === 0 ? minCommission : undefined}
nominatedBy={intentIndex === 1 ? nominatedBy : undefined}
ownStashIds={ownStashIds}
paraValidators={paraValidators}
recentlyOnline={intentIndex === 0 ? recentlyOnline : undefined}
stakingOverview={stakingOverview}
targets={targets}
toggleFavorite={toggleFavorite}
/>
{intentIndex === 1 && (
<CurrentList
className={intentIndex === 1 ? '' : '--hidden'}
favorites={favorites}
hasQueries={hasQueries}
isIntentions
isOwn={isOwn}
nominatedBy={nominatedBy}
ownStashIds={ownStashIds}
paraValidators={paraValidators}
stakingOverview={stakingOverview}
targets={targets}
toggleFavorite={toggleFavorite}
/>
)}
</div>
);
}

View File

@ -391,13 +391,14 @@ function Targets ({ className = '', isInElection, nominatedBy, ownStashes, targe
<>
{!(validators && allIdentity) && <div>{t('Retrieving validators')}</div>}
{!nominatedBy && <div>{t('Retrieving nominators')}</div>}
{!displayList && <div>{t('Preparing target display')}</div>}
</>
}
filter={filter}
header={header}
legend={<Legend />}
>
{displayList?.map((info): React.ReactNode =>
{displayList && displayList.map((info): React.ReactNode =>
<Validator
allSlashes={allSlashes}
canSelect={selected.length < maxNominations}

View File

@ -6,7 +6,7 @@ import { useEffect, useState } from 'react';
import { createNamedHook } from './createNamedHook';
import { useIsMountedRef } from './useIsMountedRef';
function useLoadingDelayImpl (delay = 100): boolean {
function useLoadingDelayImpl (delay = 0): boolean {
const mountedRef = useIsMountedRef();
const [isLoading, setIsLoading] = useState(true);