1- import React , { useCallback , useMemo , useState } from 'react' ;
1+ import React , {
2+ useCallback ,
3+ useEffect ,
4+ useMemo ,
5+ useRef ,
6+ useState ,
7+ } from 'react' ;
28import { useSelector } from 'react-redux' ;
39import { Hex } from '@metamask/utils' ;
410import {
@@ -32,6 +38,12 @@ import { getImageForChainId } from '../../../../../selectors/multichain';
3238import { getURLHost , shortenAddress } from '../../../../../helpers/utils/util' ;
3339import Card from '../../../../ui/card' ;
3440import { useI18nContext } from '../../../../../hooks/useI18nContext' ;
41+ import { useCopyToClipboard } from '../../../../../hooks/useCopyToClipboard' ;
42+ import {
43+ getInternalAccountByAddress ,
44+ getNativeTokenInfo ,
45+ selectERC20TokensByChain ,
46+ } from '../../../../../selectors/selectors' ;
3547import {
3648 convertTimestampToReadableDate ,
3749 getPeriodFrequencyValueTranslationKey ,
@@ -42,10 +54,6 @@ import {
4254} from '../../../../../../shared/lib/gator-permissions' ;
4355import { PreferredAvatar } from '../../../../app/preferred-avatar' ;
4456import { BackgroundColor } from '../../../../../helpers/constants/design-system' ;
45- import {
46- getNativeTokenInfo ,
47- selectERC20TokensByChain ,
48- } from '../../../../../selectors/selectors' ;
4957import { getTokenMetadata } from '../../../../../helpers/utils/token-util' ;
5058import { getPendingRevocations } from '../../../../../selectors/gator-permissions/gator-permissions' ;
5159
@@ -122,6 +130,62 @@ export const ReviewGatorPermissionItem = ({
122130 getNativeTokenInfo ( state , chainId ) ,
123131 ) as TokenMetadata ;
124132 const pendingRevocations = useSelector ( getPendingRevocations ) ;
133+ const internalAccount = useSelector ( ( state ) =>
134+ getInternalAccountByAddress ( state , permissionAccount ) ,
135+ ) ;
136+
137+ // Copy functionality with visual feedback
138+ const [ accountText , setAccountText ] = useState (
139+ shortenAddress ( permissionAccount ) ,
140+ ) ;
141+ const [ addressCopied , setAddressCopied ] = useState ( false ) ;
142+ const [ copyIcon , setCopyIcon ] = useState ( IconName . Copy ) ;
143+ const [ copyMessage , setCopyMessage ] = useState ( accountText ) ;
144+
145+ const timeoutRef = useRef < number | null > ( null ) ;
146+ const [ , handleCopy ] = useCopyToClipboard ( ) ;
147+
148+ // Cleanup timeout when component unmounts
149+ useEffect ( ( ) => {
150+ return ( ) => {
151+ if ( timeoutRef . current ) {
152+ clearTimeout ( timeoutRef . current ) ;
153+ timeoutRef . current = null ;
154+ }
155+ } ;
156+ } , [ ] ) ;
157+
158+ useEffect ( ( ) => {
159+ if ( internalAccount ?. metadata ?. name ) {
160+ setAccountText ( internalAccount ?. metadata ?. name ) ;
161+ }
162+ } , [ internalAccount ] ) ;
163+
164+ // Update copy message when account changes
165+ useEffect ( ( ) => {
166+ setCopyMessage ( accountText ) ;
167+ } , [ accountText ] ) ;
168+
169+ // Handle copy button click
170+ const handleCopyClick = useCallback ( ( ) => {
171+ // Clear existing timeout if clicking multiple times
172+ if ( timeoutRef . current ) {
173+ clearTimeout ( timeoutRef . current ) ;
174+ }
175+
176+ setAddressCopied ( true ) ;
177+ handleCopy ( permissionAccount ) ;
178+ setCopyMessage ( t ( 'addressCopied' ) ) ;
179+ setCopyIcon ( IconName . CopySuccess ) ;
180+
181+ // Reset state after 1 second
182+ timeoutRef . current = window . setTimeout ( ( ) => {
183+ setCopyMessage ( accountText ) ;
184+ setCopyIcon ( IconName . Copy ) ;
185+ setAddressCopied ( false ) ;
186+ timeoutRef . current = null ;
187+ } , 1000 ) ;
188+ } , [ permissionAccount , accountText , handleCopy , t ] ) ;
125189
126190 const tokenMetadata : TokenMetadata = useMemo ( ( ) => {
127191 if ( tokenAddress ) {
@@ -483,10 +547,27 @@ export const ReviewGatorPermissionItem = ({
483547 < PreferredAvatar address = { permissionAccount } />
484548 < Text
485549 variant = { TextVariant . BodyMd }
486- color = { TextColor . TextAlternative }
550+ color = {
551+ addressCopied
552+ ? TextColor . SuccessDefault
553+ : TextColor . TextAlternative
554+ }
555+ data-testid = "review-gator-permission-account-name"
487556 >
488- { shortenAddress ( permissionAccount ) }
557+ { copyMessage }
489558 </ Text >
559+ < ButtonIcon
560+ iconName = { copyIcon }
561+ color = {
562+ addressCopied ? IconColor . SuccessDefault : IconColor . IconMuted
563+ }
564+ size = { ButtonIconSize . Sm }
565+ onClick = { handleCopyClick }
566+ ariaLabel = {
567+ addressCopied ? t ( 'copiedExclamation' ) : t ( 'copyToClipboard' )
568+ }
569+ data-testid = "review-gator-permission-copy-address"
570+ />
490571 </ Box >
491572 </ Box >
492573 </ Box >
0 commit comments