Skip to content

refactor: put reused codes into 2 components #1614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions packages/extension-polkagate/src/components/ShortAddress2.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0
// @ts-nocheck

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

import type { AccountId } from '@polkadot/types/interfaces/runtime';

import { Grid, type SxProps, type Theme } from '@mui/material';
import React, { useCallback, useEffect, useRef, useState } from 'react';

import type { AccountId } from '@polkadot/types/interfaces/runtime';

import { SHORT_ADDRESS_CHARACTERS } from '../util/constants';
import CopyAddressButton from './CopyAddressButton';

Expand All @@ -21,7 +20,7 @@ interface Props {
clipped?: boolean;
}

function ShortAddress2({ address, clipped = false, charsCount = SHORT_ADDRESS_CHARACTERS, style, showCopy = false, inParentheses = false }: Props): React.ReactElement {
function ShortAddress2 ({ address, charsCount = SHORT_ADDRESS_CHARACTERS, clipped = false, inParentheses = false, showCopy = false, style }: Props): React.ReactElement {
const [charactersCount, setCharactersCount] = useState<number>(charsCount);
const pRef = useRef<HTMLDivElement>(null);
const cRef = useRef<HTMLDivElement>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ import type { HexString } from '@polkadot/util/types';
import type { FetchedBalance } from '../../../hooks/useAssetsBalances';
import type { BalancesInfo, Prices } from '../../../util/types';

import { Divider, Grid, IconButton, Skeleton, Typography, useTheme } from '@mui/material';
import { Divider, Grid, Skeleton, Typography, useTheme } from '@mui/material';
import React, { useCallback, useEffect, useMemo } from 'react';

import { AssetLogo, FormatBalance2, FormatPrice, Identicon, Identity, Infotip, Infotip2, OptionalCopyButton, ShortAddress2, VaadinIcon } from '../../../components';
import { useIdentity, useInfo, useTranslation } from '../../../hooks';
import { showAccount, tieAccount } from '../../../messaging';
import { AssetLogo, FormatBalance2, FormatPrice, Infotip, Infotip2 } from '../../../components';
import { useInfo, useTranslation } from '../../../hooks';
import { tieAccount } from '../../../messaging';
import { getValue } from '../../../popup/account/util';
import { BALANCES_VALIDITY_PERIOD } from '../../../util/constants';
import getLogo2 from '../../../util/getLogo2';
import { amountToHuman } from '../../../util/utils';
import AccountIconsFs from './AccountIconsFs';
import AccountBodyFs from '../../homeFullScreen/partials/AccountBodyFs';
import AccountIdenticonIconsFS from '../../homeFullScreen/partials/AccountIdenticonIconsFS';
import AOC from './AOC';

interface PriceJSXType {
Expand Down Expand Up @@ -147,24 +148,10 @@ interface AddressDetailsProps {
setAssetIdOnAssetHub: React.Dispatch<React.SetStateAction<number | string | undefined>>;
}

export const EyeIconFullScreen = ({ isHidden, onClick }: { isHidden: boolean | undefined, onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined }) => {
const { t } = useTranslation();
const theme = useTheme();

return (
<Infotip text={isHidden ? t('This account is hidden from websites') : t('This account is visible to websites')}>
<IconButton onClick={onClick} sx={{ height: '20px', ml: '7px', mt: '13px', p: 0, width: '28px' }}>
<VaadinIcon icon={isHidden ? 'vaadin:eye-slash' : 'vaadin:eye'} style={{ color: `${theme.palette.secondary.light}`, height: '20px' }} />
</IconButton>
</Infotip>
);
};

function AccountInformationForDetails ({ accountAssets, address, label, price, pricesInCurrency, selectedAsset, setAssetIdOnAssetHub, setSelectedAsset }: AddressDetailsProps): React.ReactElement {
const theme = useTheme();
const { account, api, chain, formatted, genesisHash, token } = useInfo(address);
const { account, chain, genesisHash, token } = useInfo(address);

const accountInfo = useIdentity(genesisHash, formatted);

const calculatePrice = useCallback((amount: BN, decimal: number, _price: number) => {
return parseFloat(amountToHuman(amount, decimal)) * _price;
Expand Down Expand Up @@ -210,56 +197,17 @@ function AccountInformationForDetails ({ accountAssets, address, label, price, p
}).catch(console.error);
}, [address, setSelectedAsset, setAssetIdOnAssetHub]);

const toggleVisibility = useCallback((): void => {
address && showAccount(address, account?.isHidden || false).catch(console.error);
}, [account?.isHidden, address]);

return (
<Grid alignItems='center' container item sx={{ bgcolor: 'background.paper', border: '0px solid', borderBottomWidth: '8px', borderBottomColor: theme.palette.mode === 'light' ? 'black' : 'secondary.light', borderRadius: '5px', boxShadow: '2px 3px 4px 0px rgba(0, 0, 0, 0.1)', mb: '15px', p: `20px 20px ${showAOC ? '5px' : '20px'} 20px`, position: 'relative' }}>
{label}
<Grid container item>
<Grid container item sx={{ borderRight: '1px solid', borderRightColor: 'divider', pr: '8px', width: 'fit-content' }}>
<Grid container item pr='7px' sx={{ '> div': { height: 'fit-content' }, m: 'auto', width: 'fit-content' }}>
<Identicon
iconTheme={chain?.icon ?? 'polkadot'}
prefix={chain?.ss58Format ?? 42}
size={70}
value={formatted || address}
/>
</Grid>
<AccountIconsFs
accountInfo={accountInfo}
<AccountIdenticonIconsFS
address={address}
/>
<Grid container item sx={{ display: 'grid', gridTemplateColumns: 'minmax(150px, 60%) max-content' }} xs>
<AccountBodyFs
address={address}
/>
</Grid>
<Grid container item sx={{ display: 'grid', gridTemplateColumns: 'minmax(150px, 60%) max-content' }} xs>
<Grid container direction='column' item sx={{ borderRight: '1px solid', borderRightColor: 'divider', px: '7px' }}>
<Grid container item justifyContent='space-between'>
<Identity
accountInfo={accountInfo}
address={address}
api={api}
chain={chain}
noIdenticon
style={{ width: 'calc(100% - 40px)' }}
// subIdOnly
/>
<Grid item width='40px'>
<EyeIconFullScreen
isHidden={account?.isHidden}
onClick={toggleVisibility}
/>
</Grid>
</Grid>
<Grid alignItems='center' container item>
<Grid container item sx={{ '> div div:last-child': { width: 'auto' } }} xs>
<ShortAddress2 address={formatted || address} clipped style={{ fontSize: '10px', fontWeight: 300 }} />
</Grid>
<Grid container item width='fit-content'>
<OptionalCopyButton address={address} />
</Grid>
</Grid>
</Grid>
<SelectedAssetBox
balanceToShow={selectedAsset as unknown as BalancesInfo}
genesisHash={chain === null ? null : genesisHash}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0

/* eslint-disable react/jsx-first-prop-new-line */
/* eslint-disable react/jsx-max-props-per-line */

import { Grid, IconButton, useTheme } from '@mui/material';
import React, { useCallback } from 'react';

import { noop } from '@polkadot/util';

import { Identity, Infotip, OptionalCopyButton, ShortAddress2, VaadinIcon } from '../../../components';
import { useIdentity, useInfo, useTranslation } from '../../../hooks';
import { showAccount } from '../../../messaging';

export const EyeIconFullScreen = ({ isHidden, onClick }: { isHidden: boolean | undefined, onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined }) => {
const { t } = useTranslation();
const theme = useTheme();

return (
<Infotip text={isHidden ? t('This account is hidden from websites') : t('This account is visible to websites')}>
<IconButton onClick={onClick} sx={{ height: '20px', ml: '7px', mt: '13px', p: 0, width: '28px' }}>
<VaadinIcon icon={isHidden ? 'vaadin:eye-slash' : 'vaadin:eye'} style={{ color: `${theme.palette.secondary.light}`, height: '20px' }} />
</IconButton>
</Infotip>
);
};

interface Props {
address: string | undefined;
goToDetails?: () => void;
gridSize?: number;
}

function AccountBodyFs ({ address, goToDetails = noop, gridSize }: Props): React.ReactElement {
const { account, api, chain, formatted, genesisHash } = useInfo(address);

const accountInfo = useIdentity(genesisHash, formatted);

const toggleVisibility = useCallback((): void => {
address && showAccount(address, account?.isHidden || false).catch(console.error);
}, [account?.isHidden, address]);

return (
<Grid container direction='column' item sx={{ borderRight: '1px solid', borderRightColor: 'divider', px: '7px' }} xs={gridSize}>
<Grid container item justifyContent='space-between'>
<Identity
accountInfo={accountInfo}
address={address}
api={api}
chain={chain}
noIdenticon
onClick={goToDetails}
style={{ width: 'calc(100% - 40px)' }}
subIdOnly
/>
<Grid item width='40px'>
<EyeIconFullScreen
isHidden={account?.isHidden}
onClick={toggleVisibility}
/>
</Grid>
</Grid>
<Grid alignItems='center' container item>
<Grid container item sx={{ '> div div:last-child': { width: 'auto' } }} xs>
<ShortAddress2 address={formatted || address} charsCount={40} style={{ fontSize: '10px', fontWeight: 300 }} />
</Grid>
<Grid container item width='fit-content'>
<OptionalCopyButton address={address} />
</Grid>
</Grid>
</Grid>
);
}

export default React.memo(AccountBodyFs);
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
// SPDX-License-Identifier: Apache-2.0

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

import { Grid } from '@mui/material';
import React from 'react';

import { Identicon } from '../../../components';
import { useIdentity, useInfo } from '../../../hooks';
import AccountIconsFs from '../../accountDetails/components/AccountIconsFs';

interface Props {
address: string | undefined;
}
Comment on lines +13 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider making the address prop required and more strictly typed.

Since this component is meant to display account information, the address should probably be required. Also, consider using a more specific type for the address string (e.g., a type that ensures it's a valid substrate address).

 interface Props {
-  address: string | undefined;
+  address: string;
 }

Committable suggestion was skipped due to low confidence.


function AccountIdenticonIconsFS ({ address }: Props): React.ReactElement {
const { chain, formatted, genesisHash } = useInfo(address);

const accountInfo = useIdentity(genesisHash, formatted);

return (
<Grid container item sx={{ borderRight: '1px solid', borderRightColor: 'divider', pr: '8px', width: 'fit-content' }}>
<Grid container item pr='7px' sx={{ '> div': { height: 'fit-content' }, m: 'auto', width: 'fit-content' }}>
<Identicon
iconTheme={chain?.icon ?? 'polkadot'}
prefix={chain?.ss58Format ?? 42}
size={55}
value={formatted || address}
/>
</Grid>
<AccountIconsFs
accountInfo={accountInfo}
address={address}
/>
</Grid>
);
}

export default React.memo(AccountIdenticonIconsFS);
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ import React, { useCallback, useContext, useMemo, useState } from 'react';
import { getValue } from '@polkadot/extension-polkagate/src/popup/account/util';

import { stars6Black, stars6White } from '../../../assets/icons';
import { ActionContext, Identicon, Identity, OptionalCopyButton, ShortAddress2 } from '../../../components';
import { ActionContext } from '../../../components';
import FormatPrice from '../../../components/FormatPrice';
import { useCurrency, useIdentity, useInfo, usePrices, useTranslation } from '../../../hooks';
import { showAccount, tieAccount } from '../../../messaging';
import { useAccount, useCurrency, usePrices, useTranslation } from '../../../hooks';
import { tieAccount } from '../../../messaging';
import { amountToHuman } from '../../../util/utils';
import AccountIconsFs from '../../accountDetails/components/AccountIconsFs';
import { EyeIconFullScreen } from '../../accountDetails/components/AccountInformationForDetails';
import AOC from '../../accountDetails/components/AOC';
import { openOrFocusTab } from '../../accountDetails/components/CommonTasks';
import DeriveAccountModal from '../../partials/DeriveAccountModal';
import ExportAccountModal from '../../partials/ExportAccountModal';
import ForgetAccountModal from '../../partials/ForgetAccountModal';
import RenameModal from '../../partials/RenameAccountModal';
import AccountBodyFs from './AccountBodyFs';
import AccountIdenticonIconsFS from './AccountIdenticonIconsFS';
import FullScreenAccountMenu from './FullScreenAccountMenu';

interface AddressDetailsProps {
Expand Down Expand Up @@ -96,11 +96,9 @@ function AccountInformationForHome ({ accountAssets, address, hideNumbers, isChi
const theme = useTheme();
const pricesInCurrencies = usePrices();
const currency = useCurrency();
const { account, api, chain, formatted, genesisHash } = useInfo(address);
const account = useAccount(address);
const onAction = useContext(ActionContext);

const accountInfo = useIdentity(genesisHash, formatted);

const [displayPopup, setDisplayPopup] = useState<number>();

const calculatePrice = useCallback((amount: BN, decimal: number, price: number) => parseFloat(amountToHuman(amount, decimal)) * price, []);
Expand Down Expand Up @@ -135,10 +133,6 @@ function AccountInformationForHome ({ accountAssets, address, hideNumbers, isChi
}).catch(console.error);
}, [address, setSelectedAsset]);

const toggleVisibility = useCallback((): void => {
address && showAccount(address, account?.isHidden || false).catch(console.error);
}, [account?.isHidden, address]);

const openSettings = useCallback((): void => {
address && onAction();
}, [onAction, address]);
Expand All @@ -151,48 +145,14 @@ function AccountInformationForHome ({ accountAssets, address, hideNumbers, isChi
<>
<Grid alignItems='center' container item sx={{ bgcolor: 'background.paper', border: isChild ? '0.1px dashed' : 'none', borderColor: 'secondary.main', borderRadius: '5px', p: '20px 10px 15px 30px' }}>
<Grid container item>
<Grid container item sx={{ borderRight: '1px solid', borderRightColor: 'divider', pr: '8px', width: 'fit-content' }}>
<Grid container item pr='7px' sx={{ '> div': { height: 'fit-content' }, m: 'auto', width: 'fit-content' }}>
<Identicon
iconTheme={chain?.icon ?? 'polkadot'}
prefix={chain?.ss58Format ?? 42}
size={70}
value={formatted || address}
/>
</Grid>
<AccountIconsFs
accountInfo={accountInfo}
address={address}
/>
</Grid>
<Grid container direction='column' item sx={{ borderRight: '1px solid', borderRightColor: 'divider', px: '7px' }} xs={5.6}>
<Grid container item justifyContent='space-between'>
<Identity
accountInfo={accountInfo}
address={address}
api={api}
chain={chain}
noIdenticon
onClick={goToDetails}
style={{ width: 'calc(100% - 40px)' }}
subIdOnly
/>
<Grid item width='40px'>
<EyeIconFullScreen
isHidden={account?.isHidden}
onClick={toggleVisibility}
/>
</Grid>
</Grid>
<Grid alignItems='center' container item>
<Grid container item sx={{ '> div div:last-child': { width: 'auto' } }} xs>
<ShortAddress2 address={formatted || address} charsCount={40} style={{ fontSize: '10px', fontWeight: 300 }} />
</Grid>
<Grid container item width='fit-content'>
<OptionalCopyButton address={address} />
</Grid>
</Grid>
</Grid>
<AccountIdenticonIconsFS
address={address}
/>
<AccountBodyFs
address={address}
goToDetails={goToDetails}
gridSize={5.6}
/>
<AccountTotal
hideNumbers={hideNumbers}
totalBalance={totalBalance}
Expand Down
Loading