Skip to content

Commit

Permalink
refactor: add translation to account icons tooltips
Browse files Browse the repository at this point in the history
  • Loading branch information
Nick-1979 committed Oct 26, 2024
1 parent cf66353 commit 23616a4
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 85 deletions.
44 changes: 26 additions & 18 deletions packages/extension-polkagate/src/components/AccountIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,48 @@

/* eslint-disable react/jsx-max-props-per-line */

import type { Chain } from '@polkadot/extension-chains/types';
import type { IconTheme } from '@polkadot/react-identicon/types';
import type { Proxy } from '../util/types';

import { faShieldHalved, faSitemap } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Grid, IconButton, useTheme } from '@mui/material';
import React, { useCallback, useContext } from 'react';
import React, { useCallback, useContext, useEffect,useState } from 'react';

import { useAnimateOnce, useTranslation } from '../hooks';
import { useAnimateOnce, useHasProxyTooltipText, useInfo, useIsRecoverableTooltipText, useProxies } from '../hooks';
import { windowOpen } from '../messaging';
import { PROXY_CHAINS } from '../util/constants';
import { getSubstrateAddress } from '../util/utils';
import { ActionContext } from './contexts';
import Identicon from './Identicon';
import { Infotip } from '.';

interface Props {
chain: Chain | null | undefined;
formatted: string | undefined;
address: string | undefined;
identiconTheme: IconTheme;
isSubId: boolean;
judgements?: RegExpMatchArray | null | undefined;
prefix?: number;
proxies: Proxy[] | undefined;
recoverable?: boolean;
}

