Skip to content
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

feat: optimized connect-button code #481

Merged
merged 10 commits into from
Jan 12, 2024
5 changes: 5 additions & 0 deletions .changeset/thick-singers-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ant-design/web3': patch
---

优化组件代码
shanchuan1 marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 1 addition & 9 deletions packages/web3/src/connect-button/chain-select.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import React, { useContext } from 'react';
import { DownOutlined } from '@ant-design/icons';
import type { Chain } from '@ant-design/web3-common';
import { Button, ConfigProvider, Dropdown, Space } from 'antd';
import classNames from 'classnames';

export interface ChainSelectProps {
className?: string;
hashId: string;
chains: Chain[];
onSwitchChain?: (chain: Chain) => void;
currentChain?: Chain;
style?: React.CSSProperties;
}
import type { ChainSelectProps } from './interface';

export const ChainSelect: React.FC<ChainSelectProps> = ({
className,
Expand Down
118 changes: 57 additions & 61 deletions packages/web3/src/connect-button/connect-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import { CryptoPrice } from '../crypto-price';
import useIntl from '../hooks/useIntl';
import { fillWith0x, writeCopyText } from '../utils';
import { ChainSelect } from './chain-select';
import type { ConnectButtonProps, ConnectButtonTooltipProps } from './interface';
import type {
Chain,
ChainSelectProps,
ConnectButtonProps,
ConnectButtonTooltipProps,
IntlType,
ProfileModalProps,
} from './interface';
import { ProfileModal } from './profile-modal';
import { useStyle } from './style';
import { ConnectButtonTooltip } from './tooltip';
Expand Down Expand Up @@ -73,21 +80,39 @@ export const ConnectButton: React.FC<ConnectButtonProps> = (props) => {
...restProps,
};

const renderChainSelect = () => {
if (availableChains && availableChains.length > 1) {
return (
<ChainSelect
hashId={hashId}
onSwitchChain={onSwitchChain}
currentChain={chain}
chains={availableChains}
/>
);
}
return null;
const chainProps: ChainSelectProps = {
hashId,
onSwitchChain,
currentChain: chain,
chains: availableChains as Chain[],
};

const chainSelect = renderChainSelect();
const profileModalProps: ProfileModalProps = {
intl,
open: profileOpen,
__hashId__: hashId,
onDisconnect: () => {
setProfileOpen(false);
onDisconnectClick?.();
},
onClose: () => {
setProfileOpen(false);
},
address: account?.address,
name: account?.name,
avatar: avatar ?? {
icon: chain?.icon ? (
<div className={`${prefixCls}-chain-icon`}>{chain?.icon}</div>
) : (
<UserOutlined className={`${prefixCls}-default-icon`} />
),
},
balance,
modalProps: typeof profileModal === 'object' ? profileModal : undefined,
};

const chainSelect =
(availableChains && availableChains.length > 1 && <ChainSelect {...chainProps} />) || null;
shanchuan1 marked this conversation as resolved.
Show resolved Hide resolved

const buttonInnerText = (
<div className={`${prefixCls}-content`}>
Expand All @@ -114,36 +139,6 @@ export const ConnectButton: React.FC<ConnectButtonProps> = (props) => {
<Button {...buttonProps}>{buttonInnerText}</Button>
);

const profileModalContent = (
<ProfileModal
intl={intl}
open={profileOpen}
__hashId__={hashId}
onDisconnect={() => {
setProfileOpen(false);
onDisconnectClick?.();
}}
onClose={() => {
setProfileOpen(false);
}}
address={account?.address}
name={account?.name}
avatar={
avatar ?? {
icon: chain?.icon ? (
<div className={`${prefixCls}-chain-icon`}>{chain?.icon}</div>
) : (
<UserOutlined className={`${prefixCls}-default-icon`} />
),
}
}
balance={balance}
modalProps={typeof profileModal === 'object' ? profileModal : undefined}
/>
);

let content = buttonContent;

const defaultMenuItems: MenuItemType[] = useMemo(
() => [
{
Expand Down Expand Up @@ -194,8 +189,8 @@ export const ConnectButton: React.FC<ConnectButtonProps> = (props) => {
return combinedItems;
}, [actionsMenu, defaultMenuItems, account]);

if (mergedMenuItems.length > 0) {
content = (
const content =
mergedMenuItems.length > 0 ? (
<Dropdown
open={showMenu}
onOpenChange={setShowMenu}
Expand All @@ -206,35 +201,36 @@ export const ConnectButton: React.FC<ConnectButtonProps> = (props) => {
>
{buttonContent}
</Dropdown>
) : (
buttonContent
);
}

const mergedTooltipCopyable: ConnectButtonTooltipProps['copyable'] =
typeof tooltip === 'object' ? tooltip.copyable !== false : !!tooltip;

let tooltipTitle: string = tooltip && account?.address ? fillWith0x(account?.address) : '';
if (typeof tooltip === 'object' && typeof tooltip.title === 'string') {
tooltipTitle = tooltip.title;
}
const ConnectButtonTooltipProps: () => ConnectButtonTooltipProps & { intl: IntlType } = () => {
shanchuan1 marked this conversation as resolved.
Show resolved Hide resolved
const mergedTooltipCopyable: ConnectButtonTooltipProps['copyable'] =
typeof tooltip === 'object' ? tooltip.copyable !== false : !!tooltip;
return {
intl,
copyable: mergedTooltipCopyable,
title: tooltipTitle,
prefixCls,
__hashId__: hashId,
...(typeof tooltip === 'object' ? tooltip : {}),
};
};

const main = (
<>
{contextHolder}
{tooltipTitle ? (
<ConnectButtonTooltip
intl={intl}
copyable={mergedTooltipCopyable}
title={tooltipTitle}
prefixCls={prefixCls}
__hashId__={hashId}
{...(typeof tooltip === 'object' ? tooltip : {})}
>
{content}
</ConnectButtonTooltip>
<ConnectButtonTooltip {...ConnectButtonTooltipProps()}>{content}</ConnectButtonTooltip>
) : (
content
)}
{profileModalContent}
<ProfileModal {...profileModalProps} />
</>
);

Expand Down
37 changes: 33 additions & 4 deletions packages/web3/src/connect-button/interface.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { ConnectorTriggerProps, Locale } from '@ant-design/web3-common';
import type { AvatarProps, ButtonProps, MenuProps, TooltipProps } from 'antd';
import type { Balance, Chain, ConnectorTriggerProps, Locale } from '@ant-design/web3-common';
import type { AvatarProps, ButtonProps, MenuProps, ModalProps, TooltipProps } from 'antd';
import type { MenuItemType } from 'antd/es/menu/hooks/useItems';

import type { AddressProps } from '../address';
import type { ProfileModalProps } from './profile-modal';
import type { IntlType } from '../hooks/useIntl';
shanchuan1 marked this conversation as resolved.
Show resolved Hide resolved

export type ConnectButtonTooltipProps = TooltipProps & {
__hashId__?: string;
Expand Down Expand Up @@ -33,5 +33,34 @@ export type ConnectButtonProps = ButtonProps &
extraItems?: MenuItemType[];
};
};
export interface ChainSelectProps {
className?: string;
shanchuan1 marked this conversation as resolved.
Show resolved Hide resolved
hashId: string;
chains: Chain[];
onSwitchChain?: (chain: Chain) => void;
currentChain?: Chain;
style?: React.CSSProperties;
}

export { ConnectorTriggerProps };
export interface ProfileModalProps {
className?: string;
intl: IntlType;
/** @internal */
__hashId__: string;
avatar?: AvatarProps;
address?: string;
name?: string;
onDisconnect?: () => void;
open?: boolean;
onClose?: () => void;
modalProps?: Omit<ModalProps, 'open' | 'onClose' | 'className'>;
balance?: Balance;
isShow?: boolean;
}

export interface chainType {
id?: number;
name?: string;
icon?: string | React.ReactNode;
}
export { ConnectorTriggerProps, Chain, IntlType };
55 changes: 20 additions & 35 deletions packages/web3/src/connect-button/profile-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,11 @@
import React, { useContext } from 'react';
import { Address } from '@ant-design/web3';
import type { Balance } from '@ant-design/web3-common';
import { Avatar, Button, ConfigProvider, message, Modal, Space, type AvatarProps } from 'antd';
import type { ModalProps } from 'antd';
import { Avatar, Button, ConfigProvider, message, Modal, Space } from 'antd';
import classNames from 'classnames';

import { CryptoPrice } from '../crypto-price';
import type { IntlType } from '../hooks/useIntl';
import { writeCopyText } from '../utils';

export interface ProfileModalProps {
className?: string;
intl: IntlType;
/** @internal */
__hashId__: string;
avatar?: AvatarProps;
address?: string;
name?: string;
onDisconnect?: () => void;
open?: boolean;
onClose?: () => void;
modalProps?: Omit<ModalProps, 'open' | 'onClose' | 'className'>;
balance?: Balance;
}
import type { ProfileModalProps } from './interface';

export const ProfileModal: React.FC<ProfileModalProps> = ({
className,
Expand All @@ -41,26 +24,28 @@ export const ProfileModal: React.FC<ProfileModalProps> = ({
const prefixCls = getPrefixCls('web3-connect-button-profile-modal');
const [messageApi, contextHolder] = message.useMessage();

const footer = (
<div className={classNames(`${prefixCls}-footer`, __hashId__)}>
{address ? (
<Button
onClick={() => {
writeCopyText(address).then(() => {
messageApi.success(intl.getMessage(intl.messages.addressCopied));
});
}}
>
{intl.getMessage(intl.messages.copyAddress)}
</Button>
) : null}
<Button onClick={onDisconnect}>{intl.getMessage(intl.messages.disconnect)}</Button>
</div>
);

return (
<>
{contextHolder}
<Modal
footer={
<div className={classNames(`${prefixCls}-footer`, __hashId__)}>
{address ? (
<Button
onClick={() => {
writeCopyText(address).then(() => {
messageApi.success(intl.getMessage(intl.messages.addressCopied));
});
}}
>
{intl.getMessage(intl.messages.copyAddress)}
</Button>
) : null}
<Button onClick={onDisconnect}>{intl.getMessage(intl.messages.disconnect)}</Button>
</div>
}
footer={footer}
width={280}
{...modalProps}
onCancel={onClose}
Expand Down
Loading