From 3557e6382f983ad134084a83b6fea266889098c5 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Mon, 14 Oct 2024 14:29:42 +0200 Subject: [PATCH] feat: Add Snap UI avatar component --- .../safe-component-list.js | 2 + .../snaps/snap-ui-address/snap-ui-address.tsx | 36 ++++++--------- .../app/snaps/snap-ui-avatar/index.ts | 1 + .../snaps/snap-ui-avatar/snap-ui-avatar.tsx | 44 +++++++++++++++++++ .../snap-ui-renderer/components/address.ts | 2 +- .../snap-ui-renderer/components/avatar.ts | 9 ++++ .../snap-ui-renderer/components/index.ts | 2 + 7 files changed, 72 insertions(+), 24 deletions(-) create mode 100644 ui/components/app/snaps/snap-ui-avatar/index.ts create mode 100644 ui/components/app/snaps/snap-ui-avatar/snap-ui-avatar.tsx create mode 100644 ui/components/app/snaps/snap-ui-renderer/components/avatar.ts diff --git a/ui/components/app/metamask-template-renderer/safe-component-list.js b/ui/components/app/metamask-template-renderer/safe-component-list.js index 14abe8eceea7..a41b92c9f463 100644 --- a/ui/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/components/app/metamask-template-renderer/safe-component-list.js @@ -43,6 +43,7 @@ import { SnapUICheckbox } from '../snaps/snap-ui-checkbox'; import { SnapUITooltip } from '../snaps/snap-ui-tooltip'; import { SnapUICard } from '../snaps/snap-ui-card'; import { SnapUIAddress } from '../snaps/snap-ui-address'; +import { SnapUIAvatar } from '../snaps/snap-ui-avatar'; import { SnapUISelector } from '../snaps/snap-ui-selector'; import { SnapUIFooterButton } from '../snaps/snap-ui-footer-button'; ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) @@ -106,6 +107,7 @@ export const safeComponentList = { SnapUICard, SnapUISelector, SnapUIAddress, + SnapUIAvatar, SnapUIFooterButton, FormTextField, ///: BEGIN:ONLY_INCLUDE_IF(keyring-snaps) diff --git a/ui/components/app/snaps/snap-ui-address/snap-ui-address.tsx b/ui/components/app/snaps/snap-ui-address/snap-ui-address.tsx index 669f7dd30799..c634ac3177dc 100644 --- a/ui/components/app/snaps/snap-ui-address/snap-ui-address.tsx +++ b/ui/components/app/snaps/snap-ui-address/snap-ui-address.tsx @@ -11,32 +11,35 @@ import { Display, TextColor, } from '../../../../helpers/constants/design-system'; -import BlockieIdenticon from '../../../ui/identicon/blockieIdenticon'; -import Jazzicon from '../../../ui/jazzicon'; -import { getUseBlockie } from '../../../../selectors'; import { shortenAddress } from '../../../../helpers/utils/util'; import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { SnapUIAvatar } from '../snap-ui-avatar'; export type SnapUIAddressProps = { // The address must be a CAIP-10 string. address: string; - diameter?: number; + // This is not currently exposed to Snaps. + avatarSize?: string; }; export const SnapUIAddress: React.FunctionComponent = ({ address, - diameter = 32, + avatarSize = 'md', }) => { - const parsed = useMemo(() => { + const caipIdentifier = useMemo(() => { if (isHexString(address)) { // For legacy address inputs we assume them to be Ethereum addresses. // NOTE: This means the chain ID is not gonna be reliable. - return parseCaipAccountId(`eip155:1:${address}`); + return `eip155:1:${address}`; } - return parseCaipAccountId(address as CaipAccountId); + return address; }, [address]); - const useBlockie = useSelector(getUseBlockie); + + const parsed = useMemo( + () => parseCaipAccountId(caipIdentifier as CaipAccountId), + [caipIdentifier], + ); // For EVM addresses, we make sure they are checksummed. const transformedAddress = @@ -47,20 +50,7 @@ export const SnapUIAddress: React.FunctionComponent = ({ return ( - {useBlockie ? ( - - ) : ( - - )} + {shortenedAddress} ); diff --git a/ui/components/app/snaps/snap-ui-avatar/index.ts b/ui/components/app/snaps/snap-ui-avatar/index.ts new file mode 100644 index 000000000000..44fc129d6b39 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-avatar/index.ts @@ -0,0 +1 @@ +export * from './snap-ui-avatar'; diff --git a/ui/components/app/snaps/snap-ui-avatar/snap-ui-avatar.tsx b/ui/components/app/snaps/snap-ui-avatar/snap-ui-avatar.tsx new file mode 100644 index 000000000000..2f6d969a055f --- /dev/null +++ b/ui/components/app/snaps/snap-ui-avatar/snap-ui-avatar.tsx @@ -0,0 +1,44 @@ +import React, { useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import { CaipAccountId, parseCaipAccountId } from '@metamask/utils'; +import BlockieIdenticon from '../../../ui/identicon/blockieIdenticon'; +import Jazzicon from '../../../ui/jazzicon'; +import { getUseBlockie } from '../../../../selectors'; + +export const DIAMETERS: Record = { + 'xs': 16, + 'sm': 24, + 'md': 32, + 'lg': 40, +}; + +export type SnapUIAvatarProps = { + // The address must be a CAIP-10 string. + address: string; + size?: string; +}; + +export const SnapUIAvatar: React.FunctionComponent = ({ + address, + size = 'md', +}) => { + const parsed = useMemo(() => { + return parseCaipAccountId(address as CaipAccountId); + }, [address]); + const useBlockie = useSelector(getUseBlockie); + + return useBlockie ? ( + + ) : ( + + ); +}; diff --git a/ui/components/app/snaps/snap-ui-renderer/components/address.ts b/ui/components/app/snaps/snap-ui-renderer/components/address.ts index 108ff37f33a5..1e39966df760 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/address.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/address.ts @@ -5,6 +5,6 @@ export const address: UIComponentFactory = ({ element }) => ({ element: 'SnapUIAddress', props: { address: element.props.address, - diameter: 16, + avatarSize: 'xs', }, }); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/avatar.ts b/ui/components/app/snaps/snap-ui-renderer/components/avatar.ts new file mode 100644 index 000000000000..9572516383b6 --- /dev/null +++ b/ui/components/app/snaps/snap-ui-renderer/components/avatar.ts @@ -0,0 +1,9 @@ +import { AvatarElement } from '@metamask/snaps-sdk/jsx'; +import { UIComponentFactory } from './types'; + +export const avatar: UIComponentFactory = ({ element }) => ({ + element: 'SnapUIAvatar', + props: { + address: element.props.address, + }, +}); diff --git a/ui/components/app/snaps/snap-ui-renderer/components/index.ts b/ui/components/app/snaps/snap-ui-renderer/components/index.ts index 5d3b8fa16789..17a9b6aa37c1 100644 --- a/ui/components/app/snaps/snap-ui-renderer/components/index.ts +++ b/ui/components/app/snaps/snap-ui-renderer/components/index.ts @@ -26,6 +26,7 @@ import { container } from './container'; import { selector } from './selector'; import { icon } from './icon'; import { section } from './section'; +import { avatar } from './avatar'; export const COMPONENT_MAPPING = { Box: box, @@ -38,6 +39,7 @@ export const COMPONENT_MAPPING = { Copyable: copyable, Row: row, Address: address, + Avatar: avatar, Button: button, FileInput: fileInput, Form: form,