export default function AccountIcons ({ chain, formatted, identiconTheme, isSubId, judgements, prefix, proxies, recoverable = false }: Props): React.ReactElement<Props> {
function AccountIcons ({ address, identiconTheme, isSubId, judgements, prefix }: Props): React.ReactElement<Props> {
const theme = useTheme();
const { t } = useTranslation();
const onAction = useContext(ActionContext);

const address = getSubstrateAddress(formatted);
const { api, chain, formatted } = useInfo(address);
const proxies = useProxies(api, formatted);

const shakeProxy = useAnimateOnce(!!proxies?.length);
const shakeShield = useAnimateOnce(recoverable);

const [isRecoverable, setRecoverable] = useState<boolean | undefined>();

const shakeShield = useAnimateOnce(isRecoverable);
const recoverableToolTipTxt = useIsRecoverableTooltipText(address, isRecoverable);
const hasProxy = proxies ? !!proxies.length : undefined;
const proxyTooltipTxt = useHasProxyTooltipText(address, hasProxy);

useEffect((): void => {
api?.query?.['recovery']?.['recoverable'](formatted)
.then((r: any) => setRecoverable(!!r.isSome)).catch(console.error);
}, [api, formatted]);

const openManageProxy = useCallback(() => {
address && chain && PROXY_CHAINS.includes(chain.genesisHash ?? '') && onAction(`/manageProxies/${address}`);
Expand All @@ -50,7 +55,7 @@ export default function AccountIcons ({ chain, formatted, identiconTheme, isSubI
}, [address]);

return (
<Grid container direction='column' sx={{ width: '17%', ml: '8px' }}>
<Grid container direction='column' sx={{ ml: '8px', width: '17%' }}>
<Grid item m='auto' width='fit-content'>
<Identicon
iconTheme={identiconTheme}
Expand All @@ -63,12 +68,13 @@ export default function AccountIcons ({ chain, formatted, identiconTheme, isSubI
</Grid>
<Grid container direction='row' item justifyContent='center'>
<Grid item>
<Infotip placement='bottom-start' text={t('Is recoverable')}>
<Infotip placement='bottom-start' text={recoverableToolTipTxt}>
<IconButton
onClick={openSocialRecovery}
sx={{ height: '15px', width: '15px' }}>
sx={{ height: '15px', width: '15px' }}
>
<FontAwesomeIcon
color={recoverable ? theme.palette.success.main : theme.palette.action.disabledBackground}
color={isRecoverable ? theme.palette.success.main : theme.palette.action.disabledBackground}
fontSize='13px'
icon={faShieldHalved}
shake={shakeShield}
Expand All @@ -77,7 +83,7 @@ export default function AccountIcons ({ chain, formatted, identiconTheme, isSubI
</Infotip>
</Grid>
<Grid item>
<Infotip placement='bottom-end' text={t('Has proxy')}>
<Infotip placement='bottom-end' text={proxyTooltipTxt}>
<IconButton onClick={openManageProxy} sx={{ height: '15px', width: '15px' }}>
<FontAwesomeIcon
color={proxies?.length ? theme.palette.success.main : theme.palette.action.disabledBackground}
Expand All @@ -92,3 +98,5 @@ export default function AccountIcons ({ chain, formatted, identiconTheme, isSubI
</Grid>
);
}

export default React.memo(AccountIcons);
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import type { Proxy } from '../../../util/types';
import { faChain, faCheckCircle, faCircleInfo, faShieldHalved, faSitemap } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Grid, IconButton, useTheme } from '@mui/material';
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import React, { useCallback, useContext, useEffect, useState } from 'react';

import { ActionContext, Infotip } from '../../../components';
import { useAnimateOnce, useInfo, useTranslation } from '../../../hooks';
import { useAnimateOnce, useHasIdentityTooltipText, useHasProxyTooltipText, useInfo, useIsRecoverableTooltipText } from '../../../hooks';
import { windowOpen } from '../../../messaging';
import { IDENTITY_CHAINS, PROXY_CHAINS, SOCIAL_RECOVERY_CHAINS } from '../../../util/constants';

Expand All @@ -24,8 +24,7 @@ interface AddressDetailsProps {
accountInfo: DeriveAccountInfo | undefined | null
}

function AccountIconsFs ({ accountInfo, address }: AddressDetailsProps): React.ReactElement {
const { t } = useTranslation();
function AccountIconsFs({ accountInfo, address }: AddressDetailsProps): React.ReactElement {
const theme = useTheme();

const onAction = useContext(ActionContext);
Expand All @@ -39,57 +38,16 @@ function AccountIconsFs ({ accountInfo, address }: AddressDetailsProps): React.R
const shakeIdentity = useAnimateOnce(hasID);
const shakeShield = useAnimateOnce(isRecoverable);

const identityToolTipTxt = useMemo(() => {
if (!chain) {
return 'Account is in Any Chain mode';
}

switch (hasID) {
case true:
return 'Has Identity';
case false:
return 'No Identity';
default:
return 'Checking';
}
}, [chain, hasID]);

const recoverableToolTipTxt = useMemo(() => {
if (!chain) {
return 'Account is in Any Chain mode';
}

switch (isRecoverable) {
case true:
return 'Recoverable';
case false:
return 'Not Recoverable';
default:
return 'Checking';
}
}, [chain, isRecoverable]);

const proxyTooltipTxt = useMemo(() => {
if (!chain) {
return 'Account is in Any Chain mode';
}

switch (hasProxy) {
case true:
return 'Has Proxy';
case false:
return 'No Proxy';
default:
return 'Checking';
}
}, [chain, hasProxy]);
const identityToolTipTxt = useHasIdentityTooltipText(address, hasID);
const recoverableToolTipTxt = useIsRecoverableTooltipText(address, isRecoverable);
const proxyTooltipTxt = useHasProxyTooltipText(address, hasProxy);

useEffect((): void => {
setHasID(undefined);
setIsRecoverable(undefined);
setHasProxy(undefined);

if (!api || !address || !account?.genesisHash || api.genesisHash.toHex() !== account.genesisHash) {
if (!api || !formatted || !account?.genesisHash || api.genesisHash.toHex() !== account.genesisHash) {
return;
}

Expand Down Expand Up @@ -119,7 +77,7 @@ function AccountIconsFs ({ accountInfo, address }: AddressDetailsProps): React.R
} else {
setHasProxy(false);
}
}, [api, address, formatted, account?.genesisHash, accountInfo]);
}, [api, formatted, account?.genesisHash, accountInfo]);

const openIdentity = useCallback(() => {
address && chain && windowOpen(`/manageIdentity/${address}`).catch(console.error);
Expand All @@ -136,7 +94,7 @@ function AccountIconsFs ({ accountInfo, address }: AddressDetailsProps): React.R
return (
<Grid alignItems='center' container direction='column' display='grid' height='72px' item justifyContent='center' justifyItems='center' width='fit-content'>
<Grid item onClick={openIdentity} sx={{ cursor: 'pointer', height: '24px', m: 'auto', p: '2px', width: 'fit-content' }}>
<Infotip placement='right' text={t(identityToolTipTxt)}>
<Infotip placement='right' text={identityToolTipTxt}>
{hasID
? accountInfo?.identity?.displayParent
? <FontAwesomeIcon
Expand All @@ -157,7 +115,7 @@ function AccountIconsFs ({ accountInfo, address }: AddressDetailsProps): React.R
</Infotip>
</Grid>
<Grid height='24px' item my='1px' width='24px'>
<Infotip placement='right' text={t(recoverableToolTipTxt)}>
<Infotip placement='right' text={recoverableToolTipTxt}>
<IconButton
onClick={openSocialRecovery}
sx={{ height: '24px', width: '24px' }}
Expand All @@ -171,7 +129,7 @@ function AccountIconsFs ({ accountInfo, address }: AddressDetailsProps): React.R
</Infotip>
</Grid>
<Grid height='24px' item width='fit-content'>
<Infotip placement='right' text={t(proxyTooltipTxt)}>
<Infotip placement='right' text={proxyTooltipTxt}>
<IconButton onClick={openManageProxy} sx={{ height: '16px', width: '16px' }}>
<FontAwesomeIcon
icon={faSitemap}
Expand Down
3 changes: 3 additions & 0 deletions packages/extension-polkagate/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ export { useGenericLedger } from './useGenericLedger';
export { default as useGenesisHash } from './useGenesisHash';
export { default as useGenesisHashOptions } from './useGenesisHashOptions';
export { default as useHasDelegated } from './useHasDelegated';
export { default as useHasIdentityTooltipText } from './useHasIdentityTooltipText';
export { default as useHasProxyTooltipText } from './useHasProxyTooltipText';
export { default as useIdentity } from './useIdentity';
export { default as useInfo } from './useInfo';
export { default as useIsExposed } from './useIsExposed';
export { default as useIsExtensionPopup } from './useIsExtensionPopup';
export { default as useIsLoginEnabled } from './useIsLoginEnabled';
export { default as useIsMounted } from './useIsMounted';
export { default as useIsRecoverableTooltipText } from './useIsRecoverableTooltipText';
export { default as useIsTestnetEnabled } from './useIsTestnetEnabled';
export { default as useIsValidator } from './useIsValidator';
export { useLedger } from './useLedger';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { useMemo } from 'react';

import { useChain, useTranslation } from '.';

export default function useHasIdentityTooltipText (address: string | undefined, hasID: boolean | undefined): string {
const { t } = useTranslation();

const chain = useChain(address);
const anyChinModeText = t('Account is in Any Chain mode');

return useMemo(() => {
if (!chain) {
return anyChinModeText;
}

switch (hasID) {
case true:
return t('Has identity');
case false:
return t('No identity');
default:
return t('Checking');
}
}, [anyChinModeText, chain, hasID, t]);
}
28 changes: 28 additions & 0 deletions packages/extension-polkagate/src/hooks/useHasProxyTooltipText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { useMemo } from 'react';

import { useChain, useTranslation } from '.';

export default function useHasProxyTooltipText (address: string | undefined, hasProxy: boolean | undefined): string {
const { t } = useTranslation();

const chain = useChain(address);
const anyChinModeText = t('Account is in Any Chain mode');

return useMemo(() => {
if (!chain) {
return anyChinModeText;
}

switch (hasProxy) {
case true:
return t('Has proxy');
case false:
return t('No proxy');
default:
return t('Checking');
}
}, [anyChinModeText, chain, hasProxy, t]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { useMemo } from 'react';

import { useChain, useTranslation } from '.';

export default function useIsRecoverableTooltipText (address: string | undefined, isRecoverable: boolean | undefined): string {
const { t } = useTranslation();

const chain = useChain(address);
const anyChinModeText = t('Account is in Any Chain mode');

return useMemo(() => {
if (!chain) {
return anyChinModeText;
}

switch (isRecoverable) {
case true:
return t('Recoverable');
case false:
return t('Not recoverable');
default:
return t('Checking');
}
}, [anyChinModeText, chain, isRecoverable, t]);
}
17 changes: 3 additions & 14 deletions packages/extension-polkagate/src/popup/home/AccountPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
import { ActionContext } from '../../components';
import AccountFeatures from '../../components/AccountFeatures';
import AccountIcons from '../../components/AccountIcons';
import { useInfo, useMyAccountIdentity, useProxies } from '../../hooks';
import { useInfo, useMyAccountIdentity } from '../../hooks';
import useIsExtensionPopup from '../../hooks/useIsExtensionPopup';
import { showAccount } from '../../messaging';
import { AccountMenu } from '../../partials';
Expand All @@ -22,7 +22,6 @@ import AccountDetail from './AccountDetail';
export interface Props {
actions?: React.ReactNode;
address: string;
// children?: React.ReactNode;
isExternal?: boolean | null;
isHardware?: boolean | null;
isHidden?: boolean;
Expand All @@ -38,21 +37,14 @@ export interface Props {

export default function AccountPreview ({ address, hideNumbers, isHidden, name, quickActionOpen, setQuickActionOpen, toggleActions, type }: Props): React.ReactElement<Props> {
const onExtension = useIsExtensionPopup();
const { api, chain, formatted } = useInfo(address);
const { chain, formatted } = useInfo(address);
const onAction = useContext(ActionContext);
const proxies = useProxies(api, formatted);
const identity = useMyAccountIdentity(address);

const [showAccountMenu, setShowAccountMenu] = useState(false);
const [recoverable, setRecoverable] = useState<boolean | undefined>();

const _judgement = identity && JSON.stringify(identity.judgements).match(/reasonable|knownGood/gi);

useEffect((): void => {
api?.query?.['recovery']?.['recoverable'](formatted)
.then((r: any) => setRecoverable(!!r.isSome)).catch(console.error);
}, [api, formatted]);

useEffect((): void => {
setShowAccountMenu(false);
}, [toggleActions]);
Expand Down Expand Up @@ -83,14 +75,11 @@ export default function AccountPreview ({ address, hideNumbers, isHidden, name,
return (
<Grid alignItems='center' container overflow='hidden' p='15px 0 13px' position='relative'>
<AccountIcons
chain={chain}
formatted={formatted || address}
address={address}
identiconTheme={identiconTheme}
isSubId={!!identity?.displayParent}
judgements={_judgement}
prefix={chain?.ss58Format ?? 42}
proxies={proxies}
recoverable={recoverable}
/>
<AccountDetail
address={address}
Expand Down

0 comments on commit 23616a4

Please sign in to comment